首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

请问:C代码基于wpa_supplicant怎么编写无线连接程序

2013-05-02 
请教:C代码基于wpa_supplicant如何编写无线连接程序各位大侠好,我是一个c代码新手目前需要制作一个无线连

请教:C代码基于wpa_supplicant如何编写无线连接程序
各位大侠好,我是一个c代码新手
目前需要制作一个无线连接程序,驱动什么的已经搞好了
目前我基于wpa_supplicant和wireless tools做了一个,感觉好像很别扭

首先,对于wpa_supplicant需要的配置文件,我使用fopen创建文件,把配置在一个字符串数组里组装好,然后fwrite到配置文件里,然后使用system执行 wpa_supplicant -B -iwlan0 -c/etc/wpa_supplicant.conf -Dwext 这样的命令来进行无线连接。

搜索过程,我就是使用system执行 iwlist ra0 scan >tmp_file,把结果写到文件里,fopen后,用ftell一句一句的分析,把需要的essid,加密方式这些参数提取出来

对于连接的情况,也是通过执行相关命令把命令结果存在文件中,然后fopen后,读出来检查。

因为没有参加太多的软件开发,所以,目前我只想了这么一个办法。

这个办法很别扭,如果完全都是正确的话,那直接就连接了,没什么问题。
但是如果wpa_supplicant命令执行错了,比如密码有问题等,没法反馈出来
特别是wep方式,密码错了,完全没有打印反馈回来的,我也没法准确的提示出连接正确还是错误。

特地来请教各位大侠,有没有更好的办法?我感觉我这个办法,那是相当的费时费力啊。。。

万分感谢了!!
[解决办法]
顶。是android环境还是linux环境呀?android下应该有参考源码呀。linux环境命令行模式下不懂怎么搞。
[解决办法]
可以把密码保存到一个文件,再和获取的密码比较啊,比较字符串还不会吗?
[解决办法]
基本就是LZ的做法了,可以根据需求慢慢改善。

[解决办法]
system执行 iwlis
[解决办法]
1. 使能 WIFI
2. 查找 AP
3. 配置 AP 参数
4. 连接
5. 配置 IP 地址
基本流程就这样吧。
[解决办法]
一、WIFI的基本架构
    1、wifi用户空间的程序和库:
         external/wpa_supplicant/
       生成库libwpaclient.so和守护进程wpa_supplicant。
    2、hardware/libhardware_legary/wifi/是wifi管理库。
    3、JNI部分:
         frameworks/base/core/jni/android_net_wifi_Wifi.cpp
    4、JAVA部分:
         frameworks/base/services/java/com/android/server/
         frameworks/base/wifi/java/android/net/wifi/ 
    5、WIFI Settings应用程序位于:
       packages/apps/Settings/src/com/android/settings/wifi/
二、WIFI在Android中如何工作
   Android使用一个修改版wpa_supplicant作为daemon来控制WIFI,代码位于
   external/wpa_supplicant。wpa_supplicant是通过socket与
   hardware/libhardware_legacy/wifi/wifi.c通信。UI通过android.net.wifi package
   (frameworks/base/wifi/java/android/net/wifi/)发送命令给wifi.c。
   相应的JNI实现位于frameworks/base/core/jni/android_net_wifi_Wifi.cpp。
   更高一级的网络管理位于frameworks/base/core/java/android/net。
三、配置Android支持WIFI
   在BoardConfig.mk中添加:
      BOARD_HAVE_WIFI := true
      BOARD_WPA_SUPPLICANT_DRIVER := WEXT
   这将在external/wpa_supplicant/Android.mk设置WPA_BUILD_SUPPLICANT为true,
   默认使用驱动driver_wext.c。
   如果使用定制的wpa_supplicant驱动(例如 madwifi),可以设置:
       BOARD_WPA_SUPPLICANT_DRIVER := MADWIFI
四、使能wpa_supplicant调试信息
   默认wpa_supplicant设置为MSG_INFO,为了输出更多信息,可修改:
   1、在common.c中设置wpa_debug_level = MSG_DEBUG;
   2、在common.c中把#define wpa_printf宏中的
      if ((level) >= MSG_INFO)
      改为
      if ((level) >= MSG_DEBUG)


 
