国产一二三四区中,精品无码人妻一区二区三区免费,亚洲欧美日本国产专区一区,欧美成人A激情

電腦知識(shí)

Linux無線網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)開發(fā)

時(shí)間:2024-09-17 15:07:33   作者:網(wǎng)際迅聯(lián)   來源:統(tǒng)信軟件技術(shù)   閱讀:71   評(píng)論:0
內(nèi)容摘要:無線網(wǎng)卡驅(qū)動(dòng)可以借助PCI,SDIO,UART,USB來用于總線通訊。MAC層可以用軟件來實(shí)現(xiàn),也可以用硬件來實(shí)現(xiàn)。一般有mac和phy組成。構(gòu)圖:mac:一般用于數(shù)據(jù)的過濾phy: 操作數(shù)據(jù)實(shí)際的收發(fā)。wifi架構(gòu)圖以USB接口的WIFI模塊進(jìn)行分析:1、從USB總線的角度去看......

無線網(wǎng)卡驅(qū)動(dòng)可以借助PCI,SDIO,UART,USB來用于總線通訊。MAC層可以用軟件來實(shí)現(xiàn),也可以用硬件來實(shí)現(xiàn)。一般有mac和phy組成。構(gòu)圖:

mac:一般用于數(shù)據(jù)的過濾

phy: 操作數(shù)據(jù)實(shí)際的收發(fā)。

wifi1

wifi架構(gòu)圖

以USB接口的WIFI模塊進(jìn)行分析:

1、從USB總線的角度去看,它是USB設(shè)備

2、從Linux設(shè)備的分類上看,它又是網(wǎng)絡(luò)設(shè)備

3、從WIFI本身的角度去看,它又有自己獨(dú)特的功能及屬性,因此它又是一個(gè)私有的設(shè)備

只要抓住這三條線索深入去分析驅(qū)動(dòng),整個(gè)WIFI驅(qū)動(dòng)框架就會(huì)浮現(xiàn)在你眼前。

總線設(shè)備驅(qū)動(dòng)層

首先,現(xiàn)在我們先從USB設(shè)備開始,要寫一個(gè)USB設(shè)備驅(qū)動(dòng),那么大致步驟如下:

1、需要針對(duì)該設(shè)備定義一個(gè)USB驅(qū)動(dòng),對(duì)應(yīng)到代碼中即定義一個(gè)usb_driver結(jié)構(gòu)體變量。

2、填充該設(shè)備的usb_driver結(jié)構(gòu)體成員變量

3、將該驅(qū)動(dòng)注冊(cè)到USB子系統(tǒng)

網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)層

其次,接下來是網(wǎng)絡(luò)設(shè)備的角度要完成的事。

1、網(wǎng)絡(luò)協(xié)議接口層向網(wǎng)絡(luò)層協(xié)議提供統(tǒng)一的數(shù)據(jù)包收發(fā)接口,不論上層協(xié)議為ARP 還是 IP,都通過 dev_queue_xmit()函數(shù)發(fā)送數(shù)據(jù),并通過 netif_rx()函數(shù)接收數(shù)據(jù)。這一層的存在使得上層協(xié)議獨(dú)立于具體的設(shè)備。

2、網(wǎng)絡(luò)設(shè)備接口層向協(xié)議接口層提供統(tǒng)一的用于描述具體網(wǎng)絡(luò)設(shè)備屬性和操作的結(jié)構(gòu)體 net_device,該結(jié)構(gòu)體是設(shè)備驅(qū)動(dòng)功能層中各函數(shù)的容器。實(shí)際上,網(wǎng)絡(luò)設(shè)備接口層從宏觀上規(guī)劃了具體操作硬件的設(shè)備驅(qū)動(dòng)功能層的結(jié)構(gòu)。

3、設(shè)備驅(qū)動(dòng)功能層各函數(shù)是網(wǎng)絡(luò)設(shè)備接口層 net_device 數(shù)據(jù)結(jié)構(gòu)的具體成員,是驅(qū)使網(wǎng)絡(luò)設(shè)備硬件完成相應(yīng)動(dòng)作的程序,它通過 hard_start_xmit()函數(shù)啟動(dòng)發(fā)送操作,并通過網(wǎng)絡(luò)設(shè)備上的中斷觸發(fā)接收操作。

4、網(wǎng)絡(luò)設(shè)備與媒介層是完成數(shù)據(jù)包發(fā)送和接收的物理實(shí)體,包括網(wǎng)絡(luò)適配器和具體的傳輸媒介,網(wǎng)絡(luò)適配器被設(shè)備驅(qū)動(dòng)功能層中的函數(shù)物理上驅(qū)動(dòng)。對(duì)于Linux 系統(tǒng)而言,網(wǎng)絡(luò)設(shè)備和媒介都可以是虛擬的。

