您的位置:首页 > 其它

7620a无线中继模块(wisp)

2015-08-20 14:32 471 查看
该模块为7620a无线中继模块,支持自动扫描,自动拨号,支持中文ssid配置(需要编解码模块支持)

无线驱动需要增加wifi断开和连接信号发送,用于应用层处理事件。

该模块仅供参考,如有问题,可以联系我。

/*
* wisp.c
* 7620a无线中继模块,支持自动重拨,支持中文ssid
* Author:dxt1107
* Mail:destan19@126.com
* 2014.12.04
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <bcmnvram.h>
#include <shutils.h>
#include <ralink.h>
#include <bcmutils.h>
#include <etioctl.h>
#include <bcmparams.h>
#include <linux/autoconf.h>
#include <signal.h>
#include "encode.h"
#define WISP_IFNAME "apcli0"

#define STAT_LINK_DOWN 0
#define STAT_LINK_UP 1
#define SIG_APCLI_LINKDOWN SIGUSR2 + 20  // 37
#define SIG_APCLI_LINKUP   SIGUSR2 + 21  // 38
#define SIG_WISP_DEBUG     SIGUSR2 + 22  // 39
#define SCAN_INTERVAL 3
#define CHECK_NETWORK_INTERVAL 180
#define DIAGNOSE_INTERVAL 16
static int wisp_debug = 0;

#define WDBG(fmt,args...) if (wisp_debug)\
printf("dxt1107\033[0;32;32m%s,%d "fmt"\033[m",__func__,__LINE__,##args);

struct wifi_node_t{
struct wifi_node_t * next;
char ssid[64];
char bssid[32];
char auth_mode[32];
char encrypt_type[32];
char w_mode[16];
int signal;
int channel;
};
typedef enum wifi_status
{
STATUS_INIT = 0,
STATUS_AUTH_OK,
STATUS_CONNECTED_OK,
STATUS_INTERNET_OK,
}E_WIFI_STATUS;
struct wifi_node_t * wifi_head = NULL;
struct wifi_node_t g_cur_connect_wifi;
static int g_wifi_node_count = 0;
E_WIFI_STATUS  g_wifi_status = STATUS_INIT;

static void update_wifi_status(E_WIFI_STATUS status)
{
char buf[16] = {0};
if ( status < STATUS_INIT || status > STATUS_INTERNET_OK ) {
printf("error,invalid status,%d\n",status);
return;
}
g_wifi_status = status;
sprintf(buf, "%d", status);
nvram_set("wisp_status",buf);
}

void show_all_wifi_node(void)
{
if (!wisp_debug)
return;
printf("dxt1107###########begin show wifi list###############\n");
int i = 0;
struct wifi_node_t * p = wifi_head;
while ( p ) {
i++;
printf("%d ssid:%s,bssid:%s,channel:%d,mode:%s,signal:%d\n",
i, p->ssid,p->bssid,p->channel,p->auth_mode,p->signal);
p = p->next;
}
printf("dxt1107###########end show wifi list###############\n");

}

void show_one_wifi_node(struct wifi_node_t * p )
{
if ( !p )
return;
printf("dxt1107###ssid:%s,bssid:%s,channel:%d,mode:%s,signal:%d###\n",
p->ssid,p->bssid,p->channel,p->auth_mode,p->signal);
}
int  add_wifi_node(struct wifi_node_t * item)
{
if ( NULL == item )
return 0;
item ->next = NULL;
if ( wifi_head == NULL ){
wifi_head = item;
}
else{
item->next = wifi_head->next;
wifi_head->next = item;
}
g_wifi_node_count ++;
return 1;
}

void  del_wifi_node(struct wifi_node_t * item)
{
struct wifi_node_t * p = wifi_head;
struct wifi_node_t * prev = wifi_head;
if ( NULL == item )
return ;
if ( wifi_head == NULL ){
return ;
}
else{
while ( p ) {
if ( !strcmp ( p->bssid , item->bssid) &&
p->channel == item->channel) {
if ( NULL == prev->next )
wifi_head = NULL;
else {
prev->next = p->next;
}
g_wifi_node_count--;
WDBG("dxt1107bssid:%s,ssid:%s,channel:%d,cur_count:%d\n",\
p->bssid,p->ssid,p->channel,g_wifi_node_count);
free(p);
return;
}
prev = p;
p = p->next;
}
}
}

void clear_wifi_list(void)
{
struct wifi_node_t * p = wifi_head, * tmp = NULL;
while ( p ) {
tmp = p->next;
free (p);
p = tmp;
}
wifi_head = NULL;
g_wifi_node_count = 0;
}

static void
wisp_signal(int sig)
{
char   signal[] = "XXXX";
int pid;
if (sig == SIG_APCLI_LINKDOWN) {
WDBG("dxt1107###########wisp link down#############\n");
if (pids("udhcpc"))
{
snprintf(signal, sizeof(signal), "-%d", SIGUSR2);
eval("killall", signal, "udhcpc");
usleep(9000);
}
sleep(1);
if (pids("udhcpc"))
{
eval("killall", "-SIGTERM", "udhcpc");
usleep(9000);
}
unlink("/tmp/udhcpc");
printf("[%d] ssid:%s,channel:%d,change status %d==>%d\n",\
__LINE__,g_cur_connect_wifi.ssid,\
g_cur_connect_wifi.channel,g_wifi_status,STATUS_INIT);
update_wifi_status(STATUS_INIT);

}
else if (sig == SIG_APCLI_LINKUP) {
WDBG("dxt1107###########wisp link up#############\n");

if (g_wifi_status >= STATUS_CONNECTED_OK)
return;
symlink( "/sbin/rc", "/tmp/udhcpc" );
char *wan_hostname = nvram_safe_get("wan_hostname");
char *dhcp_argv[] = {
"udhcpc",
"-i", WISP_IFNAME,
"-p", "/var/run/udhcpc_wan.pid",
"-s", "/tmp/udhcpc",
wan_hostname && *wan_hostname ? "-H" : NULL,
wan_hostname && *wan_hostname ? wan_hostname : NULL,
NULL };

int dhcpret = 0, trycount = 3;

while (trycount != 0)
{
dhcpret = _eval_udhcpc(dhcp_argv, NULL, 0, &pid);
if ((-3) == dhcpret) {
trycount -= 1;
dprintf( "## Pull dhcp process fails, retry three times pulled.\n" );
usleep(2000);
} else {
break;
}
}
WDBG("[%d] ssid:%s,channel:%d,change status %d==>%d\n",\
__LINE__,g_cur_connect_wifi.ssid,
g_cur_connect_wifi.channel,g_wifi_status,STATUS_AUTH_OK);
update_wifi_status(STATUS_AUTH_OK);

}
else if ( sig == SIG_WISP_DEBUG )
{

wisp_debug = (wisp_debug == 1)?0:1;
show_all_wifi_node();
printf("ssid:%s,bssid:%s,channel:%d,status:%d,count:%d\n",
g_cur_connect_wifi.ssid,g_cur_connect_wifi.bssid,
g_cur_connect_wifi.channel,g_wifi_status,
g_wifi_node_count);
}
}

void hex_to_str(unsigned char * str,unsigned char *hex){
unsigned char *p = hex;
unsigned char *p_dst = str;
unsigned char tmp[8]={0};
strcpy(p_dst,"0x");
p_dst+=2;
while(*p)
{
memset(tmp,0x0,sizeof(tmp));
sprintf(tmp,"%X",*p);
memcpy(p_dst,tmp,2);
p_dst+=2;
p++;
}
}

void my_trim(char *s)
{
size_t len = strlen(s);
size_t lws;

/* trim trailing whitespace */
while (len && isspace(s[len-1]))
--len;

