Chinaunix首页 | 论坛 | 博客
  • 博客访问: 292640
  • 博文数量: 52
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 587
  • 用 户 组: 普通用户
  • 注册时间: 2017-03-09 09:24
个人简介

水滴

文章分类

全部博文(52)

文章存档

2021年(3)

2019年(8)

2018年(32)

2017年(9)

我的朋友

分类: LINUX

2017-12-08 09:17:23

1. 内核函数说明
1subsys_initcall() 系统调用子系统初始化入口函数,你将入口函数加入到initd总,系统启动do_initcal时调用
2. WIFI 驱动学习
1. userspace nl80211 cfg80211 mac 80211结构图
2.1 基本概念
nl80211 cfg80211 mac80211由内核提供支持wifi配置的处理。
文件目录:linux-3.10.14-p112871/net/wireless/

1. nl80211: 用于对无线设备进行配置管理,它是一个基本Netlink的用户态协议(User态)
2. cfg80211:  与FullMAC, mac80211和nl80211一起工作。cfg80211是Linux 802.11配置API。 cfg80211用于取代Wireless-Extensions。 nl80211用来配置一个cfg80211设备,用于内核< - >用户空间之间的通信
3. mac80211: 是一个driver开发者可用于为SoftMAC无线设备写驱动的框架 (Kernel态)。mac80211为SoftMAC设备实现了cfg80211回调函数,且mac80211通过cfg80211实现了向网络子系统注册和配置。配置由cfg80211通过nl80211和wext实现。
2.2 nl80211驱动
开始文件:linux-3.10.14-p112871/net/wireless/nl80211.c
2.2.1 关键数据结构
1. nl消息头
struct genlmsghdr {
__u8 cmd;
__u8 version;
__u16 reserved;
};
2. 协议注册
static struct genl_family nl80211_fam = {
.id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
.name = "nl80211", /* have users key off the name instead */
.hdrsize = 0, /* no private header */
.version = 1, /* no particular meaning now */
.maxattr = NL80211_ATTR_MAX,
.netnsok = true,
.pre_doit = nl80211_pre_doit,
.post_doit = nl80211_post_doit,
};
id:genl family的ID号,一般由内核进行分配,取值范围GENL_MIN_ID~GENL_MAX_ID(16~1023),其中GENL_ID_CTRL为控制器的family ID,不可另行分配,该familyID全局唯一并且在family_ht中的位置也由该值确定;
hdrsize:用户私有报头的长度,即可选的user msg header长度,若没有则为0;
name:genl family的名称,必须是独一无二且用户层已知的(用户通过它来向控制查找family id);
version:版本号;
maxattr:消息属性attr最大的类型数(即该genl family所支持的最大attr属性类型的种类个数);
netnsok:指示当前簇是否能够处理网络命名空间;
pre_doit:调用genl_ops结构中处理消息函数doit()前调用的钩子函数,一般用于执行一些前置的当前簇通用化处理,例如对临界区加锁等;
注释:主要通过用户态发送的消息中,通过cfg80211查找相应的dev信息,并填充到info当中。
post_doit:调用genl_ops结构中处理消息函数doit()后调用的钩子函数,一般执行pre_doit函数相反的操作;
mcast_bind/mcast_unbind:在绑定/解绑定socket到一个特定的genl netlink组播组中调用(目前内核中没有相关使用);
attrbuf:保存拷贝的attr属性缓存;
ops/n_ops:保存genl family命令处理结构即命令的个数,后面详细描述;
family_list:链表结构,用于将当前当前簇链入全局family_ht散列表中;
mcgrps/n_mcgrps:保存当前簇使用的组播组及组播地址的个数;
4. 命令 钩子函数
static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY, //cmd
.doit = nl80211_get_wiphy, //对应的钩子函数
.dumpit = nl80211_dump_wiphy,
.policy = nl80211_policy, //策略
/* can be retrieved by unprivileged users */
.internal_flags = NL80211_FLAG_NEED_WIPHY,
},
}
policy:属性attr有效性策略,若该字段不为空,在genl执行消息处理函数前会对消息中的attr属性进行校验,否则则不做校验;
doit:标准命令回调函数,在当前族中收到数据时触发调用,函数的第一个入参skb中保存了用户下发的消息内容;
dumpit:转储回调函数,当genl_ops的flag标志被添加了NLM_F_DUMP以后会调用该回调函数,这里的第一个入参skb中不再有用户下发消息内容,而是要求函数能够在传入的skb中填入消息载荷并返回填入数据长度;
done:转储结束后执行的回调函数
支持的命令:
5. 接收信息结构
struct genl_info {
u32 snd_seq;
u32 snd_portid;
struct nlmsghdr * nlhdr;
struct genlmsghdr * genlhdr;
void * userhdr;
struct nlattr ** attrs;
#ifdef CONFIG_NET_NS
struct net * _net;
#endif
void * user_ptr[2];
};
内核在接收到用户的genetlink消息后,会对消息解析并封装成genl_info结构,便于命令回校函数进行处理,其中各字段含义如下:
snd_seq:消息的发送序号(不强制使用);
snd_portid:消息发送端socket所绑定的ID;
nlhdr:netlink消息头;
genlhdr:generic netlink消息头;
userhdr:用户私有报头;
attrs:netlink属性,包含了消息的实际载荷;
dst_sk:目的socket;
2.2.2 代码分析
2.2.2.1 nl80211_init()
主要完成两个任务:
1. 注册协议和命令回调函数
genl_register_family_with_ops();
2. 注册组播组(可以进行组播)
genl_register_mc_group();
2.2.2.2 支持的命令
nl80211接收来自用户态的netlink信息,通过回调函数nl80211_pre_doit, 查找cfg80211注册时的设备信息dev。 通过调用函数cfg80211函数接口或者dev钩子函数实现信息的获取或参数的设置。
enum nl80211_commands {
/* don't change the order or add anything between, this is ABI! */
NL80211_CMD_UNSPEC,
NL80211_CMD_GET_WIPHY, /* can dump */
NL80211_CMD_SET_WIPHY,
NL80211_CMD_NEW_WIPHY,
NL80211_CMD_DEL_WIPHY,

NL80211_CMD_GET_INTERFACE, /* can dump */
NL80211_CMD_SET_INTERFACE,
NL80211_CMD_NEW_INTERFACE,
NL80211_CMD_DEL_INTERFACE,
NL80211_CMD_GET_KEY,
NL80211_CMD_SET_KEY,
NL80211_CMD_NEW_KEY,
NL80211_CMD_DEL_KEY,
NL80211_CMD_GET_BEACON,
NL80211_CMD_SET_BEACON,
NL80211_CMD_START_AP,
NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP,
NL80211_CMD_STOP_AP,
NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP,
NL80211_CMD_GET_STATION,
NL80211_CMD_SET_STATION,
NL80211_CMD_NEW_STATION,
NL80211_CMD_DEL_STATION,
NL80211_CMD_GET_MPATH,
NL80211_CMD_SET_MPATH,
NL80211_CMD_NEW_MPATH,
NL80211_CMD_DEL_MPATH,
NL80211_CMD_SET_BSS,
NL80211_CMD_SET_REG,
NL80211_CMD_REQ_SET_REG,
NL80211_CMD_GET_MESH_CONFIG,
NL80211_CMD_SET_MESH_CONFIG,
NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */,
NL80211_CMD_GET_REG,
NL80211_CMD_GET_SCAN,
NL80211_CMD_TRIGGER_SCAN,
NL80211_CMD_NEW_SCAN_RESULTS,
NL80211_CMD_SCAN_ABORTED,
NL80211_CMD_REG_CHANGE,
NL80211_CMD_AUTHENTICATE,
NL80211_CMD_ASSOCIATE,
NL80211_CMD_DEAUTHENTICATE,
NL80211_CMD_DISASSOCIATE,
NL80211_CMD_MICHAEL_MIC_FAILURE,
NL80211_CMD_REG_BEACON_HINT,
NL80211_CMD_JOIN_IBSS,
NL80211_CMD_LEAVE_IBSS,
NL80211_CMD_TESTMODE,
NL80211_CMD_CONNECT,
NL80211_CMD_ROAM,
NL80211_CMD_DISCONNECT,
NL80211_CMD_SET_WIPHY_NETNS,
NL80211_CMD_GET_SURVEY,
NL80211_CMD_NEW_SURVEY_RESULTS,
NL80211_CMD_SET_PMKSA,
NL80211_CMD_DEL_PMKSA,
NL80211_CMD_FLUSH_PMKSA,
NL80211_CMD_REMAIN_ON_CHANNEL,
NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
NL80211_CMD_SET_TX_BITRATE_MASK,
NL80211_CMD_REGISTER_FRAME,
NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME,
NL80211_CMD_FRAME,
NL80211_CMD_ACTION = NL80211_CMD_FRAME,
NL80211_CMD_FRAME_TX_STATUS,
NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS,
NL80211_CMD_SET_POWER_SAVE,
NL80211_CMD_GET_POWER_SAVE,
NL80211_CMD_SET_CQM,
NL80211_CMD_NOTIFY_CQM,
NL80211_CMD_SET_CHANNEL,
NL80211_CMD_SET_WDS_PEER,
NL80211_CMD_FRAME_WAIT_CANCEL,
NL80211_CMD_JOIN_MESH,
NL80211_CMD_LEAVE_MESH,
NL80211_CMD_UNPROT_DEAUTHENTICATE,
NL80211_CMD_UNPROT_DISASSOCIATE,
NL80211_CMD_NEW_PEER_CANDIDATE,
NL80211_CMD_GET_WOWLAN,
NL80211_CMD_SET_WOWLAN,
NL80211_CMD_START_SCHED_SCAN,
NL80211_CMD_STOP_SCHED_SCAN,
NL80211_CMD_SCHED_SCAN_RESULTS,
NL80211_CMD_SCHED_SCAN_STOPPED,
NL80211_CMD_SET_REKEY_OFFLOAD,
NL80211_CMD_PMKSA_CANDIDATE,
NL80211_CMD_TDLS_OPER,
NL80211_CMD_TDLS_MGMT,
NL80211_CMD_UNEXPECTED_FRAME,
NL80211_CMD_PROBE_CLIENT,
NL80211_CMD_REGISTER_BEACONS,
NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
NL80211_CMD_SET_NOACK_MAP,
NL80211_CMD_CH_SWITCH_NOTIFY,
NL80211_CMD_START_P2P_DEVICE,
NL80211_CMD_STOP_P2P_DEVICE,
NL80211_CMD_CONN_FAILED,
NL80211_CMD_SET_MCAST_RATE,
NL80211_CMD_SET_MAC_ACL,
NL80211_CMD_RADAR_DETECT,
NL80211_CMD_GET_PROTOCOL_FEATURES,
NL80211_CMD_UPDATE_FT_IES,
NL80211_CMD_FT_EVENT,
NL80211_CMD_CRIT_PROTOCOL_START,
NL80211_CMD_CRIT_PROTOCOL_STOP,
__NL80211_CMD_AFTER_LAST,
NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
};
2.3 cfg80211驱动
开始文件:linux-3.10.14-p112871/net/wireless/core.c, 文件主要提供一些相关接口函数,实现设备在cfg80211中设备的注册,在链表cfg80211_rdev_list 中添加设备信息。
2.3.1 关键数据结构
1.
struct pernet_operations {
struct list_head list;
int (*init)(struct net *net);
void (*exit)(struct net *net);
void (*exit_batch)(struct list_head *net_exit_list);
int *id;
size_t size;
};

