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
- Linux usb wifi驱动分析(一)
- Linux usb wifi驱动分析(二)
- Linux USB驱动框架分析(一)
- Linux USB驱动框架分析(一)
- Linux USB驱动框架分析(一)
- Linux下的USB总线驱动(一) USB驱动框架usb-skeleton.c分析
- Linux下的USB总线驱动(一) USB驱动框架usb-skeleton.c分析
- USB驱动分析(一)
- USB驱动分析(一)
- USB驱动分析(一)
- Linux USB驱动框架分析(一)(转)
- Linux USB驱动框架分析(一)
- Linux USB驱动框架分析(一)
- Linux USB 驱动开发实例(一) —— USB摄像头驱动实现源码分析
- Linux USB 驱动开发实例(一) —— USB摄像头驱动实现源码分析
- Linux USB 驱动开发实例(一) —— USB摄像头驱动实现源码分析
- LINUX USB驱动分析(3)-USB驱动分析
- linux WIFI驱动分析
- Android菜鸟练习第一课 调用系统裁剪功能裁剪图片上传服务器
- (二十一)内存溢出解决方法---学习笔记
- iOS 画虚线方法总结
- 一个合格的程序员应该读过哪些书
- java面试题
- Linux usb wifi驱动分析(一)
- java常见对象集合
- 上传图片file优化
- 验证是数字的 小数点后两位的
- MySQL允许远程授权
- solaris veritas_SF5.0
- linux下实时查看tomcat运行日志
- 只有dll的情况下如何动态调用里面的类成员函数
- 浅析分布式系统韩伟