/* trim leading whitespace */
if (len) {
lws = strspn(s, " \n\r\t\v");
if (lws) {
len -= lws;
memmove(s, s + lws, len);
}
}
s[len] = '\0';
}

/*
* Function: parse_auth_encrypt
* Description:
* Input: auth_encrypt
* Output: auth_mode, encrypt_type
* Return: none
* Author: dxt1107
*/

void parse_auth_encrypt(char *auth_encrypt,
char * auth_mode,
char *encrypt_type)
{
char *p = NULL;
char auth_encrypt_buf[64] = {0};
strcpy(auth_encrypt_buf,auth_encrypt);

if ( 0 == memcmp(auth_encrypt_buf,"NONE",4)) {
strcpy(auth_mode, "OPEN");
strcpy(encrypt_type, "NONE" );
}
else if ( 0 == memcmp(auth_encrypt_buf,"WEP",3)) {
strcpy (auth_mode, "WEPAUTO");
strcpy(encrypt_type, "WEP" );
}
else {
p = strtok (auth_encrypt_buf, "/");
if ( !p ) {
printf("invalid type:%s\n",auth_encrypt);
return;
}
strcpy ( auth_mode, p);
p = strtok (NULL, "/");
if ( !p ) {
return;
}
strcpy ( encrypt_type, p);
if ( 0 == memcmp ( auth_mode, "WPA1PSKWPA2PSK",14)) {
strcpy(auth_mode,"WPA2PSK");
}
}
}

