linux设备驱动(31)usb驱动-usb键盘驱动详解

内核自带的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 <linux/kernel.h>
  2 #include <linux/slab.h>
  3 #include <linux/module.h>
  4 #include <linux/init.h>
  5 #include <linux/usb/input.h>
  6 #include <linux/hid.h>
  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;i<8;i++)
 59     if(myusb_kbd_buf[i]!=buf1[i])
 60     {
 61      if(myusb_kbd_buf[i] )      //按下事件
 62     input_report_key(myusb_kbd_dev,usb_kbd_keycode[myusb_kbd_buf[i]], 1);
 63     else  if(buf1[i])                                             //松开事件
 64     input_report_key(myusb_kbd_dev,usb_kbd_keycode[buf1[i]], 0);
 65     input_sync(myusb_kbd_dev);             //上传同步事件
 66     }
 67 
 68   my_memcpy(buf1, myusb_kbd_buf, 8);       //更新数据
 69   usb_submit_urb(myusb_kbd_urb, GFP_KERNEL);
 70 }
 71 
 72 static int myusb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
 73 {
 74        volatile unsigned char  i;
 75        struct usb_device *dev = interface_to_usbdev(intf);                 //设备
 76        struct usb_endpoint_descriptor *endpoint;
 77        struct usb_host_interface *interface;                                              //当前接口
 78        int pipe;                                                                               //端点管道
 79        interface=intf->cur_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 

posted @ 2020-07-14 21:39  Action_er  阅读(1006)  评论(0编辑  收藏  举报