新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 嵌入式Linux下USB驅(qū)動(dòng)程序的設(shè)計(jì)

        嵌入式Linux下USB驅(qū)動(dòng)程序的設(shè)計(jì)

        作者: 時(shí)間:2013-10-08 來(lái)源:網(wǎng)絡(luò) 收藏

          (2)probe()函數(shù)

          probe()函數(shù)的編寫(xiě)格式為:static void * skel_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);需要確認(rèn)插入的設(shè)備是否可以被接受,如果不接受,或者在初始化的過(guò)程中發(fā)生任何錯(cuò)誤,probe()函數(shù)返回一個(gè)NULL值。否則返回一個(gè)含有設(shè)備狀態(tài)的指針,通過(guò)這個(gè)指針,就可以訪問(wèn)所有結(jié)構(gòu)中的回調(diào)函數(shù)。

          在里,最后一點(diǎn)是要注冊(cè)devfs(設(shè)備文件系統(tǒng))。首先創(chuàng)建一個(gè)緩沖用來(lái)保存那些被發(fā)送給設(shè)備的數(shù)據(jù)和那些從設(shè)備上接受的數(shù)據(jù),并為設(shè)備傳輸創(chuàng)建一個(gè)請(qǐng)求塊(URB)以向設(shè)備寫(xiě)入數(shù)據(jù),同時(shí) urb 被初始化,然后在devfs子系統(tǒng)中注冊(cè)設(shè)備,允許devfs用戶訪問(wèn)USB的設(shè)備。注冊(cè)過(guò)程如下:

          /* initialize the devfs node for this device and register it */

          sprintf(name, "skel%d", skel->minor);

          skel->devfs = devfs_register (usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR, USB_SKEL_MINOR_BASE + skel->minor, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, skel_fops, NULL);

          如果devfs_register函數(shù)失敗, devfs子系統(tǒng)會(huì)將此情況報(bào)告給用戶。如果設(shè)備從USB總線拔掉,設(shè)備指針會(huì)調(diào)用disconnect 函數(shù)。驅(qū)動(dòng)程序就需要清除那些被分配了的所有私有數(shù)據(jù)、關(guān)閉urbs,并且從devfs上注銷調(diào)自己。調(diào)用函數(shù)的格式為:

          /* remove our devfs node */

          devfs_unregister(skel->devfs);

          現(xiàn)在,skeleton驅(qū)動(dòng)就已經(jīng)和設(shè)備綁定上了,任何用戶態(tài)程序要操作此設(shè)備都可以通過(guò)file_operations結(jié)構(gòu)所定義的函數(shù)進(jìn)行了。

          (3)open()、write()和read()函數(shù)

          首先,要打開(kāi)此設(shè)備。在open()函數(shù)中MODULE_INC_USE_COUNT 宏是一個(gè)關(guān)鍵,它起到一個(gè)計(jì)數(shù)的作用,有一個(gè)用戶態(tài)程序打開(kāi)一個(gè)設(shè)備,計(jì)數(shù)器就加1。例如,以模塊方式加入一個(gè)驅(qū)動(dòng),若計(jì)數(shù)器不為零,就說(shuō)明仍然有用戶程序在使用此驅(qū)動(dòng),這時(shí)候,就不能通過(guò)rmmod命令卸載驅(qū)動(dòng)模塊了。

          /* increment our usage count for the module */

          MOD_INC_USE_COUNT;

          ++skel->open_count;

          /* save our object in the file's private structure */

          file->private_data = skel;

          當(dāng)open完設(shè)備后,read()、write()函數(shù)就可以收、發(fā)數(shù)據(jù)了。

          read()函數(shù)首先從open()函數(shù)中保存的fi。

          Write()函數(shù)和read()函數(shù)是完成驅(qū)動(dòng)對(duì)讀寫(xiě)等操作的響應(yīng)。在skel_write中,一個(gè)FILL_BULK_URB函數(shù),就完成了urb 系統(tǒng)callbak和的skel_write_bulk_callback之間的聯(lián)系。注意skel_write_bulkcallback是中斷方式,所以要注意時(shí)間不能太久,本程序中它就只是報(bào)告一些urb的狀態(tài)等。 read 函數(shù)與write 函數(shù)稍有不同在于:程序并沒(méi)有用urb 將數(shù)據(jù)從設(shè)備傳送到驅(qū)動(dòng)程序,而是用usb_bulk_msg 函數(shù)代替,這個(gè)函數(shù)能夠不需要?jiǎng)?chuàng)建urbs 和操作urb函數(shù)的情況下,來(lái)發(fā)送數(shù)據(jù)給設(shè)備,或者從設(shè)備來(lái)接收數(shù)據(jù)。調(diào)用usb_bulk_msg函數(shù)并傳到一個(gè)存儲(chǔ)空間,用來(lái)緩沖和放置驅(qū)動(dòng)收到的數(shù)據(jù),若沒(méi)有收到數(shù)據(jù)表示失敗并返回一個(gè)錯(cuò)誤信息。

          usb_bulk_msg函數(shù):當(dāng)對(duì)usb設(shè)備進(jìn)行一次讀或者寫(xiě)時(shí),usb_bulk_msg 函數(shù)是非常有用的; 然而, 當(dāng)需要連續(xù)地對(duì)設(shè)備進(jìn)行讀/寫(xiě)時(shí),應(yīng)建立一個(gè)自己的urbs,同時(shí)將urbs 提交給USB子系統(tǒng)。

          skel_disconnect函數(shù):當(dāng)釋放設(shè)備文件句柄時(shí),這個(gè)函數(shù)會(huì)被調(diào)用。

          MOD_DEC_USE_COUNT宏也會(huì)被調(diào)用到(和MOD_INC_USE_COUNT剛好對(duì)應(yīng),它減少一個(gè)計(jì)數(shù)器),首先確認(rèn)當(dāng)前是否有其他的程序正在訪問(wèn)這個(gè)設(shè)備,如果是最后一個(gè)用戶在使用,可以關(guān)閉任何正在發(fā)生的寫(xiě),操作如下:

          /* decrement our usage count for the device */

          --skel->open_count;

          if (skel->open_count = 0) {

          /* shutdown any bulk writes that might be

          going on */

          usb_unlink_urb (skel->write_urb);

          skel->open_count = 0;

          }

          /* decrement our usage count for the module */

          MOD_DEC_USE_COUNT;

          USB設(shè)備可以在任何時(shí)間點(diǎn)從系統(tǒng)中取走,即使程序目前正在訪問(wèn)它。USB驅(qū)動(dòng)程序必須要能夠很好地處理解決此問(wèn)題,它需要能夠切斷任何當(dāng)前的讀寫(xiě),同時(shí)通知用戶空間程序:USB設(shè)備已經(jīng)被取走。

          2.設(shè)計(jì)實(shí)例

          下面通過(guò)介紹鍵盤(pán)飛梭驅(qū)動(dòng)程序的實(shí)例來(lái)讓讀者更好的理解USB驅(qū)動(dòng)程序的工作原理,實(shí)現(xiàn)代碼如下:

          /*需要的頭文件*/

          #include linux/kernel.h>

          #include linux/slab.h>

          #include linux/module.h>

          #include linux/input.h>

          #include linux/init.h>

          #include linux/usb.h>

          #include linux/kbd_ll.h>

          /* 驅(qū)動(dòng)程序版本信息*/

          #define DRIVER_VERSION ""

          #define DRIVER_AUTHOR " TGE HOTKEY "

          #define DRIVER_DESC "USB HID Tge hotkey driver"

          #define USB_HOTKEY_VENDOR_ID 0x07e4

          #define USB_HOTKEY_PRODUCT_ID 0x9473

          /*廠商和產(chǎn)品ID信息就是/proc/bus/usb/devices中看到的值,通過(guò)cat/proc/bus/usb/devices得到當(dāng)前系統(tǒng)探測(cè)到的USB總線上的設(shè)備信息。它包括Vendor、ProdID、Product等*/

          MODULE_AUTHOR( DRIVER_AUTHOR );

          MODULE_DESCRIPTION( DRIVER_DESC );

          /*此結(jié)構(gòu)來(lái)自內(nèi)核中drivers/usb/usbkbd.c*/

          struct usb_kbd {

          struct input_dev dev;

          struct usb_device *usbdev;

          unsigned char new[8];

          unsigned char old[8];

          struct urb irq, led;

          struct usb_ctrlrequest dr;

          unsigned char leds, newleds;

          char name[128];

          int open;

          };

          static void usb_kbd_irq(struct urb *urb) /*urb為USB請(qǐng)求塊*/

          {

          struct usb_kbd *kbd = urb->context;

          int *new;

          new = (int *) kbd->new;

          if(kbd->new[0] == (char)0x01)

          {

          if(((kbd->new[1]>>4)0x0f)!=0x7)

          {

          handle_scancode(0xe0,1);

          handle_scancode(0x4b,1);

          handle_scancode(0xe0,0);

          handle_scancode(0x4b,0);

          }

        linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

        linux相關(guān)文章:linux教程




        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 丹凤县| 民和| 广丰县| 阿拉善盟| 柘荣县| 康乐县| 乐业县| 黑山县| 周宁县| 延寿县| 天全县| 麻城市| 仁化县| 江陵县| 建平县| 静乐县| 黔东| 靖安县| 武乡县| 寻甸| 莲花县| 六盘水市| 新安县| 固阳县| 廉江市| 竹北市| 兴安县| 绥江县| 安义县| 吴川市| 庆城县| 大化| 浦江县| 延安市| 车险| 丁青县| 谢通门县| 称多县| 南开区| 兴义市| 长葛市|