五、配置wpa_supplicant.conf
   wpa_supplicant是通过wpa_supplicant.conf中的ctrl_interface=来指定控制socket的,应该在
   AndroidBoard.mk中配置好复制到$(TARGET_OUT_ETC)/wifi(也就是
   /system/etc/wifi/wpa_supplicant.conf)
   这个位置会在init.rc中再次检测的。
   一般的wpa_supplicant.conf配置为:
      ctrl_interface=DIR=/data/system/wpa_supplicant GROUP=wifi
      update_config=1
      fast_reauth=1  
   有时,驱动需要增加:
      ap_scan=1
   如果遇到AP连接问题,需要修改ap_scan=0来让驱动连接,代替wpa_supplicant。
   如果要连接到non-WPA or open wireless networks,要增加:
      network={
              key_mgmt=NONE
      }
六、配置路径和权限
    Google修改的wpa_supplicant要运行在wifi用户和组下的。代码可见wpa_supplicant/os_unix.c
   中的os_program_init()函数。   如果配置不对,会出现下面错误:
      E/WifiHW  (  ): Unable to open connection to supplicant on 
      "/data/system/wpa_supplicant/wlan0": No such file or directory will appear.
   确认init.rc中有如下配置:
       mkdir /system/etc/wifi 0770 wifi wifi
       chmod 0770 /system/etc/wifi
       chmod 0660 /system/etc/wifi/wpa_supplicant.conf
       chown wifi wifi /system/etc/wifi/wpa_supplicant.conf
       # wpa_supplicant socket
       mkdir /data/system/wpa_supplicant 0771 wifi wifi
       chmod 0771 /data/system/wpa_supplicant
       #wpa_supplicant control socket for android wifi.c
       mkdir /data/misc/wifi 0770 wifi wifi
       mkdir /data/misc/wifi/sockets 0770 wifi wifi
       chmod 0770 /data/misc/wifi
       chmod 0660 /data/misc/wifi/wpa_supplicant.conf
   如果系统的/system目录为只读,那应该使用路径/data/misc/wifi/wpa_supplicant.conf。
七、运行wpa_supplicant和dhcpcd
   在init.rc中确保有如下语句:
      service wpa_supplicant /system/bin/logwrapper /system/bin/wpa_supplicant -dd 
                   -Dwext -iwlan0 -c /data/misc/wifi/wpa_supplicant.conf
         user root
         group wifi inet
      socket wpa_wlan0 dgram 660 wifi wifi
         oneshot
      service dhcpcd /system/bin/logwrapper /system/bin/dhcpcd -d -B wlan0
         disabled
         oneshot
 
   根据所用的WIFI驱动名字,修改wlan0为自己驱动的名字。
   
七、编译WIFI驱动为module或kernel built in
 


   1、编译为module
      在BoardConfig.mk中添加:
         WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/ar6000.ko"
         WIFI_DRIVER_MODULE_ARG := ""  #for example nohwcrypt
         WIFI_DRIVER_MODULE_NAME := "ar6000"  #for example wlan0 
         WIFI_FIRMWARE_LOADER := ""         
   2、编译为kernel built in  
     1)在hardware/libhardware_legacy/wifi/wifi.c要修改interface名字,
     2)在init.rc中添加:
        setprop wifi.interface "wlan0"
     3)在hardware/libhardware_legacy/wifi/wifi.c中当insmod/rmmod时,
        直接return 0。
八、WIFI需要的firmware
   Android不使用标准的hotplug binary,WIFI需要的firmware要复制到/etc/firmware。   或者复制到WIFI驱动指定的位置,然后WIFI驱动会自动加载。
 