2.3.2 代码分析
2.3.2.1 cfg80211_init(void)
1. register_pernet_device(&cfg80211_pernet_ops);(无初始化函数)
注册网络设备操作,该函数是register_pernet_operations的包裹函数,其中first_device的定义如下:
static struct list_head *first_device = &pernet_list; 所有要添加到网络命名空间的网络协议模块都会添加到链表first_device中。当kernel支持网络命令空间时,register_pernet_operations的定义如下:
当支持多网络命令空间时,会调用该函数,该函数会遍历目前已存在的所有网络命名空间,将网络协议模块添加到每一个网络命令空间中;并执行init操作,在每一个网络命名空间中,执行协议初始化相关的东东(生成proc相关的文件或者为协议申请缓存等)。
2. wiphy_sysfs_init();
在/net/wireless/sysfs.c中,该文件的作用是:当cfg80211.ko驱动模块被安装后,在终端设备的sys/class/下会出现ieee80211文件夹.
3. register_netdevice_notifier(&cfg80211_netdev_notifier);
实现设备cfg80211中的初始化、注册cfg80211以及相关参数的设置
4.nl80211_init();
nl80211 初始化函数
5. regulatory_init();

2.4 mac80211驱动
mac80211:是一个Linux内核子系统,是驱动开发者可用于为SoftMAC无线设备写驱动的框架。 mac80211在内核空间实现STA模式,在用户空间实现AP模式(hostapd)。
2.4.1 代码结构
1. ieee80211_i.h(主要数据结构)
2. main.c(主函数入口)
3. iface.c(虚拟接口处理)
4. key.c,key.h(密钥管理)
5. sta_info.c,sta_info.h(用户管理)
6. pm.c(功率管理)
7. rate.c,rate.h(速率控制函数)
8. rc80211*(速率控制算法)
9. rx.c(帧接收路径代码)
10. tx.c(帧发送路径代码)
11. scan.c(软件扫描代码)
12. mlme.c(station/managed模式MLME)
13. ibss.c(IBSS MLME)
14. cfg.c,cfg.h,wext.c(配置入口代码)
15. aes*,tkip*,wep*,michael*,wpa*(WPA/RSN/WEP代码)
16. wme.c,wme.h(QoS代码)
17. util.c(公共函数)