void update_wifi_list()
{
char  channel[8];
char  ssid[64];
char  bssid[32];
char  auth_mode[32];
char  encrypt_type[32];
char  auth_encrypt[64];
char  cmd_buf[256] = {0};
char  signal[16] = {0};
char  w_mode[16] = {0};
char  * conf_ssid = NULL;
char  * conf_ae = NULL;
char ssid_buf[128] = {0};
struct wifi_node_t * new_node = NULL;
FILE *fp = NULL;
conf_ssid = nvram_safe_get( "wisp_ssid" );
WDBG("conf_ssid:%s\n",conf_ssid);
conf_ae = nvram_safe_get( "wisp_auth_encrypt" );
if ( !conf_ssid || !strlen (conf_ssid)) {
printf("error,wisp_ssid not set.");
return;
}

if ( !conf_ae || !strlen (conf_ae)) {
printf("error,auth_encrypt not set.");
return;
}
if ( is_cn_encode(conf_ssid)) {
hex_to_str(ssid_buf,conf_ssid);
}
else {
strcpy(ssid_buf,conf_ssid);
}

do_system( "iwpriv "WISP_IFNAME" set SiteSurvey=1",wisp_debug);
sleep(4);
sprintf(cmd_buf,"iwpriv ra0 get_site_survey");
fp = popen(cmd_buf,"r");
if (!fp) {
return;
}
if ( NULL != wifi_head ) {
clear_wifi_list();
}
fgets(cmd_buf,sizeof(cmd_buf),fp);
fgets(cmd_buf,sizeof(cmd_buf),fp);

while (fgets(cmd_buf,sizeof(cmd_buf),fp) ) {
memset (encrypt_type,0x0,sizeof(encrypt_type));
memset (auth_mode,0x0,sizeof(auth_mode));
memset(channel,0x0,sizeof(channel));
memset(bssid,0x0,sizeof(bssid));
memset(ssid,0x0,sizeof(ssid));
memset(w_mode,0x0,sizeof(w_mode));
memset(signal,0x0,sizeof(signal));
memset(auth_encrypt,0x0,sizeof(auth_encrypt));

memcpy(channel,cmd_buf,4);
my_trim(channel);

memcpy(ssid,cmd_buf+4,64);
my_trim(ssid);
WDBG("ssid=%s,%s--\n",ssid_buf,ssid);

memcpy(bssid,cmd_buf+69,20);
my_trim(bssid);
memcpy(auth_encrypt,cmd_buf+89,23);
my_trim(auth_encrypt);
memcpy(signal,cmd_buf+112,9);
my_trim(signal);
memcpy(w_mode,cmd_buf+121,8);
my_trim(w_mode);

if ( strcmp(ssid_buf,ssid)
|| atoi(channel) <= 0 ) {
continue;
}
parse_auth_encrypt(auth_encrypt,auth_mode,encrypt_type);

new_node = (struct wifi_node_t *) malloc (sizeof(struct wifi_node_t));
if ( NULL == new_node ) {
printf("malloc wifi_node error!\n");
continue;
}
new_node->next = NULL;
new_node->channel = atoi(channel);
new_node->signal = atoi(signal);
strcpy(new_node->bssid,bssid);
strcpy(new_node->ssid,ssid);
strcpy(new_node->auth_mode,auth_mode);
strcpy(new_node->encrypt_type,encrypt_type);
add_wifi_node(new_node);
}
pclose(fp);
}

