linux下的USB驅(qū)動(dòng)開(kāi)發(fā)

版權(quán)聲明:本文為博主原創(chuàng)文章泣洞,如有需要, 請(qǐng)注明轉(zhuǎn)載地址:http://blog.csdn.net/tech_pro忧风。若是侵權(quán)用于商業(yè)用途,請(qǐng)聯(lián)系博主球凰,否則將追究責(zé)任狮腿。 https://blog.csdn.net/TECH_PRO/article/details/70738186

一、Linux下的USB驅(qū)動(dòng)程序

分離和分層是Linux下驅(qū)動(dòng)程序開(kāi)發(fā)采用的最基本的形式呕诉,USB驅(qū)動(dòng)開(kāi)發(fā)在主機(jī)端主要涉及兩個(gè)部分:主機(jī)控制器驅(qū)動(dòng)和設(shè)備驅(qū)動(dòng)缘厢。

主機(jī)控制器驅(qū)動(dòng)主要是和具體的Soc相關(guān)的,它來(lái)識(shí)別USB設(shè)備甩挫,安裝對(duì)應(yīng)的設(shè)備驅(qū)動(dòng)程序昧绣,提供對(duì)USB設(shè)備的讀寫(xiě)函數(shù)。

設(shè)備驅(qū)動(dòng)主要是根據(jù)具體的USB設(shè)備對(duì)USB主機(jī)驅(qū)動(dòng)提供的讀寫(xiě)函數(shù)獲得的數(shù)據(jù)進(jìn)行處理捶闸,實(shí)現(xiàn)這種USB設(shè)備特有的功能夜畴。具體的層次結(jié)構(gòu)如下所示:


基本的開(kāi)發(fā)環(huán)境:

操作系統(tǒng):Ubuntu12.04

內(nèi)核:Linux-3.0.86

GUI :Qtopia2.2.0

交叉編譯工具gcc版本 : 4.5.1

二、USB鼠標(biāo)設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)

這一部分主要完成的功能是:實(shí)現(xiàn)一個(gè)簡(jiǎn)單的USB鼠標(biāo)的設(shè)備驅(qū)動(dòng)程序删壮,讀取鼠標(biāo)進(jìn)行操作所產(chǎn)生的原始的數(shù)據(jù)贪绘。

1、準(zhǔn)備工作

默認(rèn)的在Linux內(nèi)核當(dāng)中已經(jīng)配置上了USB鼠標(biāo)相關(guān)的驅(qū)動(dòng)央碟,所以為了自己編寫(xiě)的驅(qū)動(dòng)程序能加載進(jìn)內(nèi)核和使用税灌,先要去掉內(nèi)核上的USB鼠標(biāo)驅(qū)動(dòng)。進(jìn)入內(nèi)核目錄亿虽,執(zhí)行make menuconfig菱涤,執(zhí)行如下配置:

-> Device Drivers

<span> </span>-> HID Devices

????????????????[ ]USB Human Interface Device (full HID) support

2、設(shè)備驅(qū)動(dòng)編寫(xiě)

a洛勉、分配粘秆、設(shè)置、注冊(cè)一個(gè)usb_driver的結(jié)構(gòu)體變量收毫,為了方便定義了如下一個(gè)結(jié)構(gòu)體:

/* 定義一個(gè)描述USB的結(jié)構(gòu)體 */

struct yl_usbmouse {

? ??????????????dma_addr_t usb_buf_phys; /* 描述分配的緩沖區(qū)的物理地址 */

? ??????????????char *usb_buf_virt; /* 描述分配的緩沖區(qū)的虛擬地址 */

? ??????????????int usb_buf_len; /* 用來(lái)描述緩沖區(qū)的大小 */

? ??????????????struct urb *urb; /* 描述usb的請(qǐng)求塊 */

};

定義一個(gè)usb_driver的結(jié)構(gòu)體攻走,并設(shè)置它:

