linux设备驱动(31)usb驱动 您所在的位置:网站首页 HID键盘驱动 linux设备驱动(31)usb驱动

linux设备驱动(31)usb驱动

2024-02-04 22:11| 来源: 网络整理| 查看: 265

内核自带的USB键盘驱动 :/drivers/hid/usbhid/usbkbd.c

 1 usb键盘驱动的定义

1 static struct usb_driver usb_kbd_driver = { 2 .name = "usbkbd", 3 .probe = usb_kbd_probe, 4 .disconnect = usb_kbd_disconnect, 5 .id_table = usb_kbd_id_table, 6 }; 7 8 module_usb_driver(usb_kbd_driver);

 usb键盘usb_device_id的定义:

1 static struct usb_device_id usb_kbd_id_table [] = { 2 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID,//接口类 HID类 3 USB_INTERFACE_SUBCLASS_BOOT,//子类启动设备类 4 USB_INTERFACE_PROTOCOL_KEYBOARD//usb 键盘协议) }, 5 { } /* Terminating entry */ 6 };

2 probe函数

不再重复,和usb鼠标类似

1 static int usb_kbd_probe(struct usb_interface *iface, 2 const struct usb_device_id *id) 3 { 4 struct usb_device *dev = interface_to_usbdev(iface); 5 struct usb_host_interface *interface; 6 struct usb_endpoint_descriptor *endpoint; 7 struct usb_kbd *kbd; 8 struct input_dev *input_dev; 9 int i, pipe, maxp; 10 int error = -ENOMEM; 11 12 interface = iface->cur_altsetting; 13 14 if (interface->desc.bNumEndpoints != 1) 15 return -ENODEV; 16 17 endpoint = &interface->endpoint[0].desc; 18 if (!usb_endpoint_is_int_in(endpoint)) 19 return -ENODEV; 20 21 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 22 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 23 24 kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); 25 input_dev = input_allocate_device(); 26 if (!kbd || !input_dev) 27 goto fail1; 28 29 if (usb_kbd_alloc_mem(dev, kbd)) 30 goto fail2; 31 32 kbd->usbdev = dev; 33 kbd->dev = input_dev; 34 spin_lock_init(&kbd->leds_lock); 35 36 if (dev->manufacturer) 37 strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); 38 39 if (dev->product) { 40 if (dev->manufacturer) 41 strlcat(kbd->name, " ", sizeof(kbd->name)); 42 strlcat(kbd->name, dev->product, sizeof(kbd->name)); 43 } 44 45 if (!strlen(kbd->name)) 46 snprintf(kbd->name, sizeof(kbd->name), 47 "USB HIDBP Keyboard %04x:%04x", 48 le16_to_cpu(dev->descriptor.idVendor), 49 le16_to_cpu(dev->descriptor.idProduct)); 50 51 usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); 52 strlcat(kbd->phys, "/input0", sizeof(kbd->phys)); 53 54 input_dev->name = kbd->name; 55 input_dev->phys = kbd->phys; 56 usb_to_input_id(dev, &input_dev->id); 57 input_dev->dev.parent = &iface->dev; 58 59 input_set_drvdata(input_dev, kbd); 60 61 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) | 62 BIT_MASK(EV_REP); 63 input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | 64 BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) | 65 BIT_MASK(LED_KANA); 66 67 for (i = 0; i < 255; i++) 68 set_bit(usb_kbd_keycode[i], input_dev->keybit); 69 clear_bit(0, input_dev->keybit); 70 71 input_dev->event = usb_kbd_event; 72 input_dev->open = usb_kbd_open; 73 input_dev->close = usb_kbd_close; 74 75 usb_fill_int_urb(kbd->irq, dev, pipe, 76 kbd->new, (maxp > 8 ? 8 : maxp), 77 usb_kbd_irq, kbd, endpoint->bInterval); 78 kbd->irq->transfer_dma = kbd->new_dma; 79 kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 80 81 kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; 82 kbd->cr->bRequest = 0x09; 83 kbd->cr->wValue = cpu_to_le16(0x200); 84 kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); 85 kbd->cr->wLength = cpu_to_le16(1); 86 87 usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), 88 (void *) kbd->cr, kbd->leds, 1, 89 usb_kbd_led, kbd); 90 kbd->led->transfer_dma = kbd->leds_dma; 91 kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 92 93 error = input_register_device(kbd->dev); 94 if (error) 95 goto fail2; 96 97 usb_set_intfdata(iface, kbd); 98 device_set_wakeup_enable(&dev->dev, 1); 99 return 0; 100 101 fail2: 102 usb_kbd_free_mem(dev, kbd); 103 fail1: 104 input_free_device(input_dev); 105 kfree(kbd); 106 return error; 107 }

 2.1 usb_kbd_keycode的定义

