標籤:des style blog color 使用 資料
本文以USB滑鼠講解USB裝置驅動。
驅動程式中調用usb_register(struct usb_driver *)函數時,先判斷USB匯流排驅動程式是否支援usb_driver裡定義的id_table,若支援,調用usb_driver的probe函數。
所以首先要定義並初始化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,};構造id_table:
static struct usb_device_id usbmouse_as_key_id_table[] = { {USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS, USB_INTERFACE_PROTOCOL_MOUSE)}, {},};構造probe和disconnect函數:usb傳輸需要用到urb,定義urb:
static struct urb *uk_urb;static int usbmouse_as_key_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_descripter *endpoint;/* 端點描述符 */ int pipe; interface = intf->cur_alterseting;/* 獲得設定描述符 */ endpoint = &interface->endpoint[0].desc;/* 獲得端點描述符 */ /* 分配設定input_dev */ uk_dev = input_allocate_device(); set_bit(EV_KEY, uk_dev->evbit); set_bit(EV_REP, uk_dev->evbit); set_bit(KEY_L, uk_dev->keybit); set_bit(KEY_S, uk_dev->keybit); set_bit(KEY_ENTER, uk_dev->keybit); input_register_device(uk_dev); /* 構造資料轉送3要素 */ /* 源 */ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);//產生一個中斷管道,然後把得到的管道賦到了urb上 /* 長度 */ len = endpoint->wMaxPacketSize; /* 目的 */ uk_buf = usb_buffer_alloc(0, GFP_KERNEL); /* 使用三要素設定URB 填充中斷urb */ usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval); uk_urb->transer_dma = usb_buf_phys; uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_REP; usb_submit_urb(uk_urb, GFP_KERNEL);/* 將urb遞交給USB核心 */ return 0;}static void usbmouse_as_key_disconnect(struct usb_interface *intf){ struct usb_device *dev = interface_to_usbdev(intf); //printk("disconnect usbmouse!\n"); usb_kill_urb(uk_urb); usb_free_urb(uk_urb); usb_buffer_free(dev, len, usb_buf, usb_buf_phys); input_unregister_device(uk_dev); input_free_device(uk_dev);}static void usbmouse_as_key_irq(struct urb *urb){ static unsigned char pre_val; /* USB滑鼠資料含義 * data[0]: bit0-左鍵, 1-按下, 0-鬆開 * bit1-右鍵, 1-按下, 0-鬆開 * bit2-中鍵, 1-按下, 0-鬆開 * */ if ((pre_val & (1<<0)) != (usb_buf[0] & (1<<0))) { /* 左鍵發生了變化 */ input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0); input_sync(uk_dev); } if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1))) { /* 右鍵發生了變化 */ input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0); input_sync(uk_dev); } if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2))) { /* 中鍵發生了變化 */ input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0); input_sync(uk_dev); } pre_val = usb_buf[0]; usb_submit_urb(uk_urb, GFP_KERNEL);/* 重新提交URB */}