linux設備驅動程序的編寫--將usb鼠標當做按鍵

USB設備驅動程序的編寫:
1分配一個struct 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,
    };

1.1分配成員id_table
    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 */
    };
    usb_device_id結構體包含了設備驅動程序支持的設備。

2:註冊:
    入口函數裏面註冊:
    usb_register(&usbmouse_as_key_driver);
    在出口函數裏面取消註冊:
    usb_deregister(&usbmouse_as_key_driver);    

3具體函數的設置和實現:

    幾個usb設備概念:
    端口:USB 通訊的最基本形式是通過某些稱爲 端點 的. 一個 USB 端點只能在一個方
         向承載數據, 或者從主機到設備(稱爲輸出端點)或者從設備到主機(稱爲輸入端
          點). 端點可看作一個單向的管道.
         struct usb_endpoint_descriptor *endpoint;
    接口:
         USB 端點被綁在接口中. USB 接口只處理一類 USB 邏輯連接, 例如一個鼠標,
         一個鍵盤, 或者一個音頻流. 一些 USB 設備有多個接口, 例如一個 USB 揚聲
        器可能有 2 個接口: 一個 USB 鍵盤給按鈕和一個 USB 音頻流。
    USBurb:
        linux內核中的USB代碼通過urb(usb請求塊)和所有的usb設備通信。這個塊使用struct urb來描述。


       static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
    {

        static dma_addr_t *buf_phys;

        struct usb_host_interface *interface;   //定義接口變量
        struct usb_endpoint_descriptor *endpoint; //定義端點變量
    
        struct usb_device *dev = interface_to_usbdev(intf);//根據接口信息分配一個usb_dev結構體。
        interface = intf->cur_altsetting;            //
        endpoint = &interface->endpoint[0].desc;//接口和端口的信息填充
        
        /*創建urb結構體*/
        urb_uk = usb_alloc_urb(0, GFP_KERNEL);
        
        /*創建一個DMA緩衝區來以最高效的方式發送數據*/

        buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &buf_phys);
        
        /*把指定的USB設備端點號設置成一個控制IN型端口*/
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
        
        /*端口一次可以處理的最大字節數 /
        len = endpoint->wMaxPacketSize;

        /*初始化即將被髮送到usb設備的中斷端點的urb*/
        usb_fill_int_urb(urb_uk, dev, pipe, buf,len,usb_mouse_as_key_irq, NULL, endpoint->bInterval);
        urb_uk->transfer_dma = buf_phys; //以DMA方式傳輸數據到USB設備的緩衝區
        urb_uk->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

        /*urb被創建和初始化之後, 提交到usb核心以發送到usb設備*/
        usb_submit_urb(urb_uk,GFP_KERNEL);

        /*urb被成功的傳輸到usb設備之後,urb裏面的回調函數(usb_mouse_as_key_irq)將被usb核心調用*/
    



    
    }

    static void usb_mouse_as_key_irq(struct urb *urb)
    {
        /*將usb鼠標用作按鍵使用, 用到輸入子系統*/
        
        int pipe;
        /*1:分配一個input_dev結構體*/
        input_mk = input_allocate_device();

        /*2:設置*/

        set_bit(EV_KEY,input_mk->evbit);
        set_bit(EV_REP,input_mk->evbit);

        set_bit(KEY_L,input_mk->keybit);
        set_bit(KEY_S,input_mk->keybit);
        set_bit(KEY_ENTER,input_mk->keybit);
        
        
        /*3:註冊*/

        input_register_device(input_mk);
        
        /* USB鼠標數據含義
         * data[0]: bit0-左鍵, 1-按下, 0-鬆開
         *          bit1-右鍵, 1-按下, 0-鬆開
         *          bit2-中鍵, 1-按下, 0-鬆開
         *
             */
        static unsigned char pre_val;

        if ((pre_val & (1<<0)) != (buf[0] & (1 << 0)))
        {
            input_event(input_mk, EV_KEY, KEY_L,(buf[0] & (1 << 0) ? 1 : 0));
            input_sync(input_mk);
        }
        else if ((pre_val & (1<<1)) != (buf[0] & (1 << 1)))
        {
            input_event(input_mk, EV_KEY, KEY_S,(buf[0] & (1 << 1) ? 1 : 0));
            input_sync(input_mk);
        }
        else if ((pre_val & (1<<2)) != (buf[0] & (1 << 2)))
        {
            input_event(input_mk, EV_KEY, KEY_ENTER,(buf[0] & (1 << 2) ? 1 : 0));
            input_sync(input_mk);
        }

        pre_val = buf[0];

        /*再次提交*/
        usb_submit_urb(urb_uk,GFP_KERNEL);
    }
       static void usbmouse_as_key_disconnect(struct usb_interface *intf)
    {    
        struct usb_device *dev = interface_to_usbdev(intf);
        
        usb_free_urb(buf);
        usb_kill_urb(buf);
        usb_buffer_free(dev,len, buf, buf_phys);

        
        input_unregister_device(input_mk);
        input_free_device(input_mk);
        
    }


發佈了38 篇原創文章 · 獲贊 0 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章