0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

USB鼠標(biāo)驅(qū)動程序上機實驗

麥辣雞腿堡 ? 來源:嵌入式Linux系統(tǒng)開發(fā) ? 作者:韋東山老師驅(qū)動大 ? 2023-07-17 17:35 ? 次閱讀

上機實驗

韋老師的 USB 鼠標(biāo)驅(qū)動,只實現(xiàn)了檢測鼠標(biāo)左鍵、右鍵、中鍵的【按下彈起】功能,沒有實現(xiàn)復(fù)雜功能,可以做 demo 學(xué)習(xí)參考。使用完整 USB 鼠標(biāo)功能請使用 Linux 內(nèi)核自帶的 driver,如文章開頭目錄。

/* 參考: drivershidusbhidusbmouse.c */
#include < linux/kernel.h >
#include < linux/slab.h >
#include < linux/module.h >
#include < linux/init.h >
#include < linux/usb.h >
#include < linux/input.h >
#include < linux/hid.h >

struct usb_mouse_as_key_desc {
    struct usb_device *dev;
    struct usb_interface *intf;
    const struct usb_device_id *id;
    int pipe, maxp;
    int bInterval;
    void *data_buffer;
    dma_addr_t data_dma;
    struct urb *urb;
};

/* 1. 構(gòu)造 usb_driver 
 * 1.1 id_table : 能支持哪些設(shè)備
 * 1.2 probe : 記錄某些信息, 分配/設(shè)置/注冊 input_dev, 也許"分配/填充/提交 URB"
 */

static struct usb_device_id usb_mouse_as_key_id_table [] = {
 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
  USB_INTERFACE_PROTOCOL_MOUSE), .driver_info = (kernel_ulong_t)"it is a mouse", },
 { } /* Terminating entry */
};

static void usb_mouse_as_key_irq(struct urb *urb)
{
 struct input_dev *dev = urb- >context;
 struct usb_mouse_as_key_desc *desc = input_get_drvdata(dev);
 signed char *data = desc- >data_buffer;
 int status;

 //printk("%s %s %d, urb- >status = %dn", __FILE__, __FUNCTION__, __LINE__, urb- >status);
 switch (urb- >status) {
 case 0:   /* success */
  break;
 case -ECONNRESET: /* unlink */
 case -ENOENT:
 case -ESHUTDOWN:
  return;
 /* -EPIPE:  should clear the halt */
 default:  /* error */
  goto resubmit;
 }

 //printk("data[1] = 0x%xn", data[1]);
 input_report_key(dev, KEY_L, data[1] & 0x01);
 input_report_key(dev, KEY_S, data[1] & 0x02);
 input_report_key(dev, KEY_ENTER, data[1] & 0x04);

 input_sync(dev);
resubmit:
 status = usb_submit_urb (urb, GFP_ATOMIC);
  //printk("%s %s %d, status = %dn", __FILE__, __FUNCTION__, __LINE__, status);
}

static int usb_mouse_as_key_open(struct input_dev *dev)
{
    struct urb *urb;
    struct usb_mouse_as_key_desc *desc = input_get_drvdata(dev);
    int err;
    
    printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
    /* 分配/填充/提交 URB */
    urb = usb_alloc_urb(0, GFP_KERNEL);

    desc- >urb = urb;

    usb_fill_int_urb(urb,
         desc- >dev,
         desc- >pipe,
         desc- >data_buffer,
         (desc- >maxp > 8 ? 8 : desc- >maxp),
         usb_mouse_as_key_irq,
         dev,
         desc- >bInterval);
    
    urb- >transfer_dma = desc- >data_dma;
    urb- >transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    err = usb_submit_urb (urb, GFP_ATOMIC);
    
    printk("%s %s %d, err = %dn", __FILE__, __FUNCTION__, __LINE__, err);
    return err;
}

static void usb_mouse_as_key_close(struct input_dev *dev)
{
    struct usb_mouse_as_key_desc *desc = input_get_drvdata(dev);
    
    /* 取消/釋放 URB */
    usb_kill_urb(desc- >urb);
    usb_free_urb(desc- >urb);
}