2.4.2主要的数据结构
1 ieee80211_local/ieee80211_hw
位置:ieee80211_i.h
  • 每个数据结构代表一个无线设备(ieee80211_hw嵌入到ieee80211_local)
  • ieee80211_hw是ieee80211_local在驱动中的可见部分
  • 包含无线设备的所有操作信息
2 sta_info/ieee80211_sta
位置:sta_info.h
  • 代表每一个station
  • 可能是mesh,IBSS,AP,WDS
  • ieee80211_sta是驱动可见部分
3 ieee80211_conf
位置:mac80211.h
  • 硬件配置
  • 当前信道是最重要的字段
  • 硬件特殊参数
4 ieee80211_bss_conf
位置:mac80211.h
  • BSS配置
  • 多BSSes类型(IBSS/AP/managed)
  • 包含比如基础速率位图
  • per BSS parameters in case hardware supports creating/associating with multiple BSSes
5 ieee80211_key/ieee80211_key_conf
位置:key.h
  • 代表加密/解密密钥
  • ieee80211_key_conf提供给驱动用于硬件加速
  • ieee80211_key包含book-keeping和软件解密状态
6 ieee80211_tx_info
位置:mac80211.h
  • 大部分复杂数据结构
  • skb内部控制缓冲区(cb)
  • 经历三个阶段:1、由mac80211初始化;2、由驱动使用;3、由发送状态通告使用
