USB驅動程式之滑鼠用做鍵盤
我們還是接著來看看我們的例子程式 usbmouse.c
這裡它接著判斷了他是不是滑鼠,
得到它的usb_host_interface,interface=intf->cur_alsetting就是當前介面的設定
這裡有個介面描述符,我們來看看介面描述符
介面描述符裡面有個__u8 bNumEndpoints端點的個數
這個端點的個數是除了端點0之外還有多少個端點
這裡首先判斷如果除了端點0之外,端點個數不是1的話就返回錯誤,不是我能夠支援的裝置
如果只有一個端點,那就把這個端點放到endpoint這個陣列裡面,這個並不是端點0,而是除了端點0之外第一個端點
得到一個端點描述符
if(!usb_endpoint_is_int_in(endpoint))這個是指如果他不是中斷類似的端點,不是輸入端點,注意了我們這裡輸入輸出是站在主機的角度說的,站在主機角度,我們的滑鼠是輸入裝置,資料是輸入給主機的。如果不是輸入型別端點,中斷型別端點,就返回一個錯誤。這個怎麼回事呢,怎麼知道你是不是中斷輸入端點呢,端點描述符裡面不是有個屬性嗎,屬性裡面就是表示它是什麼型別的,方向。
我們在我們自己的程式裡就不做判斷了,我們回到我們的主題,我們就認為就是一個滑鼠,
我們硬體相關的操作要用到USB匯流排驅動程式裡面的讀寫函式
我們只需要記住資料傳輸3要素,把這個三要素找出就可以實現這一點
1.源 在我們這裡是USB裝置的某個端點
這個就是源
我們來看看usb_rcvintpipe這個巨集
這個源是個整數,pipe_interrupt是指中斷型別端點,USB_DIR_IN是端點的方向。我們進入__create_pipe(dev,endpoint)這個巨集
devnum是裝置的地址,endpoint是端點的地址也是端點編號
2.目的
我們從USB裝置裡面讀資料,讀到哪裡去,肯定讀到緩衝區,但這個緩衝區肯定不能用kmallioc函式,
用這函式
返回一個void* 是個虛擬地址
最後一個引數是指的實體地址
3.長度就是我們的端點描述符最大包大小
使用我們三要素
怎麼用呢,看一下我們的例子
分配一個urb urb是什麼意思呢,就是USB請求快的意思 usb request block
然後使用這個3要素設定我們的urb 來看我們的例子程式
看看這個函式原型
第一個引數是urb,第二個引數是裝置,第三個引數是源,第四個引數是目的,第五個引數是長度 ,第6個引數是完成函式,第7個引數是給那個完成函式用的,我們不需要,第8個引數是查詢的頻率。
我們前面說過usb裝置不能打斷主機控制器,只能讓主機控制器查詢,不斷的去查詢,等有資料之後才能中斷CPU。當它得到資料之後,匯流排驅動程式就會呼叫這個complete_fn這個函式,查詢多頻繁呢就是int interval 。
端點描述符裡面有個binterval就是的
我們USB主機控制器,得到資料之後是往某個地方寫,但是我們主機控制器沒那麼聰明,所以我們要告訴它,例子裡面
第一句就是告訴實體地址,下面一句是設定某些標記
我們構造了URB 就要使用urb
怎麼使用urb
使用usb_submit_urb提交urb
usb滑鼠資料含義
我們前面說框架的時候說過,USB裝置驅動程式知道資料的含義,USB匯流排驅動程式提供識別裝置,給裝置找到驅動,提供讀寫函式,但是不知道資料的含義。這些資料需要由裝置驅動程式來解析,
data[0] bit 0表示左鍵,1表示按下,0表示鬆開
bit 1表示右鍵,1表示按下,0表示鬆開
bit 2表示中鍵 1表示按下,0表示鬆開
程式碼如下
#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 *usb_key;
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) },
{ } /* Terminating entry */
};
static void usbmouse_as_key_irq(struct urb *urb)
{
static unsigned char pre_val;
/* USB滑鼠資料含義
* data[0]: bit0-左鍵, 1-按下, 0-鬆開
* bit1-右鍵, 1-按下, 0-鬆開
* bit2-中鍵, 1-按下, 0-鬆開
*/
if((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))
{
//左鍵發生了變化
input_event(usb_key, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
input_sync(usb_key);
}
if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))
{
/* 右鍵發生了變化 */
input_event(usb_key, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
input_sync(usb_key);
}
if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))
{
/* 中鍵發生了變化 */
input_event(usb_key, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0);
input_sync(usb_key);
}
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_device結構體*/
usb_key=input_allocate_device();
/*b.設定*/
/*b.1能產生哪類事件*/
//能夠產生按鍵類事件
set_bit(EV_KEY,usb_key->evbit);
set_bit(EV_REP,usb_key->evbit);//能夠產生重複類事件,就是隻我們按下一個字母不動就會不斷的列印出來
/*b.2能產生這類事件的哪些事件*/
set_bit(KEY_L,usb_key->keybit);
set_bit(KEY_S,usb_key->keybit);
set_bit(KEY_ENTER,usb_key->keybit);
/*c.註冊*/
input_register_device(usb_key);
/*d.硬體相關的操作*/
/*資料傳輸3要素 源,目的,長度*/
/*1.源 :USB裝置的某個端點*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
//長度 等於端點描述符的最大包大小
len=endpoint->wMaxPacketSize;
/*2.目的 */
usb_buf = usb_alloc_coherent(dev,len, GFP_ATOMIC, &usb_buf_phys);
//使用三要素
/*分配一個urb 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);
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
input_unregister_device(usb_key);
input_free_device(usb_key);
}
/*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,
};
static int usbmouse_as_key_init(void)
{
/*2.註冊usb_driver結構體*/
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");
MODULE_AUTHOR("EIGHT");
測試結構如下圖
相關文章
- 驅動開發 鍵盤過濾驅動程式-- 傳統的鍵盤過濾
- c++ 鍵盤/滑鼠互動C++
- usb驅動程式初步編寫
- 滑鼠、鍵盤事件事件
- win10鍵盤驅動怎麼修復_win10鍵盤驅動一鍵修復Win10
- 鍵盤驅動怎麼重新安裝 win10鍵盤驅動重新安裝的方法Win10
- garmin USB: linux USB host驅動Linux
- 電腦鍵盤怎麼代替滑鼠 win10鍵盤代替滑鼠Win10
- Python-模擬滑鼠鍵盤動作Python
- 鍵盤控制滑鼠 windows QtWindowsQT
- usb驅動開發1之學習準備
- 鍵盤滑鼠共享效率工具-Synergy
- Linux 虛擬滑鼠,鍵盤Linux
- 鍵盤滑鼠一起失靈怎麼辦 win10滑鼠鍵盤同時失靈鍵盤滑鼠一起失靈怎麼辦 win10滑鼠鍵盤同時失靈Win10
- 乾坤合一:Linux裝置驅動之USB主機和裝置驅動Linux
- 按鍵中斷驅動程式
- 鍵盤滑鼠一起失靈怎麼辦 win10滑鼠鍵盤同時失靈鍵盤滑鼠一起失靈怎麼辦Win10
- Mac 鍵盤與滑鼠的對映Mac
- tkinter中滑鼠與鍵盤事件(十五)事件
- AngularJs 鍵盤事件和滑鼠事件AngularJS事件
- jQuery 事件(一) 滑鼠與鍵盤事件jQuery事件
- java全域性滑鼠鍵盤監聽Java
- extcon驅動及其在USB驅動中的應用
- win10滑鼠鍵盤沒反應怎麼辦_win10滑鼠鍵盤失靈一鍵修復Win10
- 檢測到不相容的鍵盤驅動程式的解決辦法
- HarmonyOS USB DDK助你輕鬆實現USB驅動開發
- C#實現滑鼠、鍵盤鉤子C#
- 開啟win7鍵盤滑鼠鍵的步驟Win7
- 可不可以,對USB 限制,只能插入鍵盤或滑鼠,不能插入其它儲存介質
- 如何從USB驅動器執行Jutoh?
- win10鍵盤驅動顯示黃色感嘆號如何解決_win10系統鍵盤驅動有感嘆號解決教程Win10
- 滑鼠中鍵滾動mousewheel事件例項程式碼事件
- 滑鼠和鍵盤同時失靈應該怎麼辦 win10滑鼠鍵盤突然同時失靈Win10
- 2.3用按鍵精靈錄製鍵盤與滑鼠操作
- 眾多Logitech滑鼠/鍵盤支援改進Git
- 有趣的Python:Python控制鍵盤滑鼠Python
- python selenium2 - 滑鼠鍵盤操作Python
- 製作Linux的優盤(usb)啟動盤(轉)Linux