linux usb wifi 代码,Linux USB-Wifi Driver

1. USB设备枚举过程

设备在插入USB 接口到设备成功找到它自己的驱动这一过程为:当把USB 设备插到USB 接口上后,USB

中央控制器会检测到有设备插入USB 接口了,Linux 内核会给设备分配一个数据结构来代表这个设备,Linux 会分配一个struct

usb_device 数据结构来代表该设备,该数据结构记录设备的一些属性及数据。并把该数据结构挂载到一个全局的USB 设备链上。在这一期间主机通过0

号端点得知了设备的一些信息,并知道了设备的厂家号和产品号。然后到一个全局的USB

驱动链上查找(通过调用驱动的probe函数来询问),看看哪个驱动程序支持的设备列表中有该设备的厂家号和产品号。当找到后设备就和驱动匹配上了。

2. 关键数据结构

1) struct

cfg80211_ops :backend description for

wireless configuration

2) struct wiphy:wireless hardware description

3) struct ieee80211_ops:callbacks from

mac80211 to the driver

4) struct ieee80211_hw:hardware

information and state

5) struct ieee80211_channel:channel

definition

6) struct usb_driver:identifies USB

interface driver to usbcore

3.

USB-Wifi驱动架构

USB-Wifi驱动架构如下图所示:

a4c26d1e5885305701be709a3d33442f.png

1) ieee802.11 协议层

Linux Kernel中有ieee802.11 协议子层,各个不同型号的硬件设备驱动程序都是实现ieee80211_ops

数据结构中的函数,例如打开是start()函数,发送是tx()函数,关闭是stop()函数,睡眠是suspend函数,唤醒是resume函数等。

其代码位于: kernel/net/mac80211

2) USB无线网卡驱动层

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

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

b)

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

3.1 向USB

Core注册USB驱动

向USB Core注册USB驱动,通过USB通道收发数据,如我的代码为:

kernel/drivers/net/wireless/ath/ath9k/hif_usb.c

staticstructusb_driver ath9k_hif_usb_driver = {//USB 驱动

.name = KBUILD_MODNAME,

.probe = ath9k_hif_usb_probe,

.disconnect = ath9k_hif_usb_disconnect,

#ifdef CONFIG_PM

.suspend = ath9k_hif_usb_suspend,

.resume = ath9k_hif_usb_resume,

.reset_resume = ath9k_hif_usb_resume,

#endif

.id_table = ath9k_hif_usb_ids,

.soft_unbind = 1,

};

intath9k_hif_usb_init(void)

{

returnusb_register(&ath9k_hif_usb_driver);// 把driver注册到USB驱动链中

}

voidath9k_hif_usb_exit(void)

{

usb_deregister(&ath9k_hif_usb_driver); // 把driver从USB驱动链中删除

}

3.2

向ieee802.11注册ieee80211_ops

向ieee802.11注册ieee80211_ops,以供ieee80211随时召唤,然后通过USB通道进行数据传输,如我的代码为:

在kernel/drivers/net/wireless/ath/ath9k/htc_drv_main.c中定义了ath9k_htc_ops,其详细定义如下:

structieee80211_ops ath9k_htc_ops = {

.tx = ath9k_htc_tx,

.start = ath9k_htc_start,

.stop = ath9k_htc_stop,

.add_interface = ath9k_htc_add_interface,

.remove_interface = ath9k_htc_remove_interface,

.config = ath9k_htc_config,

.configure_filter = ath9k_htc_configure_filter,

.sta_add = ath9k_htc_sta_add,

.sta_remove = ath9k_htc_sta_remove,

.conf_tx = ath9k_htc_conf_tx,

.bss_info_changed = ath9k_htc_bss_info_changed,

.set_key = ath9k_htc_set_key,

.get_tsf = ath9k_htc_get_tsf,

.set_tsf = ath9k_htc_set_tsf,

.reset_tsf = ath9k_htc_reset_tsf,

.ampdu_action = ath9k_htc_ampdu_action,

.sw_scan_start = ath9k_htc_sw_scan_start,

.sw_scan_complete = ath9k_htc_sw_scan_complete,

.set_rts_threshold = ath9k_htc_set_rts_threshold,

.rfkill_poll = ath9k_htc_rfkill_poll_state,

.set_coverage_class = ath9k_htc_set_coverage_class,

.set_bitrate_mask = ath9k_htc_set_bitrate_mask,

};

ath9k_htc_ops注册流程如下图所示:

