基础知识
• cfg80211: 用于对无线设备进行配置管理。与FullMAC, mac80211和nl80211一起工作。(Kernel态)
• mac80211: 是一个driver开发者可用于为SoftMAC无线设备写驱动的框架 (Kernel态)。
• nl80211: 用于对无线设备进行配置管理,它是一个基本Netlink的用户态协议(User态)
• WNIC : Wireless Network Interface Controller, 它总是指望硬件执行协议(如IEEE802.11)描述的功能。
• MLME: 即MAC(Media Access Control ) Layer Management Entity,它管理物理层MAC状态机。
• SoftMAC: 其MLME由软件实现,mac80211为SoftMAC实现提供了一个driver API。 即:SoftMAC设备允许对硬件执行更好地控制,允许用软件实现对802.11的帧管理,包括解析和产生802.11无线帧。目前大多数802.11设备为SoftMAC,而FullMAC设备较少。
• FullMAC: 其MLME由硬件管理,当写FullMAC无线驱动时,不需要使用mac80211。
• wpa_supplicant: 是用户空间一个应用程序,主要发起MLME命令,然后处理相关结果。
备注:想fullmac是全部由硬件来实现的吧
工具软件
Linux Wifeless Extensions(lwe)
LWE 是linu下对无线网络配置的工具,包括内核的支持,用户层配置工具和驱动接口的支持三部分。
iwconfig
iwlist
iwpriv
and so on
专有名词:
essid: Extension Service Set ID
wpa_supplicant
wpa_supplicant本是开源项目源码,被谷歌修改后加入andriod移动平台,它主要思用来支持WEP,WPA/WPA2和WAPI无限协议和加密认证的,而实际上的工作内容是通过socket(不管wpa_supplicant与上层还是wpa_supplicant与驱动都采用socket通讯)与驱动交互上报数据给用户,而用户可以通过socket发送命令给wpa_supplicant调用驱动来对WIFI芯片操作。简单的说,wpa_supplicant就是WIFI驱动和用户的中转站外加对协议额加密认证的支持。
wpa_supplicant是核心程序,它和wpa_cli的关系就是服务和客户端的关系:后台运行wpa_supplicant,使用wpa_cli来搜索、设置、和连接网络。
命令格式:
wpa_supplicant [-BddhKLqqstuvW] [-P] [-g] \
-i -c [-C] [-D] [-p]\
[-b] [-f] \
[-o] [-O] \
[-N -i -c [-C] [-D] \
[-p] [-b] …]
linux下wifi模块接入网络的流程
在linux下该怎么进行网络的配置呢?去看看原来的的globalfish(垃圾代码,还起个怪名字)的代码吧,shit。看看看人家google :)
google貌似采用的也是wpa_supplicant,不过给wpa_supplicant添加了一个socket借口用来做配置。原生的代码貌似只有通过配置文件这种比较低级的方式(个人见解,还望指证)。
/*****************************************************************************************
*****globefish网络切换说明:
*
* 1、客户端关闭wifi启动AP功能后,拔掉网线,设备重启直接进入AP模式,供手机客户端直连,提供给
* 手机客户端点对点控制设备及搜索和设置设备wifi功能。
* 2、未插入网线状态下设备启动时,会首先检测当前是否处于AP状态,非AP状态则检查上一次保存的
* wifi是否可用,如果可以联通,则启动 wifi 连接; 否则,再搜索一次可用的wifi结点并保存,然
* 后设备启动AP模式,供手机客户端直连;此种情况下,设备启动后的15分钟内,每隔5分钟会再检
* 查一次wifi连接是否可用,可用则自动切换到 wifi 连接状态,连续检测三次仍不可用则停留于
* AP状态,用户可以在手机客户端通过AP连接重新配置设备的WIFI。
* 3、设备运行过程中,拔出网线时,会自动检查之前保存的wifi是否可以联通,以确定启用WIFI STA模
* 式还是AP模式;设备无论是在STA模式还是AP模式,插入网线则会直接切换为有线网络连接。
* 4、无RJ45网口的设备,则只有wifi station模式与wifi ap模式间的切换。
*****************************************************************************************/
int main(void)
{
printf("...............globefish start, ver: 10000200000 ...............\n");
pid_t pid;
static int fd = -1;
FILE *fp = NULL;
signal(SIGCHLD, SIG_DFL);
/**reconfig wireless configurations**/
Init_Wireless_Setting();
if (0 == g_DevWireless) //RJ45 existed.
{
/**capture signal while wire is inserted or extracted**/
signal(SIGUSR1, sig_handler);
signal(SIGUSR2, sig_handler);
pid = getpid();
itoa(pid);
//printf("char_pid =%s\n", g_PIDBuf);
fd = open(PATH_PID, O_RDWR | O_CREAT);
write(fd, g_PIDBuf, 8);
close(fd);
char tmpbuf[8] = {0};
fd = open(PATH_PID, O_RDWR);
read(fd, tmpbuf, 8);
//printf("read_pid =%s\n", tmpbuf);
close(fd);
sleep(2);
if ((0 == g_NetDevice) || (check_net_interface() <= 0)) //wire extracted.
{
g_NetDeviceOld = 0;
g_NetDevice = 0;
Change_to_WifiOrAP(); //enable ra0, AP or Sta.
}
else if ((1 == g_NetDevice) || (check_net_interface() > 0)) //wire inserted.
{
g_NetDeviceOld = 1;
g_NetDevice = 1;
Change_to_Wire_Connect(); //disable ra0, enable eth0 connection.
}
}
else if (1 == g_DevWireless) //wireless device without RJ45 interface.
{
GLOBEFISH_DBG_PRT(".........WIRELESS.........\n");
//system("ifconfig eth0 down");
g_NetDeviceOld = 0;
g_NetDevice = 0;
Change_to_WifiOrAP(); //enable ra0, AP or Sta.
}
int StatusCount = 0; //interface change state counter.
unsigned int CheckTime = 0; //recheck net state counter.
while(1)
{
sleep(2);
CheckTime += 2; //time counter.
//printf("...............g_SystemNetStatus:%d, StatusCount:%d, CheckTime:%d..................\n", g_SystemNetStatus, StatusCount, CheckTime);
if (g_NetDevice != g_NetDeviceOld) //net interface changed.
{
StatusCount++; //interface change status counter.
if (5 == StatusCount)
{
if (1 == g_NetDevice) //wire inserted.
{
Change_to_Wire_Connect(); //disable ra0, enable eth0 connection.
}
else if (0 == g_NetDevice) //wire extracted.
{
Change_to_WifiOrAP(); //disable eth0, enable ra0: station or AP.
}
g_NetDeviceOld = g_NetDevice;
StatusCount = 0; //reset connect status counter.
CheckTime = 0;
}
else
continue;
}
else //check status.
{
if (g_NetDevice == g_NetDeviceOld) //net interface changed.
{
StatusCount = 0; //reset connect status counter.
}
if ((1 == g_SystemNetStatus) || (2 == g_SystemNetStatus) || (5 == g_SystemNetStatus) || (CheckTime > 900)) //15min
{
if (CheckTime > 1000)
{
CheckTime = 0;
}
continue;
}
else if (3 == g_SystemNetStatus) //False AP.
{
if (CheckTime > 720) //12min later, stay in current state.
{
g_SystemNetStatus = 5;
continue;
}
if (0 == (CheckTime % 240)) //try to connect remote wifi every 4min.
{
Start_STA_Mode();
g_SystemNetStatus = 4; //wifi connecting status.
}
}
else if (4 == g_SystemNetStatus)//check remote wifi connection.
{
if (0 == (CheckTime % 30))
{
if (Check_WPACLI_Status(1) > 0) //check wpa_cli status.
{
g_SystemNetStatus = 5; //remote wifi is avilable, connecte it.
#if 0
char s_LocalIPAddr[16] = {0};
if (! GetLocalAddress("ra0", s_LocalIPAddr))
{
GLOBEFISH_DBG_PRT("...set local ip address: %s, len:%d\n", s_LocalIPAddr, strlen(s_LocalIPAddr));
conf_set("/mnt/sif/wifinet.cfg", "IPAddress", s_LocalIPAddr);
conf_set("/mnt/sif/wifinet.cfg", "SubnetMask", "255.255.255.0");
sleep(1);
}
#endif
Update_Net_Conf(INTERFACE_WIFI); //update wifinet.cfg
}
else //remote wifi disconnected.
{
g_SystemNetStatus = 3; //False AP mode.
if ( WifiScanForAP() ) //search wifi before change to AP mode.
{
fprintf(stderr, "wifi search result is empty !\n");
}
if (1 == g_APEnable)
{
Start_AP_Mode(); //change to AP.
}
if (CheckTime > 720)
{ //wifi is disconnected in 12min, then stay in AP mode.
g_SystemNetStatus = 2;
}
}
}
}
}
}
return 0;
}
如此low的一段代码。不过还好吧
wifi状态检查
只是检查连上了AP热点,至于连上外网没,没有做检查
int Check_WPACLI_Status(int interval)
{
int ConnectCnt = 0; //count for checking wifi connection status.
char cmdbuf[32] = {0}; //popen result buffer.
char wpaState_Key[16] = {0}; //wifi connection status: Key.
char wpaState_Value[32] = {0}; //wifi connection status: Value.
FILE *pfp = NULL;
GLOBEFISH_DBG_PRT(".........check time interval: %d.........\n", interval);
for (ConnectCnt = 0; ConnectCnt < interval; ConnectCnt++)
{
GLOBEFISH_DBG_PRT(".........connect count: %d.........\n", ConnectCnt);
pfp = popen("wpa_cli status", "r");
if (NULL == pfp)
{
fprintf(stderr, "popen failed with: %d, %s\n", errno, strerror(errno));
return -1;
}
/*parse status result to find if remote wifi is usable*/
fgets(cmdbuf, sizeof(cmdbuf), pfp); //first line, invalid.
while (fgets(cmdbuf, sizeof(cmdbuf), pfp))
{
cmdbuf[strlen(cmdbuf) - 1] = '\0'; //skip '\n' at the end of line.
memset(wpaState_Key, '\0', strlen(wpaState_Key));
memset(wpaState_Value, '\0', strlen(wpaState_Value));
sscanf(cmdbuf, "%[^=]=%[^'\n']", wpaState_Key, wpaState_Value);
//fprintf(stderr, "===> cmdbuf:%s, wpaState_Key:%s, wpaState_Value:%s\n", cmdbuf, wpaState_Key, wpaState_Value);
if ( (!strcmp(wpaState_Key, "wpa_state")) && (!strcmp(wpaState_Value, "COMPLETED")) )
{
return 1;
}
}
if (pfp)
{
pclose(pfp);
pfp = NULL;
}
//sleep(3);
}
return 0;
}
驱动源码分析
先盗个图,哈哈
参考:
http://blog.csdn.net/myarrow/article/details/9274443#t7