Linux usb wifi驱动分析(一)

来源:互联网 发布:plc编程及应用第3版 编辑:程序博客网 时间:2024/05/01 15:32

最近做一个项目需要高速传输视频,但是USB WiFi驱动提供的驱动在开发板+Linux环境下速度达不到要求,需要优化USB WiFi驱动,所以认真分析下USB WiFi驱动。本次USB WiFi采用的是rtl8812驱动,在github已经realtek官网都可以下载到驱动源码。

1、USB WiFi 驱动架构是可以分为几个部分:

         ieee 802.1协议层USB 无线网卡驱动层USB 无线网卡硬件层

    ieee802.11 协议层

     Linux Kernel中有ieee802.11 协议子层,各个不同型号的硬件设备驱动程序都是实现ieee80211_ops 数据结构中的函数,例如打开是start()函数,发送是tx()函数,关闭是stop()函数,睡眠是suspend函数,唤醒是resume函数等。

     其代码位于: kernel/net/mac80211

    USB无线网卡驱动层

     由上图可见,USB无线网卡驱动层位于USB与802.11协议层之间,为了使其可正常工作,它必须搞好上下级关系:

     a) 向USB Core注册USB驱动,通过USB通道收发数据

     b) 向ieee802.11注册ieee80211_ops,以供ieee80211随时召唤,然后通过USB通道进行数据传输.



2、以realtek  rtl8812驱动为例:

realtek usb wifi驱动代码分为几个部分: 

USB WiFi驱动中驱动中既要作为USB 从设备又要作为网络设备,所以驱动中必须既要注册网络驱动、又要注册USB驱动, 先从USB注册开始:

        在os_dep/linux/usb_intf.c中, USB驱动结构体:

struct rtw_usb_drv {struct usb_driver usbdrv;int drv_registered;u8 hw_type;};struct rtw_usb_drv usb_drv = {.usbdrv.name =(char*)DRV_NAME,.usbdrv.probe = rtw_drv_init,.usbdrv.disconnect = rtw_dev_remove,.usbdrv.id_table = rtw_usb_id_tbl,.usbdrv.suspend = rtw_suspend,.usbdrv.resume = rtw_resume,#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)).usbdrv.reset_resume = rtw_resume,#endif#ifdef CONFIG_AUTOSUSPEND.usbdrv.supports_autosuspend = 1,#endif}; 

模块注册:
module_init(rtw_drv_entry);
注册USB 驱动:

static int __init rtw_drv_entry(void){       M_DBG("enter rtw_drv_entry!!!\n");#ifdef CONFIG_PLATFORM_RTK_DMP    u32 tmp;    tmp=readl((volatile unsigned int*)0xb801a608);    tmp &= 0xffffff00;    tmp |= 0x55;    writel(tmp,(volatile unsigned int*)0xb801a608);//write dummy register for 1055#endif#ifdef CONFIG_PLATFORM_ARM_SUNxI#ifndef CONFIG_RTL8723A    int ret = 0;    /* ----------get usb_wifi_usbc_num------------- */    ret = script_parser_fetch("usb_wifi_para", "usb_wifi_usbc_num", (int *)&usb_wifi_host, 64);    if(ret != 0){        DBG_8192C("ERR: script_parser_fetch usb_wifi_usbc_num failed\n");        ret = -ENOMEM;        return ret;    }    DBG_8192C("sw_usb_enable_hcd: usbc_num = %d\n", usb_wifi_host);    sw_usb_enable_hcd(usb_wifi_host);#endif //CONFIG_RTL8723A#endif //CONFIG_PLATFORM_ARM_SUNxI#ifdef CONFIG_PLATFORM_ARM_SUN6I    script_item_value_type_e type;        type = script_get_item("wifi_para", "wifi_usbc_id", &item);    if(SCIRPT_ITEM_VALUE_TYPE_INT != type){        printk("ERR: script_get_item wifi_usbc_id failed\n");        return -ENOMEM;    }        printk("sw_usb_enable_hcd: usbc_num = %d\n", item.val);    wifi_pm_power(1);    mdelay(10);    sw_usb_enable_hcd(item.val);#endif //CONFIG_PLATFORM_ARM_SUN6I        RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_entry\n"));    DBG_871X(DRV_NAME " driver version=%s\n", DRIVERVERSION);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))    //console_suspend_enabled=0;#endif    rtw_suspend_lock_init();    usb_drv.drv_registered = _TRUE;    return usb_register(&usb_drv.usbdrv);  //注册USB 驱动}


模块注册时调用probe函数:rtw_drv_init
static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid){    _adapter *if1 = NULL, *if2 = NULL;    int status;    struct dvobj_priv *dvobj;#ifdef CONFIG_MULTI_VIR_IFACES    int i;#endif //CONFIG_MULTI_VIR_IFACES    RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));    //DBG_871X("+rtw_drv_init\n");    //step 0.    process_spec_devid(pdid);    /* Initialize dvobj_priv */   //初始化USB    if ((dvobj = usb_dvobj_init(pusb_intf)) == NULL) {        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("initialize device object priv Failed!\n"));        goto exit;    }    if ((if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid)) == NULL) {        DBG_871X("rtw_usb_if1_init Failed!\n");        goto free_dvobj;    }#ifdef CONFIG_CONCURRENT_MODE    if((if2 = rtw_drv_if2_init(if1, usb_set_intf_ops)) == NULL) {        goto free_if1;    }#ifdef CONFIG_MULTI_VIR_IFACES    for(i=0; i<if1->registrypriv.ext_iface_num;i++)    {        if(rtw_drv_add_vir_if(if1, usb_set_intf_ops) == NULL)        {            DBG_871X("rtw_drv_add_iface failed! (%d)\n", i);            goto free_if2;        }    }   #endif //CONFIG_MULTI_VIR_IFACES#endif#ifdef CONFIG_INTEL_PROXIM    rtw_sw_export=if1;#endif#ifdef CONFIG_GLOBAL_UI_PID    if(ui_pid[1]!=0) {        DBG_871X("ui_pid[1]:%d\n",ui_pid[1]);        rtw_signal_process(ui_pid[1], SIGUSR2);    }#endif    //dev_alloc_name && register_netdev  //注册网络设备    if((status = rtw_drv_register_netdev(if1)) != _SUCCESS) {        goto free_if2;    }#ifdef CONFIG_HOSTAPD_MLME    hostapd_mode_init(if1);#endif#ifdef CONFIG_PLATFORM_RTD2880B    DBG_871X("wlan link up\n");    rtd2885_wlan_netlink_sendMsg("linkup", "8712");#endif#ifdef RTK_DMP_PLATFORM    rtw_proc_init_one(if1->pnetdev);#endif    RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-871x_drv - drv_init, success!\n"));    status = _SUCCESS;free_if2:    if(status != _SUCCESS && if2) {        #ifdef CONFIG_CONCURRENT_MODE        rtw_drv_if2_stop(if2);        rtw_drv_if2_free(if2);        #endif    }free_if1:    if (status != _SUCCESS && if1) {        rtw_usb_if1_deinit(if1);    }free_dvobj:    if (status != _SUCCESS)        usb_dvobj_deinit(pusb_intf);exit:    return status == _SUCCESS?0:-ENODEV;}



0 0
原创粉丝点击