wifi驅動的理解(1)——驅動架構
轉載請註明出處:http://blog.csdn.net/Righthek 謝謝!
在分析WIFI驅動前,分享一下個人對Linux驅動的一些瞭解,其實縱觀Linux眾多的裝置驅動,幾乎都是以匯流排為載體,所有的資料傳輸都是基於匯流排形式的,即使裝置沒有所謂的匯流排介面,但是Linux還是會給它新增一條虛擬匯流排,如platform匯流排等;介於WIFI的驅動實在是太龐大了,同時又是基於比較複雜的USB匯流排,所以建議讀者在看此文章之前,先了解一下USB裝置驅動和網路裝置驅動。
我們要看懂WIFI驅動,首先要明白WIFI的工作原理。所以前期有幾篇文章都是講解WIFI的工作原理。從這篇文章開始,我們將進入WIFI的程式碼世界。對於支援802.11n、802.11ac這些比較新的無線標準的WIFI晶片,其驅動程式也會越來越複雜。那麼我們怎麼入手去了解及分析它呢?
特別宣告:以下文章是以Station的角色去分析WIFI的驅動。
網上很多文章分析Linux裝置驅動都是從模組載入入手去分析它的驅動原始碼。以博主從事Linux裝置驅動多年的經驗,這確實是一條很直觀又非常好的思路。但是這隻侷限於裝置功能少、介面較簡單、驅動原始碼較少的裝置驅動。對於功能複雜、驅動原始碼龐大的裝置驅動,根據這條思路,很多開發者可能會無耐心走下去,或者會走向死衚衕。
現在我們可以這樣來看,從硬體層面上看,WIFI裝置與CPU通訊是通過USB介面的,與其他WIFI裝置之間的通訊是通過無線射頻(RF)。從軟體層面上看,Linux作業系統要管理WIFI裝置,那麼就要將WIFI裝置掛載到USB總線上,通過USB子系統實現管理。而同時為了對接網路,又將WIFI裝置封裝成一個網路裝置。
我們以USB介面的WIFI模組進行分析:
(1)從USB匯流排的角度去看,它是USB裝置;
(2)從Linux裝置的分類上看,它又是網路裝置;
(3)從WIFI本身的角度去看,它又有自己獨特的功能及屬性,因此它又是一個私有的裝置;
通過上述的分析,我們只要抓住這三條線索深入去分析它的驅動原始碼,整個WIFI驅動框架就會浮現在你眼前。
1、現在我們先從USB裝置開始,要寫一個USB裝置驅動,那麼大致步驟如下:
(1)需要針對該裝置定義一個USB驅動,對應到程式碼中即定義一個usb_driver結構體變數。程式碼如下:
struct usb_driver xxx_usb_wifi_driver;
(2)填充該裝置的usb_driver結構體成員變數。程式碼如下:
static struct usb_driver xxx_usb_wifi_driver = {
.name = "XXX_USB_WIFI",
.probe= xxx_probe,
.disconnect= xxx_disconnect,
.suspend= xxx_suspend,
.resume= xxx_resume,
.id_table= xxx_table,
};
(3)將該驅動註冊到USB子系統。程式碼如下:
usb_register(&xxx_usb_wifi_driver);
以上步驟只是一個大致的USB驅動框架流程,而最大和最複雜的工作是填充usb_driver結構體成員變數。以上步驟的主要工作是將USB介面的WIFI裝置掛載到USB總線上,以便Linux系統在USB總線上就能夠找到該裝置。
2、接下來是網路裝置的線索,網路裝置驅動大致步驟如下:
(1)定義一個net_device結構體變數ndev。程式碼如下:
struct net_device *ndev;
(2)初始化ndev變數並分配記憶體。程式碼如下:
ndev=alloc_etherdev();
(3)填充ndev -> netdev_ops結構體成員變數。程式碼如下:
static const struct net_device_ops xxx_netdev_ops= {
.ndo_init= xxx_ndev_init,
.ndo_uninit= xxx _ndev_uninit,
.ndo_open= netdev_open,
.ndo_stop= netdev_close,
.ndo_start_xmit= xxx_xmit_entry,
.ndo_set_mac_address= xxx_net_set_mac_address,
.ndo_get_stats= xxx_net_get_stats,
.ndo_do_ioctl= xxx_ioctl,
};
(4)填充ndev->wireless_handlers結構體成員變數,該變數是無線擴充套件功能。程式碼如下:
ndev->wireless_handlers = (struct iw_handler_def *)&xxx_handlers_def;
(5)將ndev設備註冊到網路子系統。程式碼如下:
register_netdev(ndev);
3、WIFI裝置本身私有的功能及屬性,如自身的配置及初始化、建立與使用者空間的互動介面、自身功能的實現等。
(1)自身的配置及初始化。程式碼如下:
xxx_read_chip_info();
xxx_chip_configure();
xxx_hal_init();
(2)主要是在proc和sys檔案系統上建立與使用者空間的互動介面。程式碼如下:
xxx_drv_proc_init();
xxx_ndev_notifier_register();
(3)自身功能的實現,在前面章節上我們已經講解過WIFI的網路及接入原理,如掃描等。同時由於WIFI在移動裝置中,相對功耗比較大,因此,對於功耗、電源管理也會在驅動中體現。
本文章只是博主結合自身工作經驗分享一個大致的對wifi驅動框架的理解,後期文章將會細化這些內容。敬請讀者期待,謝謝!
轉載請註明出處:http://blog.csdn.net/Righthek 謝謝!
轉載請註明出處:http://blog.csdn.net/Righthek 謝謝!
在分析WIFI驅動前,分享一下個人對Linux驅動的一些瞭解,其實縱觀Linux眾多的裝置驅動,幾乎都是以匯流排為載體,所有的資料傳輸都是基於匯流排形式的,即使裝置沒有所謂的匯流排介面,但是Linux還是會給它新增一條虛擬匯流排,如platform匯流排等;介於WIFI的驅動實在是太龐大了,同時又是基於比較複雜的USB匯流排,所以建議讀者在看此文章之前,先了解一下USB裝置驅動和網路裝置驅動。
我們要看懂WIFI驅動,首先要明白WIFI的工作原理。所以前期有幾篇文章都是講解WIFI的工作原理。從這篇文章開始,我們將進入WIFI的程式碼世界。對於支援802.11n、802.11ac這些比較新的無線標準的WIFI晶片,其驅動程式也會越來越複雜。那麼我們怎麼入手去了解及分析它呢?
特別宣告:以下文章是以Station的角色去分析WIFI的驅動。
網上很多文章分析Linux裝置驅動都是從模組載入入手去分析它的驅動原始碼。以博主從事Linux裝置驅動多年的經驗,這確實是一條很直觀又非常好的思路。但是這隻侷限於裝置功能少、介面較簡單、驅動原始碼較少的裝置驅動。對於功能複雜、驅動原始碼龐大的裝置驅動,根據這條思路,很多開發者可能會無耐心走下去,或者會走向死衚衕。
現在我們可以這樣來看,從硬體層面上看,WIFI裝置與CPU通訊是通過USB介面的,與其他WIFI裝置之間的通訊是通過無線射頻(RF)。從軟體層面上看,Linux作業系統要管理WIFI裝置,那麼就要將WIFI裝置掛載到USB總線上,通過USB子系統實現管理。而同時為了對接網路,又將WIFI裝置封裝成一個網路裝置。
我們以USB介面的WIFI模組進行分析:
(1)從USB匯流排的角度去看,它是USB裝置;
(2)從Linux裝置的分類上看,它又是網路裝置;
(3)從WIFI本身的角度去看,它又有自己獨特的功能及屬性,因此它又是一個私有的裝置;
通過上述的分析,我們只要抓住這三條線索深入去分析它的驅動原始碼,整個WIFI驅動框架就會浮現在你眼前。
1、現在我們先從USB裝置開始,要寫一個USB裝置驅動,那麼大致步驟如下:
(1)需要針對該裝置定義一個USB驅動,對應到程式碼中即定義一個usb_driver結構體變數。程式碼如下:
struct usb_driver xxx_usb_wifi_driver;
(2)填充該裝置的usb_driver結構體成員變數。程式碼如下:
static struct usb_driver xxx_usb_wifi_driver = {
.name = "XXX_USB_WIFI",
.probe= xxx_probe,
.disconnect= xxx_disconnect,
.suspend= xxx_suspend,
.resume= xxx_resume,
.id_table= xxx_table,
};
(3)將該驅動註冊到USB子系統。程式碼如下:
usb_register(&xxx_usb_wifi_driver);
以上步驟只是一個大致的USB驅動框架流程,而最大和最複雜的工作是填充usb_driver結構體成員變數。以上步驟的主要工作是將USB介面的WIFI裝置掛載到USB總線上,以便Linux系統在USB總線上就能夠找到該裝置。
2、接下來是網路裝置的線索,網路裝置驅動大致步驟如下:
(1)定義一個net_device結構體變數ndev。程式碼如下:
struct net_device *ndev;
(2)初始化ndev變數並分配記憶體。程式碼如下:
ndev=alloc_etherdev();
(3)填充ndev -> netdev_ops結構體成員變數。程式碼如下:
static const struct net_device_ops xxx_netdev_ops= {
.ndo_init= xxx_ndev_init,
.ndo_uninit= xxx _ndev_uninit,
.ndo_open= netdev_open,
.ndo_stop= netdev_close,
.ndo_start_xmit= xxx_xmit_entry,
.ndo_set_mac_address= xxx_net_set_mac_address,
.ndo_get_stats= xxx_net_get_stats,
.ndo_do_ioctl= xxx_ioctl,
};
(4)填充ndev->wireless_handlers結構體成員變數,該變數是無線擴充套件功能。程式碼如下:
ndev->wireless_handlers = (struct iw_handler_def *)&xxx_handlers_def;
(5)將ndev設備註冊到網路子系統。程式碼如下:
register_netdev(ndev);
3、WIFI裝置本身私有的功能及屬性,如自身的配置及初始化、建立與使用者空間的互動介面、自身功能的實現等。
(1)自身的配置及初始化。程式碼如下:
xxx_read_chip_info();
xxx_chip_configure();
xxx_hal_init();
(2)主要是在proc和sys檔案系統上建立與使用者空間的互動介面。程式碼如下:
xxx_drv_proc_init();
xxx_ndev_notifier_register();
(3)自身功能的實現,在前面章節上我們已經講解過WIFI的網路及接入原理,如掃描等。同時由於WIFI在移動裝置中,相對功耗比較大,因此,對於功耗、電源管理也會在驅動中體現。
本文章只是博主結合自身工作經驗分享一個大致的對wifi驅動框架的理解,後期文章將會細化這些內容。敬請讀者期待,謝謝!
轉載請註明出處:http://blog.csdn.net/Righthek 謝謝!