注意:本篇講的鼠標(biāo)驅(qū)動(dòng)僅能實(shí)現(xiàn)鼠標(biāo)左右鍵跟滑輪這三個(gè)按鍵類(lèi)似button的功能,按下左鍵則打出'l',右鍵打出“s”,滑輪打出“enter”。如果要實(shí)現(xiàn)正常的鼠標(biāo)驅(qū)動(dòng),參考內(nèi)核的鼠標(biāo)驅(qū)動(dòng),修改input的一些參數(shù)即可。
一、寫(xiě)驅(qū)動(dòng)的步驟(新手稍微看下即可,內(nèi)容有點(diǎn)搞)
1、復(fù)制頭文件;
2、寫(xiě)入口函數(shù),出口函數(shù),再加上協(xié)議;
3、分配注冊(cè)u(píng)sb_driver結(jié)構(gòu)體(拷別人的),
static struct usb_driver usb_mk_driver = {};
在init中注冊(cè)該結(jié)構(gòu)體:usb_register(&usb_mk_driver);
在exit中注銷(xiāo)該結(jié)構(gòu)體:usb_deregister(&usb_mk_driver);
4、寫(xiě)id_table函數(shù),static struct usb_device_id usb_mk_id_table [] = {},只有滿(mǎn)足id_table中的各種類(lèi)別,子類(lèi)號(hào),協(xié)議,才能調(diào)用;
5、寫(xiě)probe函數(shù):static int usb_mk_probe(struct usb_interface *intf, const struct usb_device_id *id);
6、寫(xiě)disconnect函數(shù):static void usb_mk_disconnect(struct usb_interface *intf)
7、如果想在開(kāi)發(fā)板插入usb設(shè)備的時(shí)候打印設(shè)備信息(可以不用),可以在probe中加入:
printk('VID = 0x%x, PID = 0x%xn', dev->descriptor.idVendor, dev->descriptor.idProduct);
printk('USB VERS = 0x%x, PID = 0x%xn', dev->descriptor.bcdUSB);
8、probe之后要進(jìn)一步判斷你這個(gè)是不是鼠標(biāo):
1、分配一個(gè)input_dev結(jié)構(gòu)體:在頭文件下定義;static struct input_dev *mk_dev; 在probe內(nèi):mk_dev = input_allocate_device();
2、設(shè)置:
1、能產(chǎn)生哪類(lèi)事件
set_bit(EV_KEY, mk_dev->evbit);
set_bit(EV_REP, mk_dev->evbit);
2、能產(chǎn)生哪些事件
set_bit(KEY_L, mk_dev->keybit);
set_bit(KEY_S, mk_dev->keybit);
set_bit(KEY_ENTER, mk_dev->keybit);
3、注冊(cè):input_register_device(mk_dev);
4、設(shè)置:數(shù)據(jù)傳輸3要素: 源, 目的, 長(zhǎng)度
先從usbmouse.c中拷入幾行代碼:
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
int pipe;
endpoint = &interface->endpoint[0].desc;
源:usb設(shè)備的某個(gè)端點(diǎn)
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
目的:需要設(shè)置緩沖區(qū)buffer:
buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &buf_phys);
在頭文件下定義一個(gè)緩沖區(qū):
static char *buf;
static dma_addr_t buf_phys;
長(zhǎng)度:static int len(作為全局變量,等會(huì)有用)
len = endpoint->wMaxPacketSize;
5、怎么用那三要素呢?
在probe中;
1、分配一個(gè)urb,mk_urb = usb_alloc_urb(0, GFP_KERNEL);
在頭文件下定義urb:static struct urb *mk_urb;
2、使用三要素填充urb:
usb_fill_int_urb(mk_urb, dev, pipe, buf,
len,
uk_callback, NULL, endpoint->bInterval);
mk_urb->transfer_dma = buf_phys;
mk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
3、使用URB:usb_submit_urb(mk_urb, GFP_KERNEL);
6、要寫(xiě)一個(gè)中斷函數(shù),原因是usb控制器收到從usb傳來(lái)的數(shù)據(jù)后,需要一個(gè)中斷來(lái)通知cpu有信號(hào)啦!static void uk_callback(struct urb *urb)
在中斷函數(shù)中定義一些唧唧歪歪的東西后看,重新提交urb:
usb_submit_urb(mk_urb, GFP_KERNEL);
7,提交urb后當(dāng)然還要做殺掉urb,在disconnect中殺掉它!usb_kill_urb(mk_urb);
順便再disconnect中注銷(xiāo)或卸載其他的函數(shù);
8、在中斷函數(shù)里上報(bào)事件。
**************************************************************************************************************
二、驅(qū)動(dòng)程序
#include <linux/kernel.h>
#include #include #include #include #include #include /* 參考drivershidusbhidusbmouse.c */ static struct input_dev *mk_dev; static int len; static char *buf; //定義一個(gè)緩沖區(qū) static dma_addr_t buf_phys; //dma_addr實(shí)際上是一個(gè)物理地址 static struct urb *mk_urb; static struct usb_device_id usb_mk_id_table [] = { { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_MOUSE) }, /*只要它的類(lèi)是class_hid,子類(lèi)是boot,協(xié)議是mouse,那么就可以匹配*/ *{USB_DEVICE(0x46d, 0xc52f)或者直接指定自己的usb設(shè)備只支持這種廠家的設(shè)備。*/ { } /* Terminating entry */ }; /* 當(dāng)USB主機(jī)控制器獲得鼠標(biāo)數(shù)據(jù)后, * 會(huì)調(diào)用這個(gè)函數(shù) */ static void uk_callback(struct urb *urb)//這是一個(gè)中斷函數(shù)! { int i; static char pre_val; #if 0 //這一段都用不到了,因?yàn)閕f = 0 ;這一段的作用就是用來(lái)看鼠標(biāo)按下之后都顯示什么數(shù)值,最后通過(guò)這些數(shù)值來(lái)設(shè)置上報(bào)事件。 printk('Get datas:n'); for (i = 0; i < len; i++) { printk('%02x ', buf[i]); } printk('n'); #endif /* 鼠標(biāo)數(shù)據(jù)含義: * buf[0]: bit0-左鍵, 0-松開(kāi), 1-按下 * bit1-右鍵, 0-松開(kāi), 1-按下 * bit2-中鍵, 0-松開(kāi), 1-按下 * buf[1],buf[2]構(gòu)成一個(gè)整數(shù), 表示X方向的相對(duì)位移 * >0 : 右移 * <0 : 左移 * buf[3],buf[4]構(gòu)成一個(gè)整數(shù), 表示Y方向的相對(duì)位移 * >0 : 下移 * <0 : 上移 * buf[6]: 滾輪 */ /* 確定按鍵值 */ /* 上報(bào)數(shù)據(jù) */ if ((pre_val & (1<<0)) != (buf[0] & (1<<0))) //如果上次數(shù)據(jù)的bit0不等于這次數(shù)據(jù)的bit0,那么就是左鍵發(fā)生變化 { /* 左鍵按下或松開(kāi) */ input_event(mk_dev, EV_KEY, KEY_L, (buf[0] & (1<<0)) ? 1 : 0);//如果buf0=1的話(huà)那就是按下,既是1,否則為0; input_sync(mk_dev); } if ((pre_val & (1<<1)) != (buf[0] & (1<<1))) { /* 右鍵按下或松開(kāi) */ input_event(mk_dev, EV_KEY, KEY_S, (buf[0] & (1<<1)) ? 1 : 0); input_sync(mk_dev); } if ((pre_val & (1<<2)) != (buf[0] & (1<<2))) { /* 中鍵按下或松開(kāi) */ input_event(mk_dev, EV_KEY, KEY_ENTER, (buf[0] & (1<<2)) ? 1 : 0); input_sync(mk_dev); } pre_val = buf[0]; /* 重新提交URB */ usb_submit_urb(mk_urb, GFP_KERNEL); } /*interface是指接口,一個(gè)usb設(shè)備可能有多個(gè)邏輯接口,這個(gè)邏輯接口就是用下面的usb_interface來(lái)表示的*/ static int usb_mk_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; static int first = 1; if (!first) return -EIO; first = 0; /* 每一個(gè)設(shè)備都有端點(diǎn)0 * interface->endpoint[]數(shù)組里放'除了端點(diǎn)0外的其他端點(diǎn)' * interface->endpoint[0]表示'除端點(diǎn)0外的第1個(gè)端點(diǎn)' * interface->endpoint[1]表示'除端點(diǎn)0外的第2個(gè)端點(diǎn)' */ interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; /* 1. 分配inputd_dev */ mk_dev = input_allocate_device(); /* 2. 設(shè)置 */ /* 2.1 能產(chǎn)生哪類(lèi)事件 */ set_bit(EV_KEY, mk_dev->evbit); //按鍵類(lèi)事件 set_bit(EV_REP, mk_dev->evbit); //重復(fù)類(lèi)事件,例如一直按著L,則會(huì)顯示LLLLLLL。。。 /* 2.2 能產(chǎn)生這類(lèi)事件里的哪些事件 */ set_bit(KEY_L, mk_dev->keybit); set_bit(KEY_S, mk_dev->keybit); set_bit(KEY_ENTER, mk_dev->keybit); /* 3. 注冊(cè) */ input_register_device(mk_dev); /* 4. 硬件相關(guān)的操作: * 對(duì)于GPIO按鍵, 是request_irq, 在中斷處理函數(shù)里上報(bào)按鍵 * 對(duì)于USB設(shè)備, 是使用'USB主機(jī)驅(qū)動(dòng)程序提供的函數(shù)'發(fā)起USB傳輸獲得數(shù)據(jù) */ /* 數(shù)據(jù)傳輸3要素: 源, 目的, 長(zhǎng)度 */ /* A. 源: USB設(shè)備的某個(gè)端點(diǎn) */ /* ((PIPE_INTERRUPT << 30) | (dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN) */ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);//pipe是源,源是一個(gè)整數(shù),這個(gè)整數(shù)里有端點(diǎn)的類(lèi)型,端點(diǎn)的方向 /* C. 長(zhǎng)度: 這個(gè)端點(diǎn)描述符的wMaxPacketSize */ len = endpoint->wMaxPacketSize; /* B. 目的: 分配buffer */ buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &buf_phys);//從usb_buffer_alloc換成usb_alloc_coherent /* D. 怎么使用這3要素 ? */ /* 分配URB: USB Reqeust Block ,usb請(qǐng)求塊*/ mk_urb = usb_alloc_urb(0, GFP_KERNEL); /* 用3要素填充URB *實(shí)際上usb設(shè)備沒(méi)有中斷cpu的能力,但是電腦的usb主機(jī)有中斷cpu的能力,所以u(píng)sb主機(jī)不斷查詢(xún),有信號(hào)便中斷cpu。 */ usb_fill_int_urb(mk_urb, dev, pipe, buf, len, uk_callback, NULL, endpoint->bInterval);//bInterval:查詢(xún)頻率,uk_callback是一個(gè)中斷函數(shù); mk_urb->transfer_dma = buf_phys; //得到數(shù)據(jù)后要往某個(gè)內(nèi)存里寫(xiě),它沒(méi)那么聰明,需要一個(gè)物理地址 mk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;//還有設(shè)置某些標(biāo)記,這標(biāo)記什么意思偉哥也不懂 /* 使用URB ,看看別人怎么做*/ usb_submit_urb(mk_urb, GFP_KERNEL);//提交urb return 0; } static void usb_mk_disconnect(struct usb_interface *intf) { struct usb_device *dev = interface_to_usbdev(intf); printk('disconnect usb mouse!!!!!n'); usb_kill_urb(mk_urb); usb_free_urb(mk_urb); usb_free_coherent(dev,len, buf, buf_phys);//應(yīng)該是usb_free_coherent input_unregister_device(mk_dev); input_free_device(mk_dev); } /* 1. 分配usb_driver */ /* 2. 設(shè)置 */ static struct usb_driver usb_mk_driver = { .name = 'usbmk', .probe = usb_mk_probe, .disconnect = usb_mk_disconnect, .id_table = usb_mk_id_table, }; static int usb_mk_init(void) { /* 3. 注冊(cè) */ usb_register(&usb_mk_driver); return 0; } static void usb_mk_exit(void) { usb_deregister(&usb_mk_driver); } module_init(usb_mk_init); module_exit(usb_mk_exit); MODULE_LICENSE('GPL');
上一篇:u-boot2010.03 移植篇(一) 建立編譯目標(biāo)
下一篇:基于ok6410的韋東山驅(qū)動(dòng)視頻簡(jiǎn)要分析--ts驅(qū)動(dòng)
推薦閱讀最新更新時(shí)間:2025-06-17 01:51

