1*6db3dfefSJiri Kosina /* 2*6db3dfefSJiri Kosina * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $ 3*6db3dfefSJiri Kosina * 4*6db3dfefSJiri Kosina * Copyright (c) 1999-2001 Vojtech Pavlik 5*6db3dfefSJiri Kosina * 6*6db3dfefSJiri Kosina * USB HIDBP Keyboard support 7*6db3dfefSJiri Kosina */ 8*6db3dfefSJiri Kosina 9*6db3dfefSJiri Kosina /* 10*6db3dfefSJiri Kosina * This program is free software; you can redistribute it and/or modify 11*6db3dfefSJiri Kosina * it under the terms of the GNU General Public License as published by 12*6db3dfefSJiri Kosina * the Free Software Foundation; either version 2 of the License, or 13*6db3dfefSJiri Kosina * (at your option) any later version. 14*6db3dfefSJiri Kosina * 15*6db3dfefSJiri Kosina * This program is distributed in the hope that it will be useful, 16*6db3dfefSJiri Kosina * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*6db3dfefSJiri Kosina * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*6db3dfefSJiri Kosina * GNU General Public License for more details. 19*6db3dfefSJiri Kosina * 20*6db3dfefSJiri Kosina * You should have received a copy of the GNU General Public License 21*6db3dfefSJiri Kosina * along with this program; if not, write to the Free Software 22*6db3dfefSJiri Kosina * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23*6db3dfefSJiri Kosina * 24*6db3dfefSJiri Kosina * Should you need to contact me, the author, you can do so either by 25*6db3dfefSJiri Kosina * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: 26*6db3dfefSJiri Kosina * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 27*6db3dfefSJiri Kosina */ 28*6db3dfefSJiri Kosina 29*6db3dfefSJiri Kosina #include <linux/kernel.h> 30*6db3dfefSJiri Kosina #include <linux/slab.h> 31*6db3dfefSJiri Kosina #include <linux/module.h> 32*6db3dfefSJiri Kosina #include <linux/init.h> 33*6db3dfefSJiri Kosina #include <linux/usb/input.h> 34*6db3dfefSJiri Kosina #include <linux/hid.h> 35*6db3dfefSJiri Kosina 36*6db3dfefSJiri Kosina /* 37*6db3dfefSJiri Kosina * Version Information 38*6db3dfefSJiri Kosina */ 39*6db3dfefSJiri Kosina #define DRIVER_VERSION "" 40*6db3dfefSJiri Kosina #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" 41*6db3dfefSJiri Kosina #define DRIVER_DESC "USB HID Boot Protocol keyboard driver" 42*6db3dfefSJiri Kosina #define DRIVER_LICENSE "GPL" 43*6db3dfefSJiri Kosina 44*6db3dfefSJiri Kosina MODULE_AUTHOR(DRIVER_AUTHOR); 45*6db3dfefSJiri Kosina MODULE_DESCRIPTION(DRIVER_DESC); 46*6db3dfefSJiri Kosina MODULE_LICENSE(DRIVER_LICENSE); 47*6db3dfefSJiri Kosina 48*6db3dfefSJiri Kosina static unsigned char usb_kbd_keycode[256] = { 49*6db3dfefSJiri Kosina 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50*6db3dfefSJiri Kosina 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 51*6db3dfefSJiri Kosina 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, 52*6db3dfefSJiri Kosina 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 53*6db3dfefSJiri Kosina 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 54*6db3dfefSJiri Kosina 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 55*6db3dfefSJiri Kosina 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 56*6db3dfefSJiri Kosina 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 57*6db3dfefSJiri Kosina 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, 58*6db3dfefSJiri Kosina 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59*6db3dfefSJiri Kosina 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60*6db3dfefSJiri Kosina 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61*6db3dfefSJiri Kosina 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62*6db3dfefSJiri Kosina 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63*6db3dfefSJiri Kosina 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 64*6db3dfefSJiri Kosina 150,158,159,128,136,177,178,176,142,152,173,140 65*6db3dfefSJiri Kosina }; 66*6db3dfefSJiri Kosina 67*6db3dfefSJiri Kosina struct usb_kbd { 68*6db3dfefSJiri Kosina struct input_dev *dev; 69*6db3dfefSJiri Kosina struct usb_device *usbdev; 70*6db3dfefSJiri Kosina unsigned char old[8]; 71*6db3dfefSJiri Kosina struct urb *irq, *led; 72*6db3dfefSJiri Kosina unsigned char newleds; 73*6db3dfefSJiri Kosina char name[128]; 74*6db3dfefSJiri Kosina char phys[64]; 75*6db3dfefSJiri Kosina 76*6db3dfefSJiri Kosina unsigned char *new; 77*6db3dfefSJiri Kosina struct usb_ctrlrequest *cr; 78*6db3dfefSJiri Kosina unsigned char *leds; 79*6db3dfefSJiri Kosina dma_addr_t cr_dma; 80*6db3dfefSJiri Kosina dma_addr_t new_dma; 81*6db3dfefSJiri Kosina dma_addr_t leds_dma; 82*6db3dfefSJiri Kosina }; 83*6db3dfefSJiri Kosina 84*6db3dfefSJiri Kosina static void usb_kbd_irq(struct urb *urb) 85*6db3dfefSJiri Kosina { 86*6db3dfefSJiri Kosina struct usb_kbd *kbd = urb->context; 87*6db3dfefSJiri Kosina int i; 88*6db3dfefSJiri Kosina 89*6db3dfefSJiri Kosina switch (urb->status) { 90*6db3dfefSJiri Kosina case 0: /* success */ 91*6db3dfefSJiri Kosina break; 92*6db3dfefSJiri Kosina case -ECONNRESET: /* unlink */ 93*6db3dfefSJiri Kosina case -ENOENT: 94*6db3dfefSJiri Kosina case -ESHUTDOWN: 95*6db3dfefSJiri Kosina return; 96*6db3dfefSJiri Kosina /* -EPIPE: should clear the halt */ 97*6db3dfefSJiri Kosina default: /* error */ 98*6db3dfefSJiri Kosina goto resubmit; 99*6db3dfefSJiri Kosina } 100*6db3dfefSJiri Kosina 101*6db3dfefSJiri Kosina for (i = 0; i < 8; i++) 102*6db3dfefSJiri Kosina input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); 103*6db3dfefSJiri Kosina 104*6db3dfefSJiri Kosina for (i = 2; i < 8; i++) { 105*6db3dfefSJiri Kosina 106*6db3dfefSJiri Kosina if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { 107*6db3dfefSJiri Kosina if (usb_kbd_keycode[kbd->old[i]]) 108*6db3dfefSJiri Kosina input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); 109*6db3dfefSJiri Kosina else 110*6db3dfefSJiri Kosina info("Unknown key (scancode %#x) released.", kbd->old[i]); 111*6db3dfefSJiri Kosina } 112*6db3dfefSJiri Kosina 113*6db3dfefSJiri Kosina if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { 114*6db3dfefSJiri Kosina if (usb_kbd_keycode[kbd->new[i]]) 115*6db3dfefSJiri Kosina input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); 116*6db3dfefSJiri Kosina else 117*6db3dfefSJiri Kosina info("Unknown key (scancode %#x) pressed.", kbd->new[i]); 118*6db3dfefSJiri Kosina } 119*6db3dfefSJiri Kosina } 120*6db3dfefSJiri Kosina 121*6db3dfefSJiri Kosina input_sync(kbd->dev); 122*6db3dfefSJiri Kosina 123*6db3dfefSJiri Kosina memcpy(kbd->old, kbd->new, 8); 124*6db3dfefSJiri Kosina 125*6db3dfefSJiri Kosina resubmit: 126*6db3dfefSJiri Kosina i = usb_submit_urb (urb, GFP_ATOMIC); 127*6db3dfefSJiri Kosina if (i) 128*6db3dfefSJiri Kosina err ("can't resubmit intr, %s-%s/input0, status %d", 129*6db3dfefSJiri Kosina kbd->usbdev->bus->bus_name, 130*6db3dfefSJiri Kosina kbd->usbdev->devpath, i); 131*6db3dfefSJiri Kosina } 132*6db3dfefSJiri Kosina 133*6db3dfefSJiri Kosina static int usb_kbd_event(struct input_dev *dev, unsigned int type, 134*6db3dfefSJiri Kosina unsigned int code, int value) 135*6db3dfefSJiri Kosina { 136*6db3dfefSJiri Kosina struct usb_kbd *kbd = dev->private; 137*6db3dfefSJiri Kosina 138*6db3dfefSJiri Kosina if (type != EV_LED) 139*6db3dfefSJiri Kosina return -1; 140*6db3dfefSJiri Kosina 141*6db3dfefSJiri Kosina 142*6db3dfefSJiri Kosina kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | 143*6db3dfefSJiri Kosina (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | 144*6db3dfefSJiri Kosina (!!test_bit(LED_NUML, dev->led)); 145*6db3dfefSJiri Kosina 146*6db3dfefSJiri Kosina if (kbd->led->status == -EINPROGRESS) 147*6db3dfefSJiri Kosina return 0; 148*6db3dfefSJiri Kosina 149*6db3dfefSJiri Kosina if (*(kbd->leds) == kbd->newleds) 150*6db3dfefSJiri Kosina return 0; 151*6db3dfefSJiri Kosina 152*6db3dfefSJiri Kosina *(kbd->leds) = kbd->newleds; 153*6db3dfefSJiri Kosina kbd->led->dev = kbd->usbdev; 154*6db3dfefSJiri Kosina if (usb_submit_urb(kbd->led, GFP_ATOMIC)) 155*6db3dfefSJiri Kosina err("usb_submit_urb(leds) failed"); 156*6db3dfefSJiri Kosina 157*6db3dfefSJiri Kosina return 0; 158*6db3dfefSJiri Kosina } 159*6db3dfefSJiri Kosina 160*6db3dfefSJiri Kosina static void usb_kbd_led(struct urb *urb) 161*6db3dfefSJiri Kosina { 162*6db3dfefSJiri Kosina struct usb_kbd *kbd = urb->context; 163*6db3dfefSJiri Kosina 164*6db3dfefSJiri Kosina if (urb->status) 165*6db3dfefSJiri Kosina warn("led urb status %d received", urb->status); 166*6db3dfefSJiri Kosina 167*6db3dfefSJiri Kosina if (*(kbd->leds) == kbd->newleds) 168*6db3dfefSJiri Kosina return; 169*6db3dfefSJiri Kosina 170*6db3dfefSJiri Kosina *(kbd->leds) = kbd->newleds; 171*6db3dfefSJiri Kosina kbd->led->dev = kbd->usbdev; 172*6db3dfefSJiri Kosina if (usb_submit_urb(kbd->led, GFP_ATOMIC)) 173*6db3dfefSJiri Kosina err("usb_submit_urb(leds) failed"); 174*6db3dfefSJiri Kosina } 175*6db3dfefSJiri Kosina 176*6db3dfefSJiri Kosina static int usb_kbd_open(struct input_dev *dev) 177*6db3dfefSJiri Kosina { 178*6db3dfefSJiri Kosina struct usb_kbd *kbd = dev->private; 179*6db3dfefSJiri Kosina 180*6db3dfefSJiri Kosina kbd->irq->dev = kbd->usbdev; 181*6db3dfefSJiri Kosina if (usb_submit_urb(kbd->irq, GFP_KERNEL)) 182*6db3dfefSJiri Kosina return -EIO; 183*6db3dfefSJiri Kosina 184*6db3dfefSJiri Kosina return 0; 185*6db3dfefSJiri Kosina } 186*6db3dfefSJiri Kosina 187*6db3dfefSJiri Kosina static void usb_kbd_close(struct input_dev *dev) 188*6db3dfefSJiri Kosina { 189*6db3dfefSJiri Kosina struct usb_kbd *kbd = dev->private; 190*6db3dfefSJiri Kosina 191*6db3dfefSJiri Kosina usb_kill_urb(kbd->irq); 192*6db3dfefSJiri Kosina } 193*6db3dfefSJiri Kosina 194*6db3dfefSJiri Kosina static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) 195*6db3dfefSJiri Kosina { 196*6db3dfefSJiri Kosina if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) 197*6db3dfefSJiri Kosina return -1; 198*6db3dfefSJiri Kosina if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) 199*6db3dfefSJiri Kosina return -1; 200*6db3dfefSJiri Kosina if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) 201*6db3dfefSJiri Kosina return -1; 202*6db3dfefSJiri Kosina if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma))) 203*6db3dfefSJiri Kosina return -1; 204*6db3dfefSJiri Kosina if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) 205*6db3dfefSJiri Kosina return -1; 206*6db3dfefSJiri Kosina 207*6db3dfefSJiri Kosina return 0; 208*6db3dfefSJiri Kosina } 209*6db3dfefSJiri Kosina 210*6db3dfefSJiri Kosina static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) 211*6db3dfefSJiri Kosina { 212*6db3dfefSJiri Kosina usb_free_urb(kbd->irq); 213*6db3dfefSJiri Kosina usb_free_urb(kbd->led); 214*6db3dfefSJiri Kosina if (kbd->new) 215*6db3dfefSJiri Kosina usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); 216*6db3dfefSJiri Kosina if (kbd->cr) 217*6db3dfefSJiri Kosina usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); 218*6db3dfefSJiri Kosina if (kbd->leds) 219*6db3dfefSJiri Kosina usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); 220*6db3dfefSJiri Kosina } 221*6db3dfefSJiri Kosina 222*6db3dfefSJiri Kosina static int usb_kbd_probe(struct usb_interface *iface, 223*6db3dfefSJiri Kosina const struct usb_device_id *id) 224*6db3dfefSJiri Kosina { 225*6db3dfefSJiri Kosina struct usb_device *dev = interface_to_usbdev(iface); 226*6db3dfefSJiri Kosina struct usb_host_interface *interface; 227*6db3dfefSJiri Kosina struct usb_endpoint_descriptor *endpoint; 228*6db3dfefSJiri Kosina struct usb_kbd *kbd; 229*6db3dfefSJiri Kosina struct input_dev *input_dev; 230*6db3dfefSJiri Kosina int i, pipe, maxp; 231*6db3dfefSJiri Kosina 232*6db3dfefSJiri Kosina interface = iface->cur_altsetting; 233*6db3dfefSJiri Kosina 234*6db3dfefSJiri Kosina if (interface->desc.bNumEndpoints != 1) 235*6db3dfefSJiri Kosina return -ENODEV; 236*6db3dfefSJiri Kosina 237*6db3dfefSJiri Kosina endpoint = &interface->endpoint[0].desc; 238*6db3dfefSJiri Kosina if (!usb_endpoint_is_int_in(endpoint)) 239*6db3dfefSJiri Kosina return -ENODEV; 240*6db3dfefSJiri Kosina 241*6db3dfefSJiri Kosina pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 242*6db3dfefSJiri Kosina maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 243*6db3dfefSJiri Kosina 244*6db3dfefSJiri Kosina kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); 245*6db3dfefSJiri Kosina input_dev = input_allocate_device(); 246*6db3dfefSJiri Kosina if (!kbd || !input_dev) 247*6db3dfefSJiri Kosina goto fail1; 248*6db3dfefSJiri Kosina 249*6db3dfefSJiri Kosina if (usb_kbd_alloc_mem(dev, kbd)) 250*6db3dfefSJiri Kosina goto fail2; 251*6db3dfefSJiri Kosina 252*6db3dfefSJiri Kosina kbd->usbdev = dev; 253*6db3dfefSJiri Kosina kbd->dev = input_dev; 254*6db3dfefSJiri Kosina 255*6db3dfefSJiri Kosina if (dev->manufacturer) 256*6db3dfefSJiri Kosina strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); 257*6db3dfefSJiri Kosina 258*6db3dfefSJiri Kosina if (dev->product) { 259*6db3dfefSJiri Kosina if (dev->manufacturer) 260*6db3dfefSJiri Kosina strlcat(kbd->name, " ", sizeof(kbd->name)); 261*6db3dfefSJiri Kosina strlcat(kbd->name, dev->product, sizeof(kbd->name)); 262*6db3dfefSJiri Kosina } 263*6db3dfefSJiri Kosina 264*6db3dfefSJiri Kosina if (!strlen(kbd->name)) 265*6db3dfefSJiri Kosina snprintf(kbd->name, sizeof(kbd->name), 266*6db3dfefSJiri Kosina "USB HIDBP Keyboard %04x:%04x", 267*6db3dfefSJiri Kosina le16_to_cpu(dev->descriptor.idVendor), 268*6db3dfefSJiri Kosina le16_to_cpu(dev->descriptor.idProduct)); 269*6db3dfefSJiri Kosina 270*6db3dfefSJiri Kosina usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); 271*6db3dfefSJiri Kosina strlcpy(kbd->phys, "/input0", sizeof(kbd->phys)); 272*6db3dfefSJiri Kosina 273*6db3dfefSJiri Kosina input_dev->name = kbd->name; 274*6db3dfefSJiri Kosina input_dev->phys = kbd->phys; 275*6db3dfefSJiri Kosina usb_to_input_id(dev, &input_dev->id); 276*6db3dfefSJiri Kosina input_dev->cdev.dev = &iface->dev; 277*6db3dfefSJiri Kosina input_dev->private = kbd; 278*6db3dfefSJiri Kosina 279*6db3dfefSJiri Kosina input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); 280*6db3dfefSJiri Kosina input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); 281*6db3dfefSJiri Kosina 282*6db3dfefSJiri Kosina for (i = 0; i < 255; i++) 283*6db3dfefSJiri Kosina set_bit(usb_kbd_keycode[i], input_dev->keybit); 284*6db3dfefSJiri Kosina clear_bit(0, input_dev->keybit); 285*6db3dfefSJiri Kosina 286*6db3dfefSJiri Kosina input_dev->event = usb_kbd_event; 287*6db3dfefSJiri Kosina input_dev->open = usb_kbd_open; 288*6db3dfefSJiri Kosina input_dev->close = usb_kbd_close; 289*6db3dfefSJiri Kosina 290*6db3dfefSJiri Kosina usb_fill_int_urb(kbd->irq, dev, pipe, 291*6db3dfefSJiri Kosina kbd->new, (maxp > 8 ? 8 : maxp), 292*6db3dfefSJiri Kosina usb_kbd_irq, kbd, endpoint->bInterval); 293*6db3dfefSJiri Kosina kbd->irq->transfer_dma = kbd->new_dma; 294*6db3dfefSJiri Kosina kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 295*6db3dfefSJiri Kosina 296*6db3dfefSJiri Kosina kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; 297*6db3dfefSJiri Kosina kbd->cr->bRequest = 0x09; 298*6db3dfefSJiri Kosina kbd->cr->wValue = cpu_to_le16(0x200); 299*6db3dfefSJiri Kosina kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); 300*6db3dfefSJiri Kosina kbd->cr->wLength = cpu_to_le16(1); 301*6db3dfefSJiri Kosina 302*6db3dfefSJiri Kosina usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), 303*6db3dfefSJiri Kosina (void *) kbd->cr, kbd->leds, 1, 304*6db3dfefSJiri Kosina usb_kbd_led, kbd); 305*6db3dfefSJiri Kosina kbd->led->setup_dma = kbd->cr_dma; 306*6db3dfefSJiri Kosina kbd->led->transfer_dma = kbd->leds_dma; 307*6db3dfefSJiri Kosina kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); 308*6db3dfefSJiri Kosina 309*6db3dfefSJiri Kosina input_register_device(kbd->dev); 310*6db3dfefSJiri Kosina 311*6db3dfefSJiri Kosina usb_set_intfdata(iface, kbd); 312*6db3dfefSJiri Kosina return 0; 313*6db3dfefSJiri Kosina 314*6db3dfefSJiri Kosina fail2: usb_kbd_free_mem(dev, kbd); 315*6db3dfefSJiri Kosina fail1: input_free_device(input_dev); 316*6db3dfefSJiri Kosina kfree(kbd); 317*6db3dfefSJiri Kosina return -ENOMEM; 318*6db3dfefSJiri Kosina } 319*6db3dfefSJiri Kosina 320*6db3dfefSJiri Kosina static void usb_kbd_disconnect(struct usb_interface *intf) 321*6db3dfefSJiri Kosina { 322*6db3dfefSJiri Kosina struct usb_kbd *kbd = usb_get_intfdata (intf); 323*6db3dfefSJiri Kosina 324*6db3dfefSJiri Kosina usb_set_intfdata(intf, NULL); 325*6db3dfefSJiri Kosina if (kbd) { 326*6db3dfefSJiri Kosina usb_kill_urb(kbd->irq); 327*6db3dfefSJiri Kosina input_unregister_device(kbd->dev); 328*6db3dfefSJiri Kosina usb_kbd_free_mem(interface_to_usbdev(intf), kbd); 329*6db3dfefSJiri Kosina kfree(kbd); 330*6db3dfefSJiri Kosina } 331*6db3dfefSJiri Kosina } 332*6db3dfefSJiri Kosina 333*6db3dfefSJiri Kosina static struct usb_device_id usb_kbd_id_table [] = { 334*6db3dfefSJiri Kosina { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, 335*6db3dfefSJiri Kosina USB_INTERFACE_PROTOCOL_KEYBOARD) }, 336*6db3dfefSJiri Kosina { } /* Terminating entry */ 337*6db3dfefSJiri Kosina }; 338*6db3dfefSJiri Kosina 339*6db3dfefSJiri Kosina MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); 340*6db3dfefSJiri Kosina 341*6db3dfefSJiri Kosina static struct usb_driver usb_kbd_driver = { 342*6db3dfefSJiri Kosina .name = "usbkbd", 343*6db3dfefSJiri Kosina .probe = usb_kbd_probe, 344*6db3dfefSJiri Kosina .disconnect = usb_kbd_disconnect, 345*6db3dfefSJiri Kosina .id_table = usb_kbd_id_table, 346*6db3dfefSJiri Kosina }; 347*6db3dfefSJiri Kosina 348*6db3dfefSJiri Kosina static int __init usb_kbd_init(void) 349*6db3dfefSJiri Kosina { 350*6db3dfefSJiri Kosina int result = usb_register(&usb_kbd_driver); 351*6db3dfefSJiri Kosina if (result == 0) 352*6db3dfefSJiri Kosina info(DRIVER_VERSION ":" DRIVER_DESC); 353*6db3dfefSJiri Kosina return result; 354*6db3dfefSJiri Kosina } 355*6db3dfefSJiri Kosina 356*6db3dfefSJiri Kosina static void __exit usb_kbd_exit(void) 357*6db3dfefSJiri Kosina { 358*6db3dfefSJiri Kosina usb_deregister(&usb_kbd_driver); 359*6db3dfefSJiri Kosina } 360*6db3dfefSJiri Kosina 361*6db3dfefSJiri Kosina module_init(usb_kbd_init); 362*6db3dfefSJiri Kosina module_exit(usb_kbd_exit); 363