USB設備驅動程序

2020-12-13 電子產品世界
// drivers\hid\usbhid\usbmouse.c

#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"

static struct input_dev *uk_dev;

static char *usb_buf;

static dma_addr_t usb_buf_phys;

static int len;

static struct urb *uk_urb;

static struct usb_device_id usbmouse_as_key_id_table [] = {

{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

USB_INTERFACE_PROTOCOL_MOUSE) },

//{USB_DEVICE(0x1234,0x5678)}, //表示USB設備驅動程序只支持某個廠家生產的某個產品

{ } // Terminating entry

};

static void usbmouse_as_key_irq(struct urb *urb)

{

static unsigned char pre_val;

#if 0

int i;

static int cnt = 0;

printk("data cnt %d: ", ++cnt);

for (i = 0; i < len; i++)

{

printk("x ", usb_buf[i]);

}

printk("\n");

#endif

// USB滑鼠數據含義

* data[0]: bit0-左鍵, 1-按下, 0-鬆開

* bit1-右鍵, 1-按下, 0-鬆開

* bit2-中鍵, 1-按下, 0-鬆開

*

//

if ((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))

{

// 左鍵發生了變化

input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);

input_sync(uk_dev);

}

if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))

{

// 右鍵發生了變化

input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);

input_sync(uk_dev);

}

if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))

{

// 中鍵發生了變化

input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0);

input_sync(uk_dev);

}

pre_val = usb_buf[0];

// 重新提交urb

usb_submit_urb(uk_urb, GFP_KERNEL);

}

static int usbmouse_as_key_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;

interface = intf->cur_altsetting;

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

// a. 分配一個input_dev

uk_dev = input_allocate_device();

// b. 設置

// b.1 能產生哪類事件

set_bit(EV_KEY, uk_dev->evbit);

set_bit(EV_REP, uk_dev->evbit);

// b.2 能產生哪些事件

set_bit(KEY_L, uk_dev->keybit);

set_bit(KEY_S, uk_dev->keybit);

set_bit(KEY_ENTER, uk_dev->keybit);

//c. 註冊

input_register_device(uk_dev);

// d. 硬體相關操作(使用USB總線驅動程序提供的函數進行讀、寫操作)

// 數據傳輸3要素: 源,目的,長度

// 1、源: USB設備的某個端點

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

// 2、長度:

len = endpoint->wMaxPacketSize;

///3、目的:

usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);

// 使用"3要素"

// 首先分配usb request block

uk_urb = usb_alloc_urb(0, GFP_KERNEL);

// 使用"3要素設置urb"

usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);

uk_urb->transfer_dma = usb_buf_phys;

uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

// 使用URB

usb_submit_urb(uk_urb, GFP_KERNEL);

return 0;

}

static void usbmouse_as_key_disconnect(struct usb_interface *intf)

{

struct usb_device *dev = interface_to_usbdev(intf);

//printk("disconnect usbmouse!\n");

usb_kill_urb(uk_urb);

usb_free_urb(uk_urb);

usb_buffer_free(dev, len, usb_buf, usb_buf_phys);

input_unregister_device(uk_dev);

input_free_device(uk_dev);

}

// 1. 分配/設置usb_driver

static struct usb_driver usbmouse_as_key_driver = {

.name = "usbmouse_as_key_",

.probe = usbmouse_as_key_probe,

.disconnect = usbmouse_as_key_disconnect,

.id_table = usbmouse_as_key_id_table, //比較id_table匹配成功以後調用probe函數

};

static int usbmouse_as_key_init(void)

{

// 2. 註冊

usb_register(&usbmouse_as_key_driver);

return 0;

}

static void usbmouse_as_key_exit(void)

{

usb_deregister(&usbmouse_as_key_driver);

}

module_init(usbmouse_as_key_init);

module_exit(usbmouse_as_key_exit);

MODULE_LICENSE("GPL");

=================================================================

現象:把USB設備接到PC

1. 右下角彈出"發現android phone"

2. 跳出一個對話框,提示你安裝驅動程序

問1. 既然還沒有"驅動程序",為何能知道是"android phone"

答1. windows裡已經有了USB的總線驅動程序,接入USB設備後,是"總線驅動程序"知道你是"android phone"

提示你安裝的是"設備驅動程序"

USB總線驅動程序負責:識別USB設備, 給USB設備找到對應的驅動程序

問2. USB設備種類非常多,為什麼一接入電腦,就能識別出來?

答2. PC和USB設備都得遵守一些規範。

比如:USB設備接入電腦後,PC機會發出"你是什麼"?

USB設備就必須回答"我是xxx", 並且回答的語言必須是中文

