日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

USB驅(qū)動程序開發(fā)全程

 lchjczw 2012-05-04

編寫USB驅(qū)動程序步驟:
1所有usb驅(qū)動都必須創(chuàng)建主要結(jié)構(gòu)體struct usb_driver
struct usb_driver
->struct module *owner
   (有他可正確對該驅(qū)動程序引用計數(shù),應(yīng)為THIS_MODULE)
->const char *name
   (驅(qū)動名字,運行時可在查看 /sys/bus/usb/drivers/)
->const struct usb_device_id *id_table
   (包含該驅(qū)動可支持的所有不同類型的驅(qū)動設(shè)備,沒添探測回調(diào)函數(shù)不會被調(diào)用)
->int (*probe)(struct usb_interface *intf,const struct usb_device_id *id)
   (usb驅(qū)動探測函數(shù),確認(rèn)后struct usb_interface 應(yīng)恰當(dāng)初始化,然后返0,如果出錯則返負(fù)值)
->void(*disconnect)(struct usb_interface *intf)
   (當(dāng)struct usb_interface 被從系統(tǒng)中移除或驅(qū)動正從usb核心中卸載時,usb核心將調(diào)用此函數(shù))
代碼實例:
   static struct usb_driver skel_driver={
    .owner = THIS_MODULE,
    .name = "skeleton",
    .id_table = skel_table,
    .probe = skel_probe,
    .disconnect = skel_disconnect,
    };
  

2usb_register()注冊將struct usb_driver 注冊到usb核心,傳統(tǒng)是在usb驅(qū)動程序模塊初始化代碼中完成該工作的
static int __init usb_skel_init(void)
{
...
usb_register(&skel_driver);
...
}

3struct usb_device_id usb核心用該表判斷哪個設(shè)備該使用哪個驅(qū)動程序,熱插拔腳本使用它來確定當(dāng)一個特定的設(shè)備插入到系統(tǒng)時該自動裝載哪個驅(qū)動程序。
->__u16 match_flags(確定設(shè)備和結(jié)構(gòu)體中下列字段中哪一個相匹配)
->__u16 idVendor(設(shè)備的usb制造商id)
->__u16 idProduct(設(shè)備的usb產(chǎn)品id)

4USB骨架程序的關(guān)鍵幾點如下:
1. USB驅(qū)動的注冊和注銷
   Usb驅(qū)動程序在注冊時會發(fā)送一個命令給usb_register,通常在驅(qū)動程序的初始化函數(shù)里。
   當(dāng)要從系統(tǒng)卸載驅(qū)動程序時,需要注銷usb子系統(tǒng)。即需要usb_unregister 函數(shù)處理。