键盘描述码表,其中0表示保留的意思。

1 static const unsigned char usb_kbd_keycode[256] = { 2 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 3 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 4 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, 5 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 6 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 7 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 8 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 9 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 10 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, 11 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 17 150,158,159,128,136,177,178,176,142,152,173,140 18 };

2.2 函数usb_kbd_irq

1 static void usb_kbd_irq(struct urb *urb) 2 { 3 struct usb_kbd *kbd = urb->context; 4 int i; 5 switch (urb->status) { // 只有urb->status==0时,说明数据传输成功 6 case 0: /* success */ 7 break; 8 case -ECONNRESET: /* unlink */ 9 case -ENOENT: 10 case -ESHUTDOWN: 11 return; 12 /* -EPIPE: should clear the halt */ 13 default: /* error */ 14 goto resubmit; 15 } 16 17 for (i = 0; i < 8; i++) //上传crtl、shift、atl、windows 等按键 18 input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); 19 20 for (i = 2; i < 8; i++) { //上传普通按键 21 /*通过上个状态的按键数据kbd->old[i]的非0值,来查找当前状态的按键数据,若没有找到,说明已经松开了该按键 */ 22 if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { 23 if (usb_kbd_keycode[kbd->old[i]]) //再次判断键盘描述码表的值是否非0 24 input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); //上传松开事件 25 else 26 info("Unknown key (scancode %#x) released.", kbd->old[i]); 27 } 28 29       /*通过当前状态的按键数据kbd->new[i]的非0值,来查找上个状态的按键数据,若没有找到,说明已经按下了该按键 */ 30 if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { 31 if (usb_kbd_keycode[kbd->new[i]]) //再次判断键盘描述码表的值是否非0 32 input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); //上传按下事件 33 else 34 info("Unknown key (scancode %#x) pressed.", kbd->new[i]); 35 } 36 } 37 38 input_sync(kbd->dev); 39 memcpy(kbd->old, kbd->new, 8); //更新上个状态值 40 resubmit: 41 i = usb_submit_urb (urb, GFP_ATOMIC); 42 if (i) 43 err ("can't resubmit intr, %s-%s/input0, status %d", 44 kbd->usbdev->bus->bus_name, 45 kbd->usbdev->devpath, i); 46 }

3 usb键盘示例

1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 8 static struct input_dev *myusb_kbd_dev; //input_dev 9 static unsigned char *myusb_kbd_buf; //虚拟地址缓存区 10 static dma_addr_t myusb_kbd_phyc; //DMA缓存区; 11 12 static __le16 myusb_kbd_size; //数据包长度 13 static struct urb *myusb_kbd_urb; //urb 14 15 static const unsigned char usb_kbd_keycode[252] = { 16 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 17 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 18 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, 19 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 20 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 21 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 22 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 23 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 24 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, 25 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 31 150,158,159,128,136,177,178,176,142,152,173,140 32 }; //键盘码表共有252个数据 33 34 35 void my_memcpy(unsigned char *dest,unsigned char *src,int len) //复制缓存 36 { 37 while(len--) 38 { 39 *dest++= *src++; 40 } 41 } 42 43 static void myusb_kbd_irq(struct urb *urb) //键盘中断函数 44 { 45 static unsigned char buf1[8]={0,0,0,0,0,0,0,0}; 46 int i; 47 48 /*上传crtl、shift、atl、windows 等按键*/ 49 for (i = 0; i < 8; i++) 50 if(((myusb_kbd_buf[0]>>i)&1)!=((buf1[0]>>i)&1)) 51 { 52 input_report_key(myusb_kbd_dev, usb_kbd_keycode[i + 224], (myusb_kbd_buf[0]>> i) & 1); 53 input_sync(myusb_kbd_dev); //上传同步事件 54 } 55 56 57 /*上传普通按键*/ 58 for(i=2;icur_altsetting; 80 endpoint = &interface->endpoint[0].desc; //当前接口下的端点描述符 81 printk("VID=%x,PID=%x\n",dev->descriptor.idVendor,dev->descriptor.idProduct); 82 83 /* 1)分配一个input_dev结构体 */ 84 myusb_kbd_dev=input_allocate_device(); 85 86 /* 2)设置input_dev支持 按键事件*/ 87 set_bit(EV_KEY, myusb_kbd_dev->evbit); 88 set_bit(EV_REP, myusb_kbd_dev->evbit); //支持重复按功能 89 90 for (i = 0; i < 252; i++) 91 set_bit(usb_kbd_keycode[i], myusb_kbd_dev->keybit); //添加所有键 92 clear_bit(0, myusb_kbd_dev->keybit); 93 94 /* 3)注册input_dev结构体*/ 95 input_register_device(myusb_kbd_dev); 96 97 /* 4)设置USB键盘数据传输 */ 98 /*->4.1)通过usb_rcvintpipe()创建一个端点管道*/ 99 pipe=usb_rcvintpipe(dev,endpoint->bEndpointAddress); 100 101 /*->4.2)通过usb_buffer_alloc()申请USB缓冲区*/ 102 myusb_kbd_size=endpoint->wMaxPacketSize; 103 myusb_kbd_buf=usb_buffer_alloc(dev,myusb_kbd_size,GFP_ATOMIC,&myusb_kbd_phyc); 104 105 /*->4.3)通过usb_alloc_urb()和usb_fill_int_urb()申请并初始化urb结构体 */ 106 myusb_kbd_urb=usb_alloc_urb(0,GFP_KERNEL); 107 usb_fill_int_urb (myusb_kbd_urb, //urb结构体 108 dev, //usb设备 109 pipe, //端点管道 110 myusb_kbd_buf, //缓存区地址 111 myusb_kbd_size, //数据长度 112 myusb_kbd_irq, //中断函数 113 0, 114 endpoint->bInterval); //中断间隔时间 115 116 /*->4.4) 因为我们2440支持DMA,所以要告诉urb结构体,使用DMA缓冲区地址*/ 117 myusb_kbd_urb->transfer_dma =myusb_kbd_phyc; //设置DMA地址 118 myusb_kbd_urb->transfer_flags =URB_NO_TRANSFER_DMA_MAP; //设置使用DMA地址 119 120 /*->4.5)使用usb_submit_urb()提交urb*/ 121 usb_submit_urb(myusb_kbd_urb, GFP_KERNEL); 122 return 0; 123 } 124 125 static void myusb_kbd_disconnect(struct usb_interface *intf) 126 { 127 struct usb_device *dev = interface_to_usbdev(intf); //设备 128 usb_kill_urb(myusb_kbd_urb); 129 usb_free_urb(myusb_kbd_urb); 130 usb_buffer_free(dev, myusb_kbd_size, myusb_kbd_buf,myusb_kbd_phyc); 131 input_unregister_device(myusb_kbd_dev); //注销内核中的input_dev 132 input_free_device(myusb_kbd_dev); //释放input_dev 133 } 134 135 static struct usb_device_id myusb_kbd_id_table [] = { 136 { USB_INTERFACE_INFO( 137 USB_INTERFACE_CLASS_HID, //接口类:hid类 138 USB_INTERFACE_SUBCLASS_BOOT, //子类:启动设备类 139 USB_INTERFACE_PROTOCOL_KEYBOARD) }, //USB协议:键盘协议 140 }; 141 142 static struct usb_driver myusb_kbd_drv = { 143 .name = "myusb_kbd", 144 .probe = myusb_kbd_probe, 145 .disconnect = myusb_kbd_disconnect, 146 .id_table = myusb_kbd_id_table, 147 }; 148 149 module_usb_driver(usb_kbd_driver);

参考博文:https://www.cnblogs.com/lifexy/p/7645527.html 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有