USB總線驅動程序會發出某些命令想獲取設備信息(描述符),

USB設備必須返回"描述符"給PC

問3. PC機上接有非常多的USB設備,怎麼分辨它們?

USB接口只有4條線: 5V,GND,D-,D+

答3. 每一個USB設備接入PC時,USB總線驅動程序都會給它分配一個編號

接在USB總線上的每一個USB設備都有自己的編號(地址)

PC機想訪問某個USB設備時,發出的命令都含有對應的編號(地址)

問4. USB設備剛接入PC時,還沒有編號;那麼PC怎麼把"分配的編號"告訴它?

答4. 新接入的USB設備的默認編號是0,在未分配新編號前,PC使用0編號和它通信。

問5. 為什麼一接入USB設備,PC機就能發現它?

答5. PC的USB口內部,D-和D+接有15K的下拉電阻,未接USB設備時為低電平

USB設備的USB口內部,D-(表示全速設備12Mbps)或D+(表示高速設備480Mbps)接有1.5K的上拉電阻;它一接入PC,就會把PC USB口的D-或D+拉高,從硬體的角度通知PC有新設備接入

其他概念:

1. USB是主從結構的

所有的USB傳輸,都是從USB主機這方發起;USB設備沒有"主動"通知USB主機的能力。

例子:USB滑鼠滑動一下立刻產生數據,但是它沒有能力通知PC機來讀數據,只能被動地等得PC機來讀。

2. USB的傳輸類型:

a. 控制傳輸:可靠,時間有保證,比如:USB設備的識別過程

b. 批量傳輸: 可靠, 時間沒有保證, 比如:U盤

c. 中斷傳輸:可靠,實時,比如:USB滑鼠

d. 實時傳輸:不可靠,實時,比如:USB攝像頭

3. USB傳輸的對象:端點(endpoint)

我們說"讀U盤"、"寫U盤",可以細化為:把數據寫到U盤的端點1,從U盤的端點2裡讀出數據

除了端點0外,每一個端點只支持一個方向的數據傳輸

端點0用於控制傳輸,既能輸出也能輸入

4. 每一個端點都有傳輸類型,傳輸方向

5. 術語裡、程序裡說的輸入(IN)、輸出(OUT) "都是" 基於USB主機的立場說的。

比如滑鼠的數據是從滑鼠傳到PC機, 對應的端點稱為"輸入端點"

6. USB總線驅動程序的作用

a. 識別USB設備

b. 查找並安裝對應的設備驅動程序

c. 提供USB讀寫函數

USB驅動程序框架:

app:

-------------------------------------------

內核 --------------------------------------

USB總線驅動程序 // 1. 識別, 2. 找到匹配的設備驅動, 3. 提供USB讀寫函數 (它不知道數據含義)

-------------------------------------------

USB主機控制器

UHCI OHCI EHCI

硬體 -----------

USB設備

UHCI: intel, 低速(1.5Mbps)/全速(12Mbps)

OHCI: microsoft 低速/全速

EHCI: 高速(480Mbps)

USB總線驅動程序的作用

1. 識別USB設備

1.1 分配地址

1.2 並告訴USB設備(set address)

1.3 發出命令獲取描述符

描述符的信息可以在include\linux\usb\Ch9.h看到

2. 查找並安裝對應的設備驅動程序

3. 提供USB讀寫函數

把USB設備接到開發板上,看輸出信息:

usb 1-1: new full speed USB device using s3c2410-ohci and address 2

usb 1-1: configuration #1 chosen from 1 choice

scsi0 : SCSI emulation for USB Mass Storage devices

scsi 0:0:0:0: Direct-Access HTC Android Phone 0100 PQ: 0 ANSI: 2

sd 0:0:0:0: [sda] Attached SCSI removable disk

拔掉

usb 1-1: USB disconnect, address 2

再接上:

usb 1-1: new full speed USB device using s3c2410-ohci and address 3

usb 1-1: configuration #1 chosen from 1 choice

scsi1 : SCSI emulation for USB Mass Storage devices

scsi 1:0:0:0: Direct-Access HTC Android Phone 0100 PQ: 0 ANSI: 2

sd 1:0:0:0: [sda] Attached SCSI removable disk

在內核目錄下搜:

grep "USB device using" * -nR

drivers/usb/core/hub.c:2186: "%s %s speed %sUSB device using %s and address %d\n",

hub_irq

kick_khubd

hub_thread

hub_events

hub_port_connect_change

udev = usb_alloc_dev(hdev, hdev->bus, port1);

dev->dev.bus = &usb_bus_type;