2 當(dāng)usb設(shè)備插入時,為了使linux-hotplug(Linux中PCI、USB等設(shè)備熱插拔支持)系統(tǒng)自動裝載驅(qū)動程序,你需要創(chuàng)建一個MODULE_DEVICE_TABLE。代碼如下(這個模塊僅支持某一特定設(shè)備):
   static struct usb_device_id skel_table [] = {
    { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
    { } /* Terminating entry */};
    MODULE_DEVICE_TABLE (usb, skel_table);
   USB_DEVICE宏利用廠商ID和產(chǎn)品ID為我們提供了一個設(shè)備的唯一標(biāo)識。當(dāng)系統(tǒng)插入一個ID匹配的USB設(shè)備到USB總線時,驅(qū)動會在USB core中注冊。驅(qū)動程序中probe 函數(shù)也就會被調(diào)用。usb_device 結(jié)構(gòu)指針、接口號和接口ID都會被傳遞到函數(shù)中。
3 static void * skel_probe(struct usb_device *dev,unsigned int ifnum, const struct usb_device_id *id)
   驅(qū)動程序需要確認(rèn)插入的設(shè)備是否可以被接受,如果不接受,或者在初始化的過程中發(fā)生任何錯誤,probe函數(shù)返回一個NULL值。否則返回一個含有設(shè)備驅(qū)動程序狀態(tài)的指針。通過這個指針,就可以訪問所有結(jié)構(gòu)中的回調(diào)函數(shù)。
4 在骨架驅(qū)動程序里,最后一點是我們要注冊devfs。我們創(chuàng)建一個緩沖用來保存那些被發(fā)送給usb設(shè)備的數(shù)據(jù)和那些從設(shè)備上接受的數(shù)據(jù),同時USB urb 被初始化,并且我們在devfs子系統(tǒng)中注冊設(shè)備,允許devfs用戶訪問我們的設(shè)備。注冊過程如下:

   /* 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ù)失敗,不用擔(dān)心,devfs子系統(tǒng)會將此情況報告給用戶。
當(dāng)然最后,如果設(shè)備從usb總線拔掉,設(shè)備指針會調(diào)用disconnect 函數(shù)。驅(qū)動程序就需要清除那些被分配了的所有私有數(shù)據(jù)、關(guān)閉urbs,并且從devfs上注銷調(diào)自己。
   /* remove our devfs node */devfs_unregister(skel->;devfs);

5其他
1 struct usb_host_endpoint(描述usb端點)
   →(包含) struct usb_endpoint_descriptor(含真正端點信息,數(shù)據(jù)格式,是真正驅(qū)動關(guān)心的字段)
   端點描述符:
   bEndpointAddress = 81(in)(第8位為1是輸入設(shè)備)(usb的端點地址,包含端點方向)
   bmAttibutes = 03(interrupt)(端點類型,為中斷傳輸)
   wMaxPacketSize = 0008(每次傳8個字節(jié))(端點每次可處理最大字節(jié)長度)
   bInterval = 08(8ms)(如端點為中斷,該值為輪詢間隔)
2 usb端點捆綁為接口,usb接口只處理一種usb邏輯連接,如鼠標(biāo)鍵盤等.
   一個usb設(shè)備可有多接口,usb揚聲器:一個usb鍵盤用于按鍵,一個usb音頻流,則需兩個不同的驅(qū)動程序。
   usb驅(qū)動 通常將struct usb_interface 轉(zhuǎn)成 struct usb_device 用函數(shù) interface_to_usbdev轉(zhuǎn)
3 struct usb_interface 描述usb接口
   →struct usb_host_interface * altsetting(接口結(jié)構(gòu)體數(shù)組,包含所有可能用于該接口的可選設(shè)置)
    →struct usb_host_endpoint
   →unsigned num_altsetting(可選設(shè)置的數(shù)量)
   →struct usb_host_interface * cur_altsetting(接口當(dāng)前活動設(shè)置)
   →int minor(usb核心分配給接口的次設(shè)備號,成功調(diào)用usb_register_dev有效)
4 usb設(shè)備非常復(fù)雜,由許多不同邏輯單元組成,簡單關(guān)系如下:
   設(shè)備通常有一個以上的配置
   配置經(jīng)常有一個以上接口
   接口通常有一個以上設(shè)置
   接口通常有一個以上端點
   設(shè)備描述-》配置描述-》接口描述-》端點描述
5 usb sysfs設(shè)備命名方案
   根集線器-集線器端口號:配置。接口
   對于usb hub樹中層次更高的字樹命名方案
   根集線器-集線器端口號-集線器端口號:配置。接口
6 linux內(nèi)核的代碼通過一個成為urb(usb請求塊)和所有usb設(shè)備通信.    用struct urb描述(include/linux/usb.h中定義)
   ->urb用異步同usb設(shè)備特定usb端點發(fā)送/接收數(shù)據(jù),使用類似網(wǎng)絡(luò)代碼中的struct skbuff
   -> urb 被動態(tài)創(chuàng)建,隨時可被驅(qū)動程序或usb核心取消,內(nèi)部有引用計數(shù),可被多次調(diào)用,使他們可在最后一個使用者釋放他們時自動地銷毀
   -> urb使得流處理或其他復(fù)雜的重疊的通信成為可能,獲得高數(shù)據(jù)傳輸速度。
   ->usb_alloc_urb() 創(chuàng)建urb包 usb_free_urb() 釋放urb包
   ->usb_fill_int_urb()正確初始化將發(fā)送到usb設(shè)備的中斷端點urb
     usb_fill_bulk_urb() .. .. .. ... 批量傳輸端點urb
     usb_fill_control_urb() .. .. .. ... 控制端點urb
     等時urb在提交給核心時必須手動初始化(很不幸,沒函數(shù))
   ->usb_submit_urb()urb被usb驅(qū)動正確創(chuàng)建和初始化后,就可提交到usb核心,發(fā)送到usb設(shè)備上了,如果調(diào)用成功,函數(shù)返0,urb控制權(quán)轉(zhuǎn)給usb核心
   ->usb_kill_urb() or usb_unlink_urb()取消已經(jīng)被提交給核心的urb


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多