7 ieee80211_rx_status
位置:mac80211.h
  • 包含接收帧状态
  • 驱动通过接收帧传给mac80211
8 ieee80211_sub_if_data/ieee80211_vif
位置:ieee80211_i.h
  • 包含每个虚拟接口信息
  • ieee80211_vif is passed to driver for those virtual interfaces the driver knows about (no monitor,VLAN)
  • 包含的sub-structures取决于模式
2.4.3 主要流程
1 配置
  • 所有发起来自用户空间(wext或者nl80211)
  • managed和IBSS模式:触发状态机(基于workqueue)
  • 有些操作或多或少直接通过驱动传递(比如信道设置)
2 接收路径
  • 通过函数ieee80211_rx()接收帧
  • 调用ieee80211_rx_monitor()拷贝帧传递给所有监听接口
  • 调用invoke_rx_handlers()处理帧
  • 如果是数据帧,转换成802.3帧格式,传递给上层协议栈
  • 如果是管理帧/控制帧,传递给MLME
3 接收处理钩子(invoke_rx_handlers)
  • ieee80211_rx_h_passive_scan
  • ieee80211_rx_h_check
  • ieee80211_rx_h_decrypt
  • ieee80211_rx_h_check_more_data
  • ieee80211_rx_h_sta_process
  • ieee80211_rx_h_defragment
  • ieee80211_rx_h_ps_poll
  • ieee80211_rx_h_michael_mic_verify
  • ieee80211_rx_h_remove_qos_control
  • ieee80211_rx_h_amsdu
  • ieee80211_rx_h_mesh_fwding
  • ieee80211_rx_h_data
  • ieee80211_rx_h_ctrl
  • ieee80211_rx_h_action
  • ieee80211_rx_h_mgmt