void wisp_init_config(void)
{
char   cmd_buf[128] = {0};
do_system("ifconfig "WISP_IFNAME" up", wisp_debug );

sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWispPid=%d",0 );
do_system(cmd_buf , wisp_debug );
do_system( "iwpriv  "WISP_IFNAME" set ApCliAuthMode=" , wisp_debug );
do_system("iwpriv  "WISP_IFNAME" set ApCliEncrypType=" , wisp_debug );
do_system("iwpriv  "WISP_IFNAME" set Channel=" , wisp_debug );
do_system("iwpriv  "WISP_IFNAME" set ApCliEnable=1", wisp_debug);
nvram_set("wan_ifname", WISP_IFNAME);
}

void connect_wifi(struct wifi_node_t * wifi_node)
{
char * password;
char * ssid;

char   cmd_buf[128] = {0};
do_system("iwpriv  "WISP_IFNAME" set ApCliEnable=0", 0);

sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWispPid=%d",0 );
do_system(cmd_buf , wisp_debug );

sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set Channel=%d", wifi_node->channel);
do_system(cmd_buf , wisp_debug );
sleep(5);

ssid = nvram_safe_get( "wisp_ssid" );
sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliSsid='%s'",ssid);
do_system(cmd_buf ,wisp_debug );

password =  nvram_safe_get( "wisp_password");

if ( 0 == memcmp( wifi_node->encrypt_type, "WEP",3)) {
sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliDefaultKeyID=%d",1 );
do_system(cmd_buf , wisp_debug );
sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliKey1=%s",password );
do_system(cmd_buf , wisp_debug );
}
else {
sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWPAPSK=%s",password );
do_system(cmd_buf , wisp_debug );
}

sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWispPid=%d",getpid() );
do_system(cmd_buf , wisp_debug );

sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliAuthMode=%s",wifi_node->auth_mode);
do_system(cmd_buf , wisp_debug );
sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliEncrypType=%s",\
wifi_node->encrypt_type);
do_system(cmd_buf , wisp_debug );
do_system("iwpriv  "WISP_IFNAME" set ApCliEnable=1", 0);
}

static char ping_domain[][32] ={
{"www.baidu.com"},
{"www.126.com"},
{""},
};

int check_internet(void)
{
int i;
char read_buf[256] = {0};
int len = 0;
FILE * fp  = NULL;
char cmd_buf[128] = {0};
struct hostent *p = NULL;
for (i = 0;strlen(ping_domain[i])> 0;i++){
p = gethostbyname(ping_domain[i]);
if (!p)
{
WDBG("get host name failed.%s\n",ping_domain[i]);
continue;
}
sprintf(cmd_buf,"ping %s -c 4",ping_domain[i]);
fp = popen(cmd_buf,"r");
if ( !fp ) {
continue;
}
len = fread(read_buf,1, sizeof(read_buf), fp);
if ( strstr(read_buf, "64 bytes from") && !strstr(read_buf,nvram_safe_get("wan_gateway"))) {
WDBG("ping success.%s\n",ping_domain[i]);
pclose(fp);
return 1;
}
pclose(fp);
}
return 0;
}

/*
* function:update_wifi_info
* desc:用于页面获取连接信息
* author:dxt1107
* date:2014.12.08
*/
void update_wifi_info(const struct wifi_node_t * p)
{
char buf[32] = {0};
sprintf(buf, "%d", p->signal);
nvram_set("wisp_signal",buf);
nvram_set("wisp_bssid",p->bssid);
sprintf(buf, "%d", p->channel);
nvram_set("wisp_channel",buf);
WDBG("wisp_signal:%d,bssid:%s,channel:%d\n",p->signal,p->bssid,p->channel);
}