/* 定義一個(gè)usb_driver的結(jié)構(gòu)體變量 */

static struct usb_driver yl_usb_mouse_driver = {

? ??????????????.name = "yl_usbmouse",

? ??????????????.probe = yl_usb_mouse_probe,

? ? ? ? ? ? ? ? ?.disconnect = yl_usb_mouse_disconnect,

? ??????????????.id_table = yl_usb_mouse_id_table,

};

在入口函數(shù)中注冊(cè)這個(gè)結(jié)構(gòu)體:

/* 模塊的入口函數(shù) */

staticint__inityl_usb_mouse_init(void)

{

????????/* 注冊(cè)一個(gè)usb_driver的結(jié)構(gòu)體變量 */

????????usb_register(&yl_usb_mouse_driver);

? ? ? ? return0;

}

b、分配此再、設(shè)置昔搂、初始化、提交一個(gè)urb输拇,urb是用來(lái)傳遞USB主機(jī)控制器驅(qū)動(dòng)的數(shù)據(jù)摘符。當(dāng)插入的設(shè)備和這個(gè)usb_driver匹配時(shí),它的probe函數(shù)將會(huì)調(diào)用,我們?cè)趐robe函數(shù)當(dāng)中實(shí)現(xiàn)對(duì)urb的一些列操作.

分配一個(gè)urb:

/* 1逛裤、分配一個(gè)usb請(qǐng)求塊 */

g_yl_usbmouse.urb = usb_alloc_urb(0, GFP_KERNEL);

設(shè)置蠢古、初始化這個(gè)urb:

/* 獲取USB設(shè)備的某個(gè)端點(diǎn) */

pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

/* 獲取傳輸?shù)臄?shù)據(jù)的長(zhǎng)度 */

g_yl_usbmouse.usb_buf_len = endpoint->wMaxPacketSize;

/* 分配一塊緩沖區(qū)用來(lái)存放usb鼠標(biāo)的數(shù)據(jù) */

g_yl_usbmouse.usb_buf_virt = usb_alloc_coherent(dev, g_yl_usbmouse.usb_buf_len, GFP_ATOMIC, &g_yl_usbmouse.usb_buf_phys);

/* 2、初始化這個(gè)usb請(qǐng)求塊 */

usb_fill_int_urb(g_yl_usbmouse.urb, dev, pipe, g_yl_usbmouse.usb_buf_virt, g_yl_usbmouse.usb_buf_len, yl_usbmouse_irq, NULL, endpoint->bInterval);

g_yl_usbmouse.urb->transfer_dma = g_yl_usbmouse.usb_buf_phys;

g_yl_usbmouse.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

提交這個(gè)urb:

/* 3别凹、提交這個(gè)usb請(qǐng)求塊 */

usb_submit_urb(g_yl_usbmouse.urb, GFP_KERNEL);

c草讶、usb鼠標(biāo)獲取數(shù)據(jù)的中斷處理函數(shù),這個(gè)函數(shù)是在urb初始化的時(shí)候傳遞進(jìn)來(lái)的回調(diào)函數(shù)炉菲,鼠標(biāo)發(fā)生動(dòng)作時(shí)便會(huì)觸及這個(gè)函數(shù)的調(diào)用堕战,把鼠標(biāo)的數(shù)據(jù)傳遞進(jìn)來(lái)。它的具體的實(shí)現(xiàn)如下所示:

/* usb鼠標(biāo)的中斷處理函數(shù) */

static void yl_usbmouse_irq(struct urb *urb)

{

? ??????int i = 0;

? ??????/* 依次把數(shù)據(jù)打印出來(lái) */

? ??????printk("yl_usbmouse data : ");

? ??????for(i = 0; i < g_yl_usbmouse.usb_buf_len; i++)

? ??????{

? ??????????????printk("0x%x ", g_yl_usbmouse.usb_buf_virt[i]);

? ??????}

? ??????printk("\n");

/* 再次提交urb */

usb_submit_urb(g_yl_usbmouse.urb, GFP_ATOMIC);

}