下面對(duì)這四層做一個(gè)較為詳細(xì)解釋:

網(wǎng)絡(luò)接口層

網(wǎng)絡(luò)協(xié)議接口層最主要的功能是給上層協(xié)議提供了透明的數(shù)據(jù)包發(fā)送和接收接口。當(dāng)上層 ARP 或 IP 協(xié) 議需要發(fā)送數(shù)據(jù) 包時(shí),它將調(diào)用網(wǎng)絡(luò)協(xié)議 接口層的dev_queue_xmit()函數(shù)發(fā)送該數(shù)據(jù)包,同時(shí)需傳遞給該函數(shù)一個(gè)指向 struct sk_buff 數(shù)據(jù)結(jié)構(gòu)的指針。dev_queue_xmit()函數(shù)的原型為:

dev_queue_xmit (struct sk_buff * skb );

同樣地,上層對(duì)數(shù)據(jù)包的接收也通過向 netif_rx()函數(shù)傳遞一個(gè) struct sk_buff 數(shù)據(jù)結(jié)構(gòu)的指針來完成。netif_rx()函數(shù)的原型為:

int netif_rx(struct sk_buff *skb);

sk_buff 結(jié)構(gòu)體非常重要,它的含義為“套接字緩沖區(qū)”,用于在 Linux 網(wǎng)絡(luò)子系統(tǒng)中的各層之間傳遞數(shù)據(jù),是 Linux 網(wǎng)絡(luò)子系統(tǒng)數(shù)據(jù)傳遞的“中樞神經(jīng)”。當(dāng)發(fā)送數(shù)據(jù)包時(shí),Linux 內(nèi)核的網(wǎng)絡(luò)處理模塊必須建立一個(gè)包含要傳輸?shù)臄?shù)據(jù)包的 sk_buff,然后將 sk_buff 遞交給下層,各層在 sk_buff 中添加不同的協(xié)議頭直至交給網(wǎng)絡(luò)設(shè)備發(fā)送。同樣地,當(dāng)網(wǎng)絡(luò)設(shè)備從網(wǎng)絡(luò)媒介上接收到數(shù)據(jù)包后,它必須將接收到的數(shù)據(jù)轉(zhuǎn)換為 sk_buff 數(shù)據(jù)結(jié)構(gòu)并傳遞給上層,各層剝?nèi)ハ鄳?yīng)的協(xié)議頭直至交給用戶。

其針對(duì)sk_buff的成員變量,操作(分配,釋放,指針移動(dòng))等是這一層的核心內(nèi)容。這一層是屬于協(xié)議層通用的。驅(qū)動(dòng)代碼不需要改動(dòng)。

設(shè)備接口層

設(shè)備接口層的主要功能是為千變?nèi)f化的網(wǎng)絡(luò)設(shè)備定義了統(tǒng)一、抽象的數(shù)據(jù)結(jié)構(gòu) net_device 結(jié)構(gòu)體,以不變應(yīng)萬變,實(shí)現(xiàn)多種硬件在軟件層次上的統(tǒng)一。

net_device 結(jié)構(gòu)體在內(nèi)核中指代一個(gè)網(wǎng)絡(luò)設(shè)備,網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序只需通過填充net_device 的具體成員并注冊(cè) net_device 即可實(shí)現(xiàn)硬件操作函數(shù)與內(nèi)核的掛接。

net_device 本身是一個(gè)巨型結(jié)構(gòu)體,包含網(wǎng)絡(luò)設(shè)備的屬性描述和操作接口。當(dāng)我們編寫網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序時(shí),只需要了解其中的一部分。比如網(wǎng)卡設(shè)備名,硬件信息,接口信息(MTU等),設(shè)備操作函數(shù)(ioctl,open,stop,poll等)。

設(shè)備驅(qū)動(dòng)功能層

net_device 結(jié)構(gòu)體的成員(屬性和函數(shù)指針)需要被設(shè)備驅(qū)動(dòng)功能層的具體數(shù)值和函數(shù)賦予。對(duì)于具體的設(shè)備,工程師應(yīng)該編寫設(shè)備驅(qū)動(dòng)功能層的函數(shù),這些函數(shù)形如 xx_open()、xxx_stop()、xxx_get_stats()、xxx_tx_timeout()、xxx_poll()等。

由于網(wǎng)絡(luò)數(shù)據(jù)包的接收可由中斷引發(fā),設(shè)備驅(qū)動(dòng)功能層中另一個(gè)主體部分將是中斷處理函數(shù),它負(fù)責(zé)讀取硬件上接收的數(shù)據(jù)包并傳送給上層協(xié)議,可能包含xxx_interrupt()和 xxx_rx()函數(shù),前者完成中斷類型判斷等基本的工作,后者則需完成數(shù)據(jù)包的生成和遞交上層等復(fù)雜工作。