choose_address(udev); // 給新設備分配編號(地址)

hub_port_init // usb 1-1: new full speed USB device using s3c2410-ohci and address 3

hub_set_address // 把編號(地址)告訴USB設備

usb_get_device_descriptor(udev, 8); // 獲取設備描述符

retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

usb_new_device(udev)

err = usb_get_configuration(udev); // 把所有的描述符都讀出來,並解析

usb_parse_configuration

device_add // 把device放入usb_bus_type的dev鍊表,

// 從usb_bus_type的driver鍊表裡取出usb_driver,

// 把usb_interface和usb_driver的id_table比較

// 如果能匹配,調用usb_driver的probe

1. 分配/設置usb_driver結構體

.id_table

.probe

.disconnect

2. 註冊

測試1th/2th:

1. make menuconfig去掉原來的USB滑鼠驅動

-> Device Drivers

-> HID Devices

<> USB Human Interface Device (full HID) support

2. make uImage 並使用新的內核啟動

3. insmod usbmouse_as_key.ko

4. 在開發板上接入、拔出USB滑鼠

測試3th:

1. insmod usbmouse_as_key.ko

2. ls /dev/event*

3. 接上USB滑鼠

4. ls /dev/event*

5. 操作滑鼠觀察數據

測試4th:

1. insmod usbmouse_as_key.ko

2. ls /dev/event*

3. 接上USB滑鼠

4. ls /dev/event*

5. cat /dev/tty1 然後按滑鼠鍵

6. hexdump /dev/event0