static int usb_mouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
 struct usb_device *dev = interface_to_usbdev(intf);
 struct input_dev *input_dev;
 struct usb_mouse_as_key_desc *desc;
 int error;
 struct usb_host_interface *interface;
 struct usb_endpoint_descriptor *endpoint;
 int pipe, maxp;

 printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
 /* 1. 記錄設(shè)備信息:  intf */
 interface = intf- >cur_altsetting;

 if (interface- >desc.bNumEndpoints != 1)
  return -ENODEV;

 endpoint = &interface- >endpoint[0].desc;
 if (!usb_endpoint_is_int_in(endpoint))
  return -ENODEV;

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

 desc = kmalloc(sizeof(struct usb_mouse_as_key_desc), GFP_KERNEL);
 desc- >dev  = dev;
 desc- >intf = intf;
 desc- >id   = id;
 desc- >pipe = pipe;
 desc- >maxp = maxp;
 desc- >bInterval = endpoint- >bInterval;
 desc- >data_buffer = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &desc- >data_dma);
 printk("%s %s %d, desc- >data_buffer = 0x%xn", __FILE__, __FUNCTION__, __LINE__, desc- >data_buffer);

 /* 2. 分配/設(shè)置/注冊input_dev 
  * 2.1 能產(chǎn)生哪類事件
  * 2.2 能產(chǎn)生這類事件里哪些些事件: L/S/ENTER
  * 2.3 設(shè)置函數(shù), 比如open
  * 2.4 在open函數(shù)里: 分配/填充/提交 URB
  * 2.5 URB的回調(diào)函數(shù): 解析數(shù)據(jù), 上報input_event
 */

 input_dev = devm_input_allocate_device(&intf- >dev);
    
 input_set_drvdata(input_dev, desc);

 /* set 1: which type event ? */ 
 __set_bit(EV_KEY, input_dev- >evbit);

 /* set 2: which event ? */ 
 __set_bit(KEY_L, input_dev- >keybit);
 __set_bit(KEY_S, input_dev- >keybit);
 __set_bit(KEY_ENTER, input_dev- >keybit);

 /* set 3: open */
 input_dev- >open  = usb_mouse_as_key_open;
 input_dev- >close = usb_mouse_as_key_close;

 error = input_register_device(input_dev);

 usb_set_intfdata(intf, input_dev);
    
 return 0;
}

static void usb_mouse_as_key_disconnect(struct usb_interface *intf)
{
 struct input_dev *input_dev = usb_get_intfdata (intf);
    struct usb_mouse_as_key_desc *desc = input_get_drvdata(input_dev);

    usb_free_coherent(desc- >dev, desc- >maxp, desc- >data_buffer, desc- >data_dma);
    kfree(desc);
        
    input_unregister_device(input_dev);
    usb_set_intfdata(intf, NULL);
}

static struct usb_driver usb_mouse_as_key_driver = {
 .name  = "usbmouse_as_key",
 .probe  = usb_mouse_as_key_probe,
 .disconnect = usb_mouse_as_key_disconnect,
 .id_table = usb_mouse_as_key_id_table,
};

/* 入口函數(shù)  / 出口函數(shù) */
// module_usb_driver(usb_mouse_as_key_driver);
static int __init usb_mouse_as_key__init(void)
{
    printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
 return usb_register(&usb_mouse_as_key_driver);
}

static void __exit usb_mouse_as_key__init_exit(void)
{ 
 usb_deregister(&usb_mouse_as_key_driver);
}

module_init(usb_mouse_as_key__init);
module_exit(usb_mouse_as_key__init_exit);

MODULE_LICENSE("GPL");

測試:

# 把 USB 鼠標(biāo)查到開發(fā)板上
# 先看看原來有哪些設(shè)備節(jié)點
ls /dev/input/event*

# 安裝驅(qū)動程序
insmod usbmouse_as_key.ko

# 再看看新得到了哪個設(shè)備節(jié)點
ls /dev/input/event*

# 執(zhí)行命令, 假設(shè) event4 是新節(jié)點
hexdump /dev/input/event4

# 點擊鼠標(biāo)按鍵即可觀察輸出信息

# 第 2 種測試方法: 執(zhí)行以下命令,按鼠標(biāo)左鍵、右鍵,再按中鍵就有輸出"ls"
cat /dev/tty0

# 第 3 種測試方法: 執(zhí)行以下命令(注意"< "號前后沒有空格),就可以使用鼠標(biāo)按鍵在控制臺輸入字符
exec 0< /dev/tty0
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • usb
    usb
    +關(guān)注

    關(guān)注

    60

    文章

    7848

    瀏覽量

    263309
  • 驅(qū)動
    +關(guān)注

    關(guān)注

    12

    文章

    1812

    瀏覽量

    85047
  • 鼠標(biāo)
    +關(guān)注

    關(guān)注

    6

    文章

    587

    瀏覽量

    39665