對(duì)于特定的設(shè)備,我們還可以定義其相關(guān)私有數(shù)據(jù)和操作,并封裝為一個(gè)私有信息結(jié)構(gòu)體xxx_private,讓其指針被賦值給net_device 的priv成員。xxx_private結(jié)構(gòu)體中可包含設(shè)備特殊的屬性和操作、自旋鎖與信號(hào)量、定時(shí)器以及統(tǒng)計(jì)信息等,由開發(fā)者自定義。

網(wǎng)絡(luò)設(shè)備和媒介層

網(wǎng)絡(luò)設(shè)備與媒介層直接對(duì)應(yīng)于實(shí)際的硬件設(shè)備。為了給設(shè)備的物理配置和寄存器操作一個(gè)更一般的描述,我們可以定義一組宏和一組訪問設(shè)備內(nèi)部寄存器的函數(shù),具體的宏和函數(shù)與特定的硬件緊密相關(guān)。主要是配置底層硬件,寄存器的定義和寄存器的讀寫函數(shù)。

從網(wǎng)卡驅(qū)動(dòng)實(shí)現(xiàn)的主要功能的角度來講,wifi驅(qū)動(dòng)還需要以下的代碼實(shí)現(xiàn):

網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)的注冊(cè)與注銷:這個(gè)是網(wǎng)絡(luò)設(shè)備通用的驅(qū)動(dòng)框架。

網(wǎng)絡(luò)設(shè)備的打開與釋放:

int xxx_open(struct net_device *dev)
{
/* 申請(qǐng)端口、IRQ 等,類似于 fops->open */
ret = request_irq(dev->irq, &xxx_interrupt, 0, dev->name, dev); ... netif_start_queue(dev); ... }
int xxx_release(struct net_device *dev)
{
/* 釋放端口、IRQ 等,類似于 fops->close */
free_irq(dev->irq, dev); ... netif_stop_queue(dev); /* can't transmit any more */
...
} 

數(shù)據(jù)發(fā)送流程:

int xxx_tx(struct sk_buff *skb, struct net_device *dev)
{ int len;
char *data, shortpkt[ETH_ZLEN]; /* 獲得有效數(shù)據(jù)指針和長(zhǎng)度 */ data = skb->data; len = skb->len; if (len < ETH_ZLEN)
{ /* 如果幀長(zhǎng)小于以太網(wǎng)幀最小長(zhǎng)度,補(bǔ) 0 */ memset(shortpkt, 0, ETH_ZLEN);
memcpy(shortpkt, skb->data, skb->len); len = ETH_ZLEN;
data = shortpkt;
}
dev->trans_start = jiffies; /* 記錄發(fā)送時(shí)間戳 */ /* 設(shè)置硬件寄存器讓硬件把數(shù)據(jù)包發(fā)送出去 */ xxx_hw_tx(data, len, dev);
...
} 

當(dāng)數(shù)據(jù)傳輸超時(shí)時(shí),意味著當(dāng)前的發(fā)送操作失敗,此時(shí),數(shù)據(jù)包發(fā)送超時(shí)處理函數(shù) xxx_tx_ timeout()將被調(diào)用。這個(gè)函數(shù)需要調(diào)用 Linux 內(nèi)核提供的 netif_wake_queue()函數(shù)重新啟動(dòng)設(shè)備發(fā)送隊(duì)列。

void xxx_tx_timeout(struct net_device *dev)
{ ... netif_wake_queue(dev); /* 重新啟動(dòng)設(shè)備發(fā)送隊(duì)列 */
} 

數(shù)據(jù)接收流程:

網(wǎng)絡(luò)設(shè)備接收數(shù)據(jù)的主要方法是由中斷引發(fā)設(shè)備的中斷處理函數(shù),中斷處理函數(shù)判斷中斷類型,如果為接收中斷,則讀取接收到的數(shù)據(jù),分配 sk_buffer 數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)緩沖區(qū),將接收到的數(shù)據(jù)復(fù)制到數(shù)據(jù)緩沖區(qū),并調(diào)用 netif_rx()函數(shù)將 sk_buffer 傳遞給上層協(xié)議。

比較簡(jiǎn)單的處理方式是中斷方式:

static void xxx_interrupt(int irq, void *dev_id, struct pt_regs
*regs)
{ ... switch (status &ISQ_EVENT_MASK)
{
case ISQ_RECEIVER_EVENT:
/* 獲取數(shù)據(jù)包 */
xxx_rx(dev); break;
/* 其他類型的中斷 */
}
}
static void xxx_rx(struct xxx_device *dev)
{ ... length = get_rev_len (...);
/* 分配新的套接字緩沖區(qū) */
skb = dev_alloc_skb(length + 2);
skb_reserve(skb, 2); /* 對(duì)齊 */
skb->dev = dev;
/* 讀取硬件上接收到的數(shù)據(jù) */
insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1); if (length &1)
skb->data[length - 1] = inw(ioaddr + RX_FRAME_PORT);
/* 獲取上層協(xié)議類型 */
skb->protocol = eth_type_trans(skb, dev);
/* 把數(shù)據(jù)包交給上層 */
netif_rx(skb);
/* 記錄接收時(shí)間戳 */
dev->last_rx = jiffies; ... } 