4 发送路径
  • 帧传递给ieee80211_subif_start_xmit()
  • 把帧转换成802.11格式,丢弃发给未认证工作站的单播包,除了来自本地的EAPOL帧
  • 如果是MONITOR接口,在帧头部增加radiotap信息
  • 调用invoke_tx_handlers()处理帧
  • 调用drv_tx(),把帧传递给驱动
5 发送处理钩子(invoke_tx_handlers)
  • ieee80211_tx_h_dynamic_ps
  • ieee80211_tx_h_check_assoc
  • ieee80211_tx_h_ps_buf
  • ieee80211_tx_h_select_key
  • ieee80211_tx_h_sta
  • ieee80211_tx_h_rate_ctrl
  • ieee80211_tx_h_michael_mic_add
  • ieee80211_tx_h_sequence
  • ieee80211_tx_h_fragment
  • ieee80211_tx_h_stats
  • ieee80211_tx_h_encrypt
  • ieee80211_tx_h_calculate_duration
6 mangement/MLME
  • 状态机运行依赖于用户请求
  • 标准方法如下:
  • probe request/response
  • auth request/response
  • assoc request/response
  • notification request/response
7 IBSS
  • 尝试寻找IBSS
  • 加入IBSS或者创建IBSS
  • 如果没有配对,则周期性地尝试寻找IBSS并加入
8 创建接口路径
  • 创建接口由用户空间通过nl80211发起
  • 分配网络设备空间(包含sdata对象空间)
  • 初始化网络设备
  • 初始化sdata对象(包括设备类型,接口类型,设备操作函数等等)
  • 注册网络设备
  • 把sdata对象加入local->interfaces
9 删除接口路径
  • 删除接口由用户空间通过nl80211发起
  • 把sdata对象从local->interfaces移除
  • 移除网络设备
10 创建station路径
  • 创建station由用户空间通过nl80211发起
  • 分配sta_info对象空间
  • 初始化sta_info对象(包括侦听间隔,支持速率集等等)
  • 初始化sta_info对象的速率控制对象
  • 把sta_info对象加入local->sta_pending_list
  • 调用local->ops->sta_add通知驱动创建station
  • 把sta_info对象加入local->sta_list
11 删除station路径
  • 删除station由用户空间通过nl80211发起
  • 删除sta_info对象的key对象
  • 把sta_info对象从local->sta_pending_list移除
  • 调用local->ops->sta_remove通知驱动移除station
  • 删除sta_info对象的速率控制对象
  • 把sta_info对象从local->sta_list移除
12 扫描请求路径
  • 扫描请求由用户空间通过nl80211发起
  • 如果支持硬件扫描,调用local->ops->hw_scan()执行硬件扫描
  • 否则,调用ieee80211_start_sw_scan()执行软件扫描
13 扫描状态机路径
  • 如果存在硬件扫描请求,调用drv_hw_scan()进行扫描,如果失败,调用ieee80211_scan_completed()完成扫描
  • 如果存在扫描请求,同时未进行扫描,调用__ieee80211_start_scan()进行软件扫描,如果失败,调用ieee80211_scan_completed()完成扫描
  • 根据next_scan_state调用相应的处理函数
  • 如果next_delay==0,则继续根据next_scan_state调用相应的处理函数
  • 延时唤醒ieee80211_scan_work()
2.4.4 切换点
1 配置
  • wireless extensions (wext)
  • cfg80211 (通过nl80211和用户空间通信)
2 wext
  • 设置SSID,BSSID和其他关联参数
  • 设置RTS/fragmentation thresholds
  • managed/IBSS模式的加密密钥
3 cfg80211
  • 扫描
  • 用户管理(AP)
  • mesh管理
  • 虚拟接口管理
  • AP模式加密密钥
4 mac80211到速率控制
  • 速率控制不是驱动的一部分
  • 每个驱动有自己的速率控制选择算法
  • 速率控制填充ieee80211_tx_info速率信息
  • 速率控制获取发送状态
5 mac80211到驱动
  • 驱动方法(ieee80211_ops)
  • mac80211有一些输出函数
  • 参考include/net/mac80211.h
