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);
}