该模块为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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/dxt1107/article/details/47807379