這個(gè)函數(shù)實(shí)現(xiàn)的功能很簡(jiǎn)單:就是把鼠標(biāo)產(chǎn)生的原始數(shù)據(jù)打印到終端上即可拍霜。

3嘱丢、編譯并安裝驅(qū)動(dòng),在開(kāi)發(fā)板上接入鼠標(biāo)實(shí)驗(yàn)結(jié)果如下:


從上面可以看出祠饺,鼠標(biāo)每操作一次會(huì)一次性產(chǎn)生7個(gè)字節(jié)的數(shù)據(jù)越驻。可以看出這些數(shù)據(jù)本身只是一些普通的數(shù)據(jù)道偷,沒(méi)有任何意義缀旁,那怎么讓鼠標(biāo)產(chǎn)生的這些數(shù)據(jù)發(fā)揮作用呢,就需要將usb鼠標(biāo)和輸入子系統(tǒng)結(jié)合使用勺鸦,才能真正發(fā)揮USB鼠標(biāo)的作用并巍。具體實(shí)現(xiàn)見(jiàn)下文。

附錄:本文實(shí)現(xiàn)的完整的例程源代碼如下所示:

#include <linux/kernel.h>

#include <linux/slab.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/usb/input.h>

#include <linux/hid.h>

/* 定義一個(gè)描述USB的結(jié)構(gòu)體 */

struct yl_usbmouse {

????????????????dma_addr_t usb_buf_phys; /* 描述分配的緩沖區(qū)的物理地址 */

????????????????char *usb_buf_virt; /* 描述分配的緩沖區(qū)的虛擬地址 */

????????????????int usb_buf_len; /* 用來(lái)描述緩沖區(qū)的大小 */

????????????????struct urb *urb; /* 描述usb的請(qǐng)求塊 */

};

/* 定義一個(gè)描述USB結(jié)構(gòu)體的變量 */

static struct yl_usbmouse g_yl_usbmouse;

/* usb鼠標(biāo)的中斷處理函數(shù) */

static void yl_usbmouse_irq(struct urb *urb)

{

????????int i = 0;

/* 依次把數(shù)據(jù)打印出來(lái) */

????????printk("yl_usbmouse data : ");

????????for(i = 0; i < g_yl_usbmouse.usb_buf_len; i++)

????????{

????????????????printk("0x%x ", g_yl_usbmouse.usb_buf_virt[i]);

????????}

????????printk("\n");

/* 再次提交urb */

????????usb_submit_urb(g_yl_usbmouse.urb, GFP_ATOMIC);

}

/* 匹配設(shè)備成功時(shí)調(diào)用的探測(cè)函數(shù) */

static int yl_usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)

{

????????struct usb_device *dev = interface_to_usbdev(intf);

????????struct usb_host_interface *interface;

????????struct usb_endpoint_descriptor *endpoint;

????????int pipe;

/* 獲取接口和端點(diǎn)信息 */

????????interface = intf->cur_altsetting;

????????endpoint = &interface->endpoint[0].desc;

/* 獲取USB設(shè)備的某個(gè)端點(diǎn) */

????????pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

/* 獲取傳輸?shù)臄?shù)據(jù)的長(zhǎng)度 */

????????g_yl_usbmouse.usb_buf_len = endpoint->wMaxPacketSize;

/* 分配一塊緩沖區(qū)用來(lái)存放usb鼠標(biāo)的數(shù)據(jù) */

????????g_yl_usbmouse.usb_buf_virt = usb_alloc_coherent(dev, g_yl_usbmouse.usb_buf_len, GFP_ATOMIC, &g_yl_usbmouse.usb_buf_phys);

/* 1换途、分配一個(gè)usb請(qǐng)求塊 */

????????g_yl_usbmouse.urb = usb_alloc_urb(0, GFP_KERNEL);

/* 2懊渡、初始化這個(gè)usb請(qǐng)求塊 */

????????usb_fill_int_urb(g_yl_usbmouse.urb, dev, pipe, g_yl_usbmouse.usb_buf_virt, g_yl_usbmouse.usb_buf_len, yl_usbmouse_irq, NULL, endpoint->bInterval);

????????g_yl_usbmouse.urb->transfer_dma = g_yl_usbmouse.usb_buf_phys;

????????g_yl_usbmouse.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

/* 3、提交這個(gè)usb請(qǐng)求塊 */

????????usb_submit_urb(g_yl_usbmouse.urb, GFP_KERNEL);

????????return 0;

}