九、修改WIFI驱动适合Android
   Google修改的wpa_supplicant要求SIOCSIWPRIV ioctl发送命令到驱动,及接收信息,例如signal 
   strength, mac address of the AP, link speed等。所以要正确实现WIFI驱动,需要从
   SIOCSIWPRIV ioctl返回RSSI (signal strength)和MACADDR信息。
   如果没实现这个ioctl,会出现如下错误:
     E/wpa_supplicant(  ): wpa_driver_priv_driver_cmd failed 
                               wpa_driver_priv_driver_cmd RSSI len = 4096 
     E/wpa_supplicant(  ): wpa_driver_priv_driver_cmd failed 
     D/wpa_supplicant(  ): wpa_driver_priv_driver_cmd LINKSPEED len = 4096
     E/wpa_supplicant(  ): wpa_driver_priv_driver_cmd failed 
     I/wpa_supplicant(  ): CTRL-EVENT-DRIVER-STATE HANGED

十、设置dhcpcd.conf
   一般/system/etc/dhcpcd/dhcpcd.conf的配置为:
      interface wlan0
      option subnet_mask, routers, domain_name_servers 

[解决办法]
我来说一下吧..不知道你那行不行,不过应该是一样的....当你的密码啥啥的,都正确的时候,那么你建立socket之后,你可以用ioctl获取到网卡的信息,里面就有关于连接是否成功的数据,连接完成...
typedef enum {
    WPA_DISCONNECTED,        // Disconnected state
    WPA_INACTIVE,            // Inactive state (wpa_supplicant disabled)
    WPA_SCANNING,            // Scanning for a network
    WPA_ASSOCIATING,         // Trying to associate with a BSS/SSID
    WPA_ASSOCIATED,          // Association completed
    WPA_4WAY_HANDSHAKE,      // WPA 4-Way Key Handshake in progress
    WPA_GROUP_HANDSHAKE,     // WPA Group Key Handshake in progress


    WPA_COMPLETED,           // All authentication completed
} wpa_states;

这部分是获取AP的信号强度
struct iwreq iwr;
memset(&iwr, 0, sizeof(iwr));
strlcpy(iwr.ifr_ifrn.ifrn_name, ifname, sizeof(iwr.ifr_ifrn.ifrn_name) - 1);
iwr.u.data.pointer = (caddr_t) stats;
iwr.u.data.length = sizeof(*stats);
iwr.u.data.flags = 1;
ret = ioctl(sock, SIOCGIWSTATS, &iwr);
[解决办法]
我做了一套WIFI的接口,通过SOCKET与WPA_SUSPPLICANT通信,当连接后,不管成功与否,直接发STATUS给WPA_SUSPPLICANT获取状态, 然后就能判断是否连接上了。 ASSOCIATING-》ASSOCIATED-》4WAY_HANDSHAKE-》GROUP_HANDSHAKE-》COMPLETED这就是它连接过程中的状态变化过程。你如果密码失败,在四次握手的阶段就会失败了。
[解决办法]

引用:
这个问题目前我想到一个办法,参照安卓的无线实现部分
直接把wpa_supplicant加到代码里面,调用它的接口
不过目前还没实现成功,把wpa_supplicant放到自己的代码里面编到一起,没那么容易。。。

你觉得难点在哪?参照android的做法,你的wpa_supplicant会编成一个可执行文件,你开两个socket一个下命令一个监控。如果你只要求使用wpa_supplicant来连接和断开wifi的话其实不难,难的是对于网络出错或者验证出错的处理。
[解决办法]
如果移植wpa_suppliacant源码困难的话,不妨试试下面官方提倡的做法:

来自于wpa_supplicant-devel文档
3、控制接口
wpa_supplicant实现了一个由外部程序使用来控制wpa_supplicant守护程序操作和得到状态信息和事件通知的控制接口。有一个单独文件的小C库wpa_ctrl.c提供辅助函数来方便使用这个控制接口。外部程序可以把这个文件链接到他们并使用wpa_ctrl.h中提供的函数来与wpa_supplicant交互。这个库也可以被C++使用。wpa_cli.c和wpa_gui 是使用这个库的实例。
[解决办法]
wpa_supplicant编译生成wpa_supplicant和wpa_cli时,
编译过程会生成每个文件的.o文件,
用ar -rsv libwpa.a wpa_supplicant.o ctrl_interface.o driver_wext.o ....就可以生成静态链接库.a。
用gcc -fPIC -shared 生成动态链接库.so。

后面的,你懂得。。。。

热点排行