2.4.5 主要函数
1 ieee80211_alloc_hw()
  • 分配wiphy对象空间(保证私有数据和硬件私有数据32字节对齐,wiphy包含ieee80211_local和驱动私有数据)
  • 初始化wiphy对象(包括重传次数,RTS门限等等)
  • 初始化ieee80211_local(包括重传次数,工作队列,接口链表等等)
  • 初始化sta_pending_list链表
  • 初始化sta_list链表
2 ieee80211_register_hw()
  • 分配int_scan_req数据结构
  • 初始化支持接口类型(包括MONITOR接口)
  • 注册wiphy
  • 初始化WEP
  • 初始化速率控制算法
  • 注册STA接口(默认wlan0)
3 ieee80211_rx()
  • 拷贝skb,同时在skb头部增加radiotap信息,传递给所有监听接口
  • 如果是数据帧,根据MAC地址查找station
  • 如果station没有找到,把skb传递给所有接口处理
  • 数据帧:转换成802.3帧格式,传递给网络协议栈
  • 管理帧/控制帧:传递给MLME
4 ieee80211_xmit()
  • 如果skb来自监听接口,移除skb头部的radiotap信息
  • 进行skb预处理(包括设置QoS优先级,设置分段标志,ACK应答标志等等)
  • 选择加密密钥
  • 选择速率(ESP8089采用硬件速率控制,所以mac80211速率控制无效)
  • 加密(mac80211采用硬件加速,所以mac80211加密无效)
  • 通过local->ops->tx()把skb传递给驱动
2.4.6 代码分析
MAC80211/main.c
2.4.6.1 ieee80211_init
1 rc80211_minstrel_init()
注册速率控制ops
位置:rc80211_minstrel.c
struct rate_control_ops mac80211_minstrel = {
.name = "minstrel",
.tx_status = minstrel_tx_status,
.get_rate = minstrel_get_rate,
.rate_init = minstrel_rate_init,
.alloc = minstrel_alloc,
.free = minstrel_free,
.alloc_sta = minstrel_alloc_sta,
.free_sta = minstrel_free_sta,
#ifdef CONFIG_MAC80211_DEBUGFS
.add_sta_debugfs = minstrel_add_sta_debugfs,
.remove_sta_debugfs = minstrel_remove_sta_debugfs,
#endif
};
2 rc80211_minstrel_ht_init();
注册80211 ht 速率控制ops
位置:rc80211_minstrel_ht.c
static struct rate_control_ops mac80211_minstrel_ht = {
.name = "minstrel_ht",
.tx_status = minstrel_ht_tx_status,
.get_rate = minstrel_ht_get_rate,
.rate_init = minstrel_ht_rate_init,
.rate_update = minstrel_ht_rate_update,
.alloc_sta = minstrel_ht_alloc_sta,
.free_sta = minstrel_ht_free_sta,
.alloc = minstrel_ht_alloc,
.free = minstrel_ht_free,
#ifdef CONFIG_MAC80211_DEBUGFS
.add_sta_debugfs = minstrel_ht_add_sta_debugfs,
.remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
#endif
};
3 rc80211_pid_init()
注册发送速率控制算法ops
位置:rc80211_pid_algo.c
static struct rate_control_ops mac80211_rcpid = {
.name = "pid",
.tx_status = rate_control_pid_tx_status,
.get_rate = rate_control_pid_get_rate,
.rate_init = rate_control_pid_rate_init,
.alloc = rate_control_pid_alloc,
.free = rate_control_pid_free,
.alloc_sta = rate_control_pid_alloc_sta,
.free_sta = rate_control_pid_free_sta,
#ifdef CONFIG_MAC80211_DEBUGFS
.add_sta_debugfs = rate_control_pid_add_sta_debugfs,
.remove_sta_debugfs = rate_control_pid_remove_sta_debugfs,
#endif
};
4 ieee80211_iface_init();
注册设备接口回调函数,用于更改相应结构体设备名称
位置:iface.c
static struct notifier_block mac80211_netdev_notifier = {
.notifier_call = netdev_notify,
};

2.4.6.2 ieee80211_restart_hw()
硬件重启初始化相关结构
2.4.6.3 ieee80211_alloc_hw
为硬件分配内存, 初始化ops,以及相关结构初始化
2.4.6.4 ieee80211_register_hw()
完成硬件的注册,以及相关初始化工作。
阅读(5632) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~