復(fù)雜一些的是poll的接收方式:

static int xxx_poll(struct net_device *dev, int *budget)
{
int npackets = 0, quota = min(dev->quota, *budget);
struct sk_buff *skb;
struct xxx_priv *priv = netdev_priv(dev);
struct xxx_packet *pkt; while (npackets < quota && priv->rx_queue)
{ /*從隊(duì)列中取出數(shù)據(jù)包*/ pkt = xxx_dequeue_buf(dev); /*接下來的處理,和中斷觸發(fā)的數(shù)據(jù)包接收一致*/ skb = dev_alloc_skb(pkt->datalen + 2); if (!skb)
{ ... continue;
}
skb_reserve(skb, 2);
memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev); /*調(diào)用 netif_receive_skb 而不是 net_rx 將數(shù)據(jù)包交給上層協(xié)議*/ netif_receive_skb(skb); /*更改統(tǒng)計(jì)數(shù)據(jù) */ priv->stats.rx_packets++;
priv->stats.rx_bytes += pkt->datalen;
xxx_release_buffer(pkt);
} /* 處理完所有數(shù)據(jù)包*/ *budget -= npackets;
dev->quota -= npackets; if (!priv->rx_queue)
{
netif_rx_complete(dev);
xxx_enable_rx_int (...); /* 再次使能網(wǎng)絡(luò)設(shè)備的接收中斷 */ return 0;
} return 1;
} 

雖然 NAPI 兼容的設(shè)備驅(qū)動(dòng)以 poll 方式接收數(shù)據(jù)包,但是仍然需要首次數(shù)據(jù)包接收中斷來觸發(fā) poll 過程。與數(shù)據(jù)包的中斷接收方式不同的是,以輪詢方式接收數(shù)據(jù)包時(shí),當(dāng)?shù)谝淮沃袛喟l(fā)生后,中斷處理程序要禁止設(shè)備的數(shù)據(jù)包接收中斷,如下:

static void xxx_poll_interrupt(int irq, void *dev_id, struct
pt_regs *regs)
{ switch (status &ISQ_EVENT_MASK)
{
case ISQ_RECEIVER_EVENT: ... /* 獲取數(shù)據(jù)包 */
xxx_disable_rx_int(...); /* 禁止接收中斷 */
netif_rx_schedule(dev); break; ... /* 其他類型的中斷 */
}
} 

還剩下一些網(wǎng)絡(luò)連接狀態(tài),參數(shù)設(shè)置和統(tǒng)計(jì)數(shù)據(jù)的函數(shù)需要實(shí)現(xiàn),這部分不再多做說明。

WIFI設(shè)備本身私有的功能及屬性,如自身的配置及初始化、建立與用戶空間的交互接口、自身功能的實(shí)現(xiàn)等。

1、自身的配置及初始化,比如xxx_read_chip_info(); xxx_chip_configure(); xxx_hal_init();

2、主要是在proc和sys文件系統(tǒng)上建立與用戶空間的交互接口,比如xxx_drv_proc_init();xxx_ndev_notifier_register();

3、wifi自身的一些功能實(shí)現(xiàn),比如掃描接入和功耗,電源管理相關(guān)的實(shí)現(xiàn)。

出處:網(wǎng)際迅聯(lián)
網(wǎng)址:
https://wjxlkj.com
轉(zhuǎn)載時(shí)請(qǐng)注明出處和網(wǎng)址

目前網(wǎng)際迅聯(lián)的產(chǎn)品如下:
1、文章https://wjxlkj.com
2、互聯(lián)https://www.wjxlkj.com

3、教程網(wǎng)http://www.downmusicas.net

4、遠(yuǎn)程桌面管理助手

5、FTP數(shù)據(jù)備份助手



企業(yè)客服QQ:58053012



標(biāo)簽:開發(fā)  設(shè)備  網(wǎng)絡(luò)  驅(qū)動(dòng)  無線  

網(wǎng)際迅聯(lián)(北京)科技有限公司
  • 營(yíng)業(yè)執(zhí)照:
  • 備案號(hào)碼:京ICP備15035957號(hào)-3
  • 地址:北京市平谷區(qū)夏各莊鎮(zhèn)稻地大街

聯(lián)系我們

微信掃一掃  手機(jī)訪問