相關焦點

  • USB驅動程序框架搭建
    把USB設備接到開發板上,看輸出信息:usb 1-1: new full speed USB device using s3c2410-ohci and address 2usb 1-1: configuration #1 chosen from 1 choicescsi0 : SCSI
  • USB萬能鍵盤驅動程序
    USB萬能鍵盤驅動程序是是一款不僅對有線鍵盤有效,還能用於無線鍵盤的驅動程序,匹配率非常高,支持三星、聯想、PS等設備,,可以解決大部分的鍵盤驅動問題,適合各種Windows作業系統安裝。
  • USB萬能驅動
    usb萬能驅動有助於解決USB設備驅動程序無法正確使用的諸多問題,同時也是解決不同作業系統USB設備驅動程序問題的通用工具。
  • USB2.0萬能驅動
    萬能驅動是所有usb設備的萬能驅動程序,本站提供usb驅動下載,此usb驅動解決很多人的usb設備因為太多或不能正常使用的問題。usb2.0萬能驅動軟體截圖1usb2.0萬能驅動軟體截圖2軟體功能USB2.0萬能驅動主要用於解決一些常見的USB設備驅動問題,如接上電腦的滑鼠無法使用、鍵盤接上電腦無反應
  • USB萬能驅動下載 USB2.0萬能驅動下載
    《USB萬能驅動下載》下載(點擊下載)    《USB2.0萬能驅動下載》下載(點擊下載)        USB設備的萬能驅動,很多人的usb設備因為太多或沒有不能正常使用設備    usb萬能驅動下載|usb萬能驅動程序|usb萬能驅動|usb2.0萬能驅動|usb2.0驅動|usb驅動    USB萬能驅動下載J-01 FOR Windows的適用產品:·華碩 A7N8X       ·Intel D865PERL ·微星 865PE Neo2-PLS ·青雲 K8X800 Pro Ⅱ
  • Linux環境下USB的原理、驅動和配置
    Linux內核支持兩種主要類型的USB驅動程序:宿主系統上的驅動程序和設備上的驅動程序,從宿主的觀點來看(一個普通的宿主也就是一個PC機),宿主系統的USB設備驅動程序控制插入其中的USB設備,而USB設備的驅動程序控制該設備如何作為一個USB設備和主機通信。
  • 基於USB設備的Linux網絡驅動程序開發
    網絡驅動程序和網絡硬體設備實現網絡協議棧中的數據鏈路層和物理層,對上層協議提供支持,是網絡協議棧的重要組成部分,對Linux的網絡性能起著決定作用。本文主要討論基於USB總線的 Linux網絡驅動程序的設計和實現方法。2. Linux體系結構出於穩定性和安全性的考慮,現代處理器往往具有至少兩個運行級別。
  • 基於USB2.0控制晶片ISP1581的USB設備驅動程序
    USB設備驅動程序的模型  USB設備驅動程序是一種典型的WDM(Windows Driver Model)驅動程序,其程序模型如圖1所示。用戶應用程式工作在Windows作業系統的用戶模式層,它不能直接訪問USB設備,當需要訪問時,通過調用作業系統的API(Application programming interface)函數生成I/O請求信息包(IRP),IRP被傳輸到工作於內核模式層的設備驅動程序,並通過驅動程序完成與UBS外設通信。
  • usb總線驅動粗略過程(OHCI協議)
    usb總線驅動分類:UHCI: intel公司製作 適用於低速/全速設備OHCI:microsoft 適用於低速/全速設備EHCI:
  • 總線,設備,和驅動的關聯
    的存在,讓struct bus_type與兩個鍊表聯繫了起來,一個是 devices 的鍊表,一個是drivers 的鍊表,也就是說,知道一條總線所對應的數據結構,就可以找到這條總線所關聯的設備有哪些,又有哪些支持這類設備的驅動程序.
  • 電腦usb無法識別提示無法識別的usb設備怎麼辦?
    當以前使用過該usb設備,現在不可以用的話,驅動問題就可以簡單的排除掉。筆者公司最近有一臺電腦出現了usb無法識別的故障,買的一個新的usb滑鼠用了不到2個月,昨天突然在電腦中沒放應了,滑鼠指示燈一閃閃的,電腦桌面右小腳有提示:「無法識別的usb設備」,如下圖:
  • USB3.0驅動
    USb3.0驅動轉上它就可以驅動usb 3.0設備,能夠適應於大部份主板,幫助用戶解決usb3.0和電腦無法正常通訊的問題。
  • USB 接口驅動程序開發
    2.1 USB 驅動程序結構  1) USB 驅動程序體系結構  運行在核心態的USB 驅動程序是基於WIN32 驅動程序模型WDM(Windows Driver Model)的,它採用分層驅動程序模型,由USB 總線驅動程序和USB 功能驅動程序兩部分組成, 總線驅動程序由作業系統提供, 用戶只需要編寫相應的功能驅動程序即可
  • SEP6200平臺上Linux內核的USB OTG驅動設計
    OTG設備驅動程序主要由USB目標設備軟體包和USB主設備軟體包構成。OTG驅動通過連接器中「ID」信號的不同連接,根據SRP和HNP協議的內部機制,確定使用USB主設備軟體包還是USB目標設備軟體包。圖2是OTG沒備驅動程序架構框圖。
  • 為什麼手機USB驅動每次都要安裝?
    當手機與電腦連接的時候,用的usb連接線而不能馬上被識別的話,就需要安裝驅動了.萬能驅動也只能大部份手機適用,有一些手機也不行的,要用PC套件才行。 現在多數的手機,如果僅用於和電腦連接傳輸數據的話,和電腦連接後,系統自動就安裝了。
  • 如何禁用Linux機器上的USB存儲設備
    在現如今,隨著網際網路科技飛速的發展,為了保護數據不被洩漏,我們使用軟體和硬體防火牆來限制外部未經授權的訪問,但是數據洩露也可能發生在內部,為了消除這種可能性,機構會限制和監測訪問網際網路,同時禁用USB存儲設備。
  • 基於STM32的 USB設計 --單片機程序篇
    本文引用地址:http://www.eepw.com.cn/article/170827.htm  當usb設備接入到主機時,主機開始枚舉usb設備,並向usb設備發出指令要求獲取usb設備的相關描述信息,其中包括設備描述(device descriptor)、配置描述(configuration descriptor)、接口描述(interface descriptor
  • 安裝Win7系統提示'缺少所需的CD/DVD驅動器設備驅動程序'解決方法
    而在系統安裝的時候,可能會遇到各類小問題,當然這與win7停止服務無關,那就是在安裝Win7原版系統的過程中會提示「缺少所需的CD/DVD驅動器設備驅動程序」,相信經常安裝Win7原版系統的朋友可能遇到過,如果遇到這個提示,系統安裝就會無法繼續下去。那麼對於這個問題是什麼原因導致的,我們要如何解決?下面裝機之家分享一下安裝Win7系統提示'缺少所需的CD/DVD驅動器設備驅動程序'解決方法。
  • win10 usb3.0驅動
    win10 usb3.0驅動 萬能驅動 大小: 8.7M
  • 無法識別usb設備怎麼辦 五大方法來解決
    這裡我們介紹的usb主要以電腦周邊產品為介紹,如usb滑鼠,鍵盤,音箱等。  usb無法識別我們主要是以下幾個思路出發,首先如果您是初次在一臺電腦上,當出現usb無法識別的時候,我們需要做的是分析清楚到底是usb設備產品的問題還是電腦或線路的問題以及是否存在驅動問題。當以前使用過該usb設備,現在不可以用的話,驅動問題就可以簡單的排除掉。