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

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

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

USB鼠標(biāo)驅(qū)動(dòng)程序上機(jī)實(shí)驗(yàn)

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

上機(jī)實(shí)驗(yàn)

韋老師的 USB 鼠標(biāo)驅(qū)動(dòng),只實(shí)現(xiàn)了檢測(cè)鼠標(biāo)左鍵、右鍵、中鍵的【按下彈起】功能,沒(méi)有實(shí)現(xiàn)復(fù)雜功能,可以做 demo 學(xué)習(xí)參考。使用完整 USB 鼠標(biāo)功能請(qǐng)使用 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è)置/注冊(cè) 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è)置/注冊(cè)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ù), 上報(bào)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");

測(cè)試:

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

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

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

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

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

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

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

    關(guān)注

    60

    文章

    7773

    瀏覽量

    262380
  • 驅(qū)動(dòng)
    +關(guān)注

    關(guān)注

    12

    文章

    1790

    瀏覽量

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

    關(guān)注

    6

    文章

    587

    瀏覽量

    39579
收藏 人收藏

    評(píng)論

    相關(guān)推薦

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

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

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

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

    天語(yǔ)手機(jī)usb驅(qū)動(dòng)程序

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

    EZ USB 通用驅(qū)動(dòng)程序說(shuō)明

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

    串口驅(qū)動(dòng)程序實(shí)驗(yàn)

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

    PDIUSBD12 USB 驅(qū)動(dòng)程序演示實(shí)驗(yàn)

    PDIUSBD12 USB 驅(qū)動(dòng)程序演示實(shí)驗(yàn) 一.實(shí)驗(yàn)目的PDIUSBD12(簡(jiǎn)稱D12) USB 芯片符合
    發(fā)表于 09-26 17:52 ?3394次閱讀

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

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

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

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

    HC6800的USB驅(qū)動(dòng)程序

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

    usb驅(qū)動(dòng)程序

    CH340G的USB驅(qū)動(dòng)程序,win7運(yùn)行完全沒(méi)有問(wèn)題。
    發(fā)表于 05-13 10:17 ?69次下載

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

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

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

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

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

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

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

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

    USB驅(qū)動(dòng)程序

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