/* usb設(shè)備拔除時(shí)調(diào)用的函數(shù) */

static void yl_usb_mouse_disconnect(struct usb_interface *intf)

{

????????struct usb_device *dev = interface_to_usbdev(intf);

????????usb_kill_urb(g_yl_usbmouse.urb);

????????usb_free_urb(g_yl_usbmouse.urb);

????????usb_free_coherent(dev, g_yl_usbmouse.usb_buf_len, g_yl_usbmouse.usb_buf_virt, g_yl_usbmouse.usb_buf_phys);

}

/* 定義一個(gè)id_table的數(shù)組军拟,當(dāng)usb設(shè)備插入時(shí)進(jìn)行比較和判斷 */

static struct usb_device_id yl_usb_mouse_id_table [] = {

{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

USB_INTERFACE_PROTOCOL_MOUSE) },

{ } /* Terminating entry */

};

/* 定義一個(gè)usb_driver的結(jié)構(gòu)體變量 */

static struct usb_driver yl_usb_mouse_driver = {

????????.name = "yl_usbmouse",

????????.probe = yl_usb_mouse_probe,

????????.disconnect = yl_usb_mouse_disconnect,

????????.id_table = yl_usb_mouse_id_table,

};

/* 模塊的入口函數(shù) */

static int __init yl_usb_mouse_init(void)

{

/* 注冊(cè)一個(gè)usb_driver的結(jié)構(gòu)體變量 */

????????usb_register(&yl_usb_mouse_driver);

????????return 0;

}

/* 模塊的出口函數(shù) */

static void __exit yl_usb_mouse_exit(void)

{

/* 注銷(xiāo)一個(gè)usb_driver的結(jié)構(gòu)體變量 */

????????usb_deregister(&yl_usb_mouse_driver);

}

module_init(yl_usb_mouse_init);

module_exit(yl_usb_mouse_exit);

MODULE_LICENSE("GPL");

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剃执,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子懈息,更是在濱河造成了極大的恐慌肾档,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漓拾,死亡現(xiàn)場(chǎng)離奇詭異阁最,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)骇两,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)姜盈,“玉大人低千,你說(shuō)我怎么就攤上這事。” “怎么了示血?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵棋傍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我难审,道長(zhǎng)瘫拣,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任告喊,我火速辦了婚禮麸拄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘黔姜。我一直安慰自己拢切,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布秆吵。 她就那樣靜靜地躺著淮椰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纳寂。 梳的紋絲不亂的頭發(fā)上主穗,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音毙芜,去河邊找鬼躯概。 笑死鹰椒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播夫壁,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼妇押!你這毒婦竟也來(lái)了拭宁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤对嚼,失蹤者是張志新(化名)和其女友劉穎夹抗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體纵竖,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漠烧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了靡砌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片已脓。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖通殃,靈堂內(nèi)的尸體忽然破棺而出度液,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布堕担,位于F島的核電站已慢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏霹购。R本人自食惡果不足惜佑惠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望齐疙。 院中可真熱鬧膜楷,春花似錦、人聲如沸剂碴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)忆矛。三九已至察蹲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間催训,已是汗流浹背洽议。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漫拭,地道東北人亚兄。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像采驻,于是被迫代替她去往敵國(guó)和親审胚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容