設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦
- 【下載】LAT1526 利用SPI的下溢實(shí)現(xiàn)回顯功能
- 【下載】LAT1509 STM32G0B1的FDCAN進(jìn)行通信丟包和多包案例分享
- 【下載】LAT1511 運(yùn)行Ux_Host_HUB_HID_MSC通過(guò)Hub連接U盤(pán)讀寫(xiě)不穩(wěn)定問(wèn)題分析
- 【下載】LAT1466 USB x Device HID Standalone的移植
- 【下載】LAT1488 STM32 USBxDevice MSC standalone移植示例
- 【下載】LAT1482 STM32G0單線(xiàn)串口通信幀錯(cuò)誤問(wèn)題解析
- Microchip 升級(jí)數(shù)字信號(hào)控制器(DSC)產(chǎn)品線(xiàn) 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無(wú)線(xiàn)微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開(kāi)發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹(shù)莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲(chǔ)html,css,js文件,以及網(wǎng)頁(yè)和arduino的通訊
- ESP32 freeRTOS使用測(cè)試
- LT3757,一個(gè) 10V30V 輸入、48V/1A 輸出升壓轉(zhuǎn)換器
- 使用 Semtech 的 SC2446 的參考設(shè)計(jì)
- LTC5585 的典型應(yīng)用 - 具有 IIP2 和 DC 偏移控制的寬帶 IQ 解調(diào)器
- EVAL-ADG5208FEBZ,ADG5208F 過(guò)壓保護(hù) 8:1 多路復(fù)用器評(píng)估板
- LTC3455EUF 演示板,USB 電源解決方案,USB/鋰離子適配器,3.15V @ 500mA,1.8V @ 400mA,Vin = 5V +/- 5%
- LTC3892IUH 高效率、雙路 5V/12V 輸出同步降壓型 DC/DC 控制器的典型應(yīng)用電路
- LTC3642EMS8E、5V、50mA 降壓轉(zhuǎn)換器的典型應(yīng)用電路
- 用于安全應(yīng)用的 L9654 Quad 爆管驅(qū)動(dòng)器和雙傳感器接口 ASIC 的典型應(yīng)用
- REP019: 調(diào)諧于單一110MHz IF的雙頻前端CDMA IC
- OM13076、LPCXpresso 18S37 開(kāi)發(fā)板,用于 LPC43/43S00 和 LPC18S00 系列 Cortex-M MCU
- 經(jīng)典儀表放大器(PGIA)的新版本提供更高的設(shè)計(jì)靈活性
- 華為全新HUD,70英寸屏幕前玻璃.
- S3C2440裸機(jī)------觸摸屏_利用ADC讀取觸摸屏坐標(biāo)
- 10元芯片炒到400元!汽車(chē)芯片缺貨漲價(jià)致全球停產(chǎn)300萬(wàn)輛
- 中國(guó)臺(tái)灣半導(dǎo)體的低調(diào)贏家
- STM32系統(tǒng)嘀嗒定時(shí)器實(shí)現(xiàn)1ms中斷事件
- PLC控制設(shè)備手動(dòng)和自動(dòng)切換功能的方法
- 教你怎么去測(cè)量電壓降?
- BICS與微軟合作推出專(zhuān)網(wǎng)漫游方案
- 混合壓縮/內(nèi)置自我測(cè)試解決方案的應(yīng)用優(yōu)勢(shì)分析
- 上汽大眾:汽車(chē)網(wǎng)絡(luò)安全漏洞防護(hù)
- 恩智浦推出全新電池控制IC系列 助力新能源解決方案發(fā)展
- 全球首條GWh級(jí)新型固態(tài)電池生產(chǎn)線(xiàn)樣件下線(xiàn)
- 總投資455億元!三大動(dòng)力電池項(xiàng)目齊刷進(jìn)度條
- 現(xiàn)代汽車(chē)韓國(guó)建氫燃料電池廠,2028年投產(chǎn)
- 6月融資一覽:智能汽車(chē)芯片、第三代半導(dǎo)體、機(jī)器人成資本焦點(diǎn)
- 艙駕一體“點(diǎn)燃”新戰(zhàn)事
- 汽車(chē)智能化2.0引爆「萬(wàn)億蛋糕」,誰(shuí)在改寫(xiě)游戲規(guī)則?
- 2025研華智能系統(tǒng)產(chǎn)業(yè)伙伴峰會(huì)成功舉辦
- 意法半導(dǎo)體公布2025年第二季度財(cái)報(bào)和電話(huà)會(huì)議時(shí)間安排
- 高通驍龍895解密:臺(tái)積電爽了
- 諾基亞國(guó)行5G新機(jī)可望于雙11前發(fā)布
- 小米折疊屏新專(zhuān)利解密:上下折疊 神似經(jīng)典翻蓋機(jī)型
- Win11 Cloud PC 或在 7 月 14 日 Inspire 大會(huì)期間發(fā)布
- 一加或?qū)⑻峁?年安卓底層更新
- 美光CEO評(píng)論長(zhǎng)江存儲(chǔ)打入蘋(píng)果供應(yīng)鏈傳聞:還差得遠(yuǎn)呢!
- 外媒點(diǎn)名聯(lián)發(fā)科或成博通下一標(biāo)的,個(gè)中真假有幾分?
- 傳蘋(píng)果以量制價(jià),擴(kuò)大OLED下單量同時(shí)要求三星降價(jià)
- 長(zhǎng)江存儲(chǔ)發(fā)布關(guān)于薛宗智先生離職的聲明
- 8英寸晶圓代工產(chǎn)能告急:三星想分一杯羹,中芯國(guó)際受益
- ±150ma電流轉(zhuǎn)0~3V電壓電路設(shè)計(jì),誰(shuí)能幫著指點(diǎn)一下?
- 大神們快來(lái)看一下LCD2004A Arduino(Atmega2560R3)程序,怎么就是不顯示呢?
- 電磁兼容設(shè)計(jì)及測(cè)試-印制板設(shè)計(jì)
- 中國(guó)IPTV用戶(hù)數(shù)量統(tǒng)計(jì)
- 28335的SARAM與FLASH大小
- 樹(shù)莓派學(xué)習(xí)——配件篇
- RT-Thread設(shè)備框架學(xué)習(xí)之UART設(shè)備
- 首批LaunchPad 收到,感謝TI和EEWORD
- 震動(dòng)信息認(rèn)證
- 半導(dǎo)體封裝形式介紹