收藏 人收藏

    評論

    相關(guān)推薦

    Linux USB鼠標(biāo)驅(qū)動程序詳解

    驅(qū)動程序(u*** driver)是如何添加到驅(qū)動鏈表上去的?在每個 USB 驅(qū)動程序的被注冊時,USB
    發(fā)表于 10-23 12:40

    usb網(wǎng)卡驅(qū)動程序下載(萬能全集)

    usb網(wǎng)卡驅(qū)動程序:ADM8511 USB網(wǎng)卡驅(qū)動程序ADM8515 USB網(wǎng)卡驅(qū)動程序AS26
    發(fā)表于 09-28 15:40 ?4202次下載
    <b class='flag-5'>usb</b>網(wǎng)卡<b class='flag-5'>驅(qū)動程序</b>下載(萬能全集)

    天語手機usb驅(qū)動程序

    天語手機usb驅(qū)動程序:天語手機usb驅(qū)動程序下載
    發(fā)表于 04-30 12:36 ?792次下載

    EZ USB 通用驅(qū)動程序說明

    EZ_USB 通用驅(qū)動程序(本文章中稱為GPD或者是EZ_USB GPD)是用來和基于EZ_USB外設(shè)接口的通用設(shè)備驅(qū)動程序
    發(fā)表于 11-06 11:26 ?52次下載

    串口驅(qū)動程序實驗

    串口驅(qū)動程序實驗 一.實驗目的本示例程序展示了如何在Small RTOS51
    發(fā)表于 09-26 17:47 ?2089次閱讀
    串口<b class='flag-5'>驅(qū)動程序</b><b class='flag-5'>實驗</b>

    PDIUSBD12 USB 驅(qū)動程序演示實驗

    PDIUSBD12 USB 驅(qū)動程序演示實驗 一.實驗目的PDIUSBD12(簡稱D12) USB 芯片符合
    發(fā)表于 09-26 17:52 ?3428次閱讀

    Windows USB 驅(qū)動程序接口及傳輸方式

    Windows USB 驅(qū)動程序接口系統(tǒng)中的USB驅(qū)動程序完成許多的工作。實際上對于一些HID的USB設(shè) 備,象鍵盤,
    發(fā)表于 05-06 16:04 ?2273次閱讀

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

    介紹USB的優(yōu)點和發(fā)展情況,基于DDK的USB設(shè)備驅(qū)動程序結(jié)構(gòu),并結(jié)合開發(fā)的ARM 板驅(qū)動程序對關(guān)鍵程序進行介紹。
    發(fā)表于 03-19 15:21 ?121次下載
    <b class='flag-5'>USB</b>接口<b class='flag-5'>驅(qū)動程序</b>開發(fā)

    HC6800的USB驅(qū)動程序

    HC6800的USB驅(qū)動程序HC6800的USB驅(qū)動程序HC6800的USB驅(qū)動程序HC6800
    發(fā)表于 12-28 15:28 ?0次下載

    usb驅(qū)動程序

    CH340G的USB驅(qū)動程序,win7運行完全沒有問題。
    發(fā)表于 05-13 10:17 ?69次下載

    CDM20600驅(qū)動程序,USB驅(qū)動程序和并口驅(qū)動應(yīng)用程序(免費下載)

    本文檔的主要內(nèi)容是CDM20600驅(qū)動程序,USB驅(qū)動程序和并口驅(qū)動應(yīng)用程序(免費下載)詳細(xì)資料概述
    發(fā)表于 06-06 10:00 ?57次下載
    CDM20600<b class='flag-5'>驅(qū)動程序</b>,<b class='flag-5'>USB</b><b class='flag-5'>驅(qū)動程序</b>和并口<b class='flag-5'>驅(qū)動</b>應(yīng)用<b class='flag-5'>程序</b>(免費下載)

    Linux USB鼠標(biāo)驅(qū)動程序詳解

    驅(qū)動程序usb driver)是如何添加到驅(qū)動鏈表上去的?在每個 USB 驅(qū)動程序的被注冊時,USB
    發(fā)表于 04-02 14:35 ?736次閱讀

    SDP USB驅(qū)動程序安裝程序

    SDP USB驅(qū)動程序安裝程序
    發(fā)表于 03-23 10:07 ?14次下載
    SDP <b class='flag-5'>USB</b><b class='flag-5'>驅(qū)動程序</b>安裝<b class='flag-5'>程序</b>

    手指在應(yīng)用程序上機器人

    電子發(fā)燒友網(wǎng)站提供《手指在應(yīng)用程序上機器人.zip》資料免費下載
    發(fā)表于 11-16 10:04 ?0次下載
    手指在應(yīng)用<b class='flag-5'>程序上機</b>器人

    USB驅(qū)動程序

    USB驅(qū)動程序
    發(fā)表于 08-17 11:47 ?54次下載