a4c26d1e5885305701be709a3d33442f.png

ieee80211_alloc_hw()函数是即分配了802.11

协议层需要的内存结构,又顺便分配了驱动的私有数据结构,该函数分配的内存结构如下图所示:

4. Wifi工作流程

4.1

Wifi打开基本流程

Wifi打开基本流程如下图所示:

a4c26d1e5885305701be709a3d33442f.png

4.2

Wifi关闭基本流程

Wifi关闭基本流程如下图所示:

a4c26d1e5885305701be709a3d33442f.png

4.3

Wifi待机和唤醒流程

a4c26d1e5885305701be709a3d33442f.png

5.

注册ieee80211_class

其详细代码如下:

net/wireless/sysfs.c

structclassieee80211_class = {

.name = "ieee80211",

.owner = THIS_MODULE,

.dev_release = wiphy_dev_release,

.dev_attrs = ieee80211_dev_attrs,

#ifdef CONFIG_HOTPLUG

.dev_uevent = wiphy_uevent,

#endif

.suspend = wiphy_suspend, // Suspend Wifi

.resume = wiphy_resume, // Resume Wifi

.ns_type = &net_ns_type_operations,

.namespace= wiphy_namespace,

};

intwiphy_sysfs_init(void)

{

returnclass_register(&ieee80211_class);

}

voidwiphy_sysfs_exit(void)

{

class_unregister(&ieee80211_class);

}

它需要调用的struct

cfg80211_ops定义如下:

net/mac80211/cfg.c

structcfg80211_ops mac80211_config_ops = {

.add_virtual_intf = ieee80211_add_iface,

.del_virtual_intf = ieee80211_del_iface,

.change_virtual_intf = ieee80211_change_iface,

.add_key = ieee80211_add_key,

.del_key = ieee80211_del_key,

.get_key = ieee80211_get_key,

.set_default_key = ieee80211_config_default_key,

.set_default_mgmt_key = ieee80211_config_default_mgmt_key,

.add_beacon = ieee80211_add_beacon,

.set_beacon = ieee80211_set_beacon,

.del_beacon = ieee80211_del_beacon,

.add_station = ieee80211_add_station,

.del_station = ieee80211_del_station,

.change_station = ieee80211_change_station,

.get_station = ieee80211_get_station,

.dump_station = ieee80211_dump_station,

.dump_survey = ieee80211_dump_survey,

#ifdef CONFIG_MAC80211_MESH

.add_mpath = ieee80211_add_mpath,

.del_mpath = ieee80211_del_mpath,

.change_mpath = ieee80211_change_mpath,

.get_mpath = ieee80211_get_mpath,

.dump_mpath = ieee80211_dump_mpath,

.update_mesh_config = ieee80211_update_mesh_config,

.get_mesh_config = ieee80211_get_mesh_config,

.join_mesh = ieee80211_join_mesh,

.leave_mesh = ieee80211_leave_mesh,

#endif

.change_bss = ieee80211_change_bss,

.set_txq_params = ieee80211_set_txq_params,

.set_channel = ieee80211_set_channel,

.suspend = ieee80211_suspend,

.resume = ieee80211_resume,

.scan = ieee80211_scan,

.sched_scan_start = ieee80211_sched_scan_start,

.sched_scan_stop = ieee80211_sched_scan_stop,

.auth = ieee80211_auth,

.assoc = ieee80211_assoc,

.deauth = ieee80211_deauth,

.disassoc = ieee80211_disassoc,

.join_ibss = ieee80211_join_ibss,

.leave_ibss = ieee80211_leave_ibss,

.set_wiphy_params = ieee80211_set_wiphy_params,

.set_tx_power = ieee80211_set_tx_power,

.get_tx_power = ieee80211_get_tx_power,

.set_wds_peer = ieee80211_set_wds_peer,

.rfkill_poll = ieee80211_rfkill_poll,

CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)

.set_power_mgmt = ieee80211_set_power_mgmt,

.set_bitrate_mask = ieee80211_set_bitrate_mask,

.remain_on_channel = ieee80211_remain_on_channel,

.cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,

.mgmt_tx = ieee80211_mgmt_tx,

.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,

.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,

.mgmt_frame_register = ieee80211_mgmt_frame_register,

.set_antenna = ieee80211_set_antenna,

.get_antenna = ieee80211_get_antenna,

.set_ringparam = ieee80211_set_ringparam,

.get_ringparam = ieee80211_get_ringparam,

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值