void check_wisp_status(void)
{
int sleep_ct = 0;
int wifi_count = 0;
struct wifi_node_t * p_wifi = wifi_head;

while ( p_wifi ) {
wifi_count ++;
update_wifi_status(STATUS_INIT);
WDBG("connecting {%s,%s,%d}..........%d\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel,wifi_count);
memcpy(&g_cur_connect_wifi,p_wifi,sizeof(struct wifi_node_t));

update_wifi_info(&g_cur_connect_wifi);
connect_wifi(p_wifi);
sleep_ct = 0;
while (sleep_ct < 20 && g_wifi_status < STATUS_AUTH_OK ) {
sleep(1);
sleep_ct ++;
}
if ( STATUS_AUTH_OK == g_wifi_status ) {
WDBG("{%s,%s,%d} auth ..............ok\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);

sleep_ct = 0;
while (sleep_ct < 20 && !nvram_match("wan_status", "Connected") ) {
sleep(1);
sleep_ct ++;
}

if (nvram_match("wan_status", "Connected")){
printf("[%d] ssid:%s,channel:%d,change status %d==>%d\n",__LINE__,g_cur_connect_wifi.ssid,
g_cur_connect_wifi.channel,STATUS_AUTH_OK,STATUS_CONNECTED_OK);
update_wifi_status(STATUS_CONNECTED_OK);
WDBG("{%s,%s,%d} connect ..............ok\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
sleep_ct = 0;
while (sleep_ct < 2 ) {
if (check_internet()) {
WDBG("{%s,%s,%d} connect internet ..............ok\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);

update_wifi_status(STATUS_INTERNET_OK);

return;
}
sleep(15);
sleep_ct ++;
}
WDBG("{%s,%s,%d} connect internet ..............failed\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
}
else
WDBG("{%s,%s,%d} lease ip ..............failed\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
}
p_wifi = p_wifi->next;
}
}

void check_wifi_list_change(void)
{
if ( strlen(g_cur_connect_wifi.ssid) > 0) {
WDBG("##### current scan result #########\n");
show_all_wifi_node();
WDBG("last time connect wifi:\n");
show_one_wifi_node(&g_cur_connect_wifi);
del_wifi_node(&g_cur_connect_wifi);
}
}

void diagnose_network(void)
{
char *wan_ip = NULL;
switch ( g_wifi_status ) {
case STATUS_CONNECTED_OK:
wan_ip = nvram_safe_get("wan_ipaddr");
if ( (NULL == wan_ip || strlen(wan_ip) < 7 )
&& nvram_match("wan_status", "Connected")) {
nvram_set("wan_status","Disconnected");
update_wifi_status(STATUS_INIT);
printf("diagnose network .........success.\n");
}
default:
break;
}
}
int main(int argc,char *argv[])
{
int loop_time = 0;
memset(&g_cur_connect_wifi,0x0,sizeof(g_cur_connect_wifi));
update_wifi_status(STATUS_INIT);
nvram_set("wan_status","Disconnected");
wisp_init_config();
signal(SIG_APCLI_LINKDOWN, wisp_signal);
signal(SIG_APCLI_LINKUP, wisp_signal);
signal(SIG_WISP_DEBUG, wisp_signal);
signal(SIGCHLD, SIG_IGN);

while(1){
WDBG("loop time:%d,status:%d,count:%d\n",loop_time, g_wifi_status,g_wifi_node_count);

if ( STATUS_AUTH_OK <= g_wifi_status ) {
if (!nvram_match("wan_status", "Connected")){
update_wifi_status(STATUS_AUTH_OK);
}
else {
update_wifi_status(STATUS_CONNECTED_OK);
}
}

if ( STATUS_CONNECTED_OK <= g_wifi_status ) {
if (!check_internet()) {
update_wifi_status(STATUS_CONNECTED_OK);
}
else {
update_wifi_status(STATUS_INTERNET_OK);
sleep(CHECK_NETWORK_INTERVAL);
continue;
}
}

if ( loop_time > 3) {
sleep(10);
}
if ( 0 ==  loop_time % DIAGNOSE_INTERVAL )
diagnose_network();

if ( loop_time < 3 || 0 == (loop_time % SCAN_INTERVAL) ) {
WDBG("dxt1107 begin scan ssid........\n");
update_wifi_list();
if ( g_wifi_node_count > 1) {
check_wifi_list_change();
}
if ( (g_wifi_status < STATUS_CONNECTED_OK
&& 1 == g_wifi_node_count )
|| g_wifi_node_count > 1) {
update_wifi_status(STATUS_INIT);
check_wisp_status();
}
}
loop_time++;
if ( loop_time > 0xffff )
loop_time = 1;

}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: