diff options
Diffstat (limited to 'drivers/usb/input/keyspan_remote.c')
-rw-r--r-- | drivers/usb/input/keyspan_remote.c | 210 |
1 files changed, 87 insertions, 123 deletions
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 99de1b33c07d..5b8d65f62abf 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
21 | #include <linux/input.h> | 21 | #include <linux/input.h> |
22 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
23 | #include <linux/usb_input.h> | ||
23 | 24 | ||
24 | #define DRIVER_VERSION "v0.1" | 25 | #define DRIVER_VERSION "v0.1" |
25 | #define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" | 26 | #define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" |
@@ -75,7 +76,7 @@ struct usb_keyspan { | |||
75 | char name[128]; | 76 | char name[128]; |
76 | char phys[64]; | 77 | char phys[64]; |
77 | struct usb_device* udev; | 78 | struct usb_device* udev; |
78 | struct input_dev input; | 79 | struct input_dev *input; |
79 | struct usb_interface* interface; | 80 | struct usb_interface* interface; |
80 | struct usb_endpoint_descriptor* in_endpoint; | 81 | struct usb_endpoint_descriptor* in_endpoint; |
81 | struct urb* irq_urb; | 82 | struct urb* irq_urb; |
@@ -136,12 +137,11 @@ static struct usb_driver keyspan_driver; | |||
136 | */ | 137 | */ |
137 | static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ | 138 | static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ |
138 | { | 139 | { |
139 | char codes[4*RECV_SIZE]; | 140 | char codes[4 * RECV_SIZE]; |
140 | int i; | 141 | int i; |
141 | 142 | ||
142 | for (i = 0; i < RECV_SIZE; i++) { | 143 | for (i = 0; i < RECV_SIZE; i++) |
143 | snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]); | 144 | snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]); |
144 | } | ||
145 | 145 | ||
146 | dev_info(&dev->udev->dev, "%s\n", codes); | 146 | dev_info(&dev->udev->dev, "%s\n", codes); |
147 | } | 147 | } |
@@ -153,7 +153,7 @@ static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ | |||
153 | static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) | 153 | static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) |
154 | { | 154 | { |
155 | if (dev->data.bits_left >= bits_needed) | 155 | if (dev->data.bits_left >= bits_needed) |
156 | return(0); | 156 | return 0; |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * Somehow we've missed the last message. The message will be repeated | 159 | * Somehow we've missed the last message. The message will be repeated |
@@ -162,7 +162,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) | |||
162 | if (dev->data.pos >= dev->data.len) { | 162 | if (dev->data.pos >= dev->data.len) { |
163 | dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n", | 163 | dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n", |
164 | __FUNCTION__, dev->data.pos, dev->data.len); | 164 | __FUNCTION__, dev->data.pos, dev->data.len); |
165 | return(-1); | 165 | return -1; |
166 | } | 166 | } |
167 | 167 | ||
168 | /* Load as much as we can into the tester. */ | 168 | /* Load as much as we can into the tester. */ |
@@ -172,7 +172,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) | |||
172 | dev->data.bits_left += 8; | 172 | dev->data.bits_left += 8; |
173 | } | 173 | } |
174 | 174 | ||
175 | return(0); | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* | 178 | /* |
@@ -311,10 +311,10 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs) | |||
311 | __FUNCTION__, message.system, message.button, message.toggle); | 311 | __FUNCTION__, message.system, message.button, message.toggle); |
312 | 312 | ||
313 | if (message.toggle != remote->toggle) { | 313 | if (message.toggle != remote->toggle) { |
314 | input_regs(&remote->input, regs); | 314 | input_regs(remote->input, regs); |
315 | input_report_key(&remote->input, keyspan_key_table[message.button], 1); | 315 | input_report_key(remote->input, keyspan_key_table[message.button], 1); |
316 | input_report_key(&remote->input, keyspan_key_table[message.button], 0); | 316 | input_report_key(remote->input, keyspan_key_table[message.button], 0); |
317 | input_sync(&remote->input); | 317 | input_sync(remote->input); |
318 | remote->toggle = message.toggle; | 318 | remote->toggle = message.toggle; |
319 | } | 319 | } |
320 | 320 | ||
@@ -397,14 +397,9 @@ static int keyspan_open(struct input_dev *dev) | |||
397 | { | 397 | { |
398 | struct usb_keyspan *remote = dev->private; | 398 | struct usb_keyspan *remote = dev->private; |
399 | 399 | ||
400 | if (remote->open++) | ||
401 | return 0; | ||
402 | |||
403 | remote->irq_urb->dev = remote->udev; | 400 | remote->irq_urb->dev = remote->udev; |
404 | if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) { | 401 | if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) |
405 | remote->open--; | ||
406 | return -EIO; | 402 | return -EIO; |
407 | } | ||
408 | 403 | ||
409 | return 0; | 404 | return 0; |
410 | } | 405 | } |
@@ -413,8 +408,26 @@ static void keyspan_close(struct input_dev *dev) | |||
413 | { | 408 | { |
414 | struct usb_keyspan *remote = dev->private; | 409 | struct usb_keyspan *remote = dev->private; |
415 | 410 | ||
416 | if (!--remote->open) | 411 | usb_kill_urb(remote->irq_urb); |
417 | usb_kill_urb(remote->irq_urb); | 412 | } |
413 | |||
414 | static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface) | ||
415 | { | ||
416 | |||
417 | struct usb_endpoint_descriptor *endpoint; | ||
418 | int i; | ||
419 | |||
420 | for (i = 0; i < iface->desc.bNumEndpoints; ++i) { | ||
421 | endpoint = &iface->endpoint[i].desc; | ||
422 | |||
423 | if ((endpoint->bEndpointAddress & USB_DIR_IN) && | ||
424 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { | ||
425 | /* we found our interrupt in endpoint */ | ||
426 | return endpoint; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | return NULL; | ||
418 | } | 431 | } |
419 | 432 | ||
420 | /* | 433 | /* |
@@ -422,110 +435,78 @@ static void keyspan_close(struct input_dev *dev) | |||
422 | */ | 435 | */ |
423 | static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) | 436 | static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) |
424 | { | 437 | { |
425 | int i; | 438 | struct usb_device *udev = interface_to_usbdev(interface); |
426 | int retval = -ENOMEM; | ||
427 | char path[64]; | ||
428 | char *buf; | ||
429 | struct usb_keyspan *remote = NULL; | ||
430 | struct usb_host_interface *iface_desc; | ||
431 | struct usb_endpoint_descriptor *endpoint; | 439 | struct usb_endpoint_descriptor *endpoint; |
432 | struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface)); | 440 | struct usb_keyspan *remote; |
441 | struct input_dev *input_dev; | ||
442 | int i, retval; | ||
433 | 443 | ||
434 | /* allocate memory for our device state and initialize it */ | 444 | endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); |
435 | remote = kmalloc(sizeof(*remote), GFP_KERNEL); | 445 | if (!endpoint) |
436 | if (remote == NULL) { | 446 | return -ENODEV; |
437 | err("Out of memory\n"); | 447 | |
438 | goto error; | 448 | remote = kzalloc(sizeof(*remote), GFP_KERNEL); |
449 | input_dev = input_allocate_device(); | ||
450 | if (!remote || !input_dev) { | ||
451 | retval = -ENOMEM; | ||
452 | goto fail1; | ||
439 | } | 453 | } |
440 | memset(remote, 0x00, sizeof(*remote)); | ||
441 | 454 | ||
442 | remote->udev = udev; | 455 | remote->udev = udev; |
456 | remote->input = input_dev; | ||
443 | remote->interface = interface; | 457 | remote->interface = interface; |
458 | remote->in_endpoint = endpoint; | ||
444 | remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ | 459 | remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ |
445 | 460 | ||
446 | /* set up the endpoint information */ | 461 | remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma); |
447 | /* use only the first in interrupt endpoint */ | 462 | if (!remote->in_buffer) { |
448 | iface_desc = interface->cur_altsetting; | 463 | retval = -ENOMEM; |
449 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 464 | goto fail1; |
450 | endpoint = &iface_desc->endpoint[i].desc; | ||
451 | |||
452 | if (!remote->in_endpoint && | ||
453 | (endpoint->bEndpointAddress & USB_DIR_IN) && | ||
454 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { | ||
455 | /* we found our interrupt in endpoint */ | ||
456 | remote->in_endpoint = endpoint; | ||
457 | |||
458 | remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma); | ||
459 | if (!remote->in_buffer) { | ||
460 | retval = -ENOMEM; | ||
461 | goto error; | ||
462 | } | ||
463 | } | ||
464 | } | ||
465 | |||
466 | if (!remote->in_endpoint) { | ||
467 | err("Could not find interrupt input endpoint.\n"); | ||
468 | retval = -ENODEV; | ||
469 | goto error; | ||
470 | } | 465 | } |
471 | 466 | ||
472 | remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); | 467 | remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); |
473 | if (!remote->irq_urb) { | 468 | if (!remote->irq_urb) { |
474 | err("Failed to allocate urb.\n"); | ||
475 | retval = -ENOMEM; | 469 | retval = -ENOMEM; |
476 | goto error; | 470 | goto fail2; |
477 | } | 471 | } |
478 | 472 | ||
479 | retval = keyspan_setup(remote->udev); | 473 | retval = keyspan_setup(udev); |
480 | if (retval) { | 474 | if (retval) { |
481 | err("Failed to setup device.\n"); | ||
482 | retval = -ENODEV; | 475 | retval = -ENODEV; |
483 | goto error; | 476 | goto fail3; |
484 | } | ||
485 | |||
486 | /* | ||
487 | * Setup the input system with the bits we are going to be reporting | ||
488 | */ | ||
489 | remote->input.evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ | ||
490 | for (i = 0; i < 32; ++i) { | ||
491 | if (keyspan_key_table[i] != KEY_RESERVED) { | ||
492 | set_bit(keyspan_key_table[i], remote->input.keybit); | ||
493 | } | ||
494 | } | 477 | } |
495 | 478 | ||
496 | remote->input.private = remote; | 479 | if (udev->manufacturer) |
497 | remote->input.open = keyspan_open; | 480 | strlcpy(remote->name, udev->manufacturer, sizeof(remote->name)); |
498 | remote->input.close = keyspan_close; | ||
499 | |||
500 | usb_make_path(remote->udev, path, 64); | ||
501 | sprintf(remote->phys, "%s/input0", path); | ||
502 | 481 | ||
503 | remote->input.name = remote->name; | 482 | if (udev->product) { |
504 | remote->input.phys = remote->phys; | 483 | if (udev->manufacturer) |
505 | remote->input.id.bustype = BUS_USB; | 484 | strlcat(remote->name, " ", sizeof(remote->name)); |
506 | remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor); | 485 | strlcat(remote->name, udev->product, sizeof(remote->name)); |
507 | remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct); | ||
508 | remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice); | ||
509 | |||
510 | if (!(buf = kmalloc(63, GFP_KERNEL))) { | ||
511 | usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); | ||
512 | kfree(remote); | ||
513 | return -ENOMEM; | ||
514 | } | 486 | } |
515 | 487 | ||
516 | if (remote->udev->descriptor.iManufacturer && | 488 | if (!strlen(remote->name)) |
517 | usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0) | 489 | snprintf(remote->name, sizeof(remote->name), |
518 | strcat(remote->name, buf); | 490 | "USB Keyspan Remote %04x:%04x", |
491 | le16_to_cpu(udev->descriptor.idVendor), | ||
492 | le16_to_cpu(udev->descriptor.idProduct)); | ||
519 | 493 | ||
520 | if (remote->udev->descriptor.iProduct && | 494 | usb_make_path(udev, remote->phys, sizeof(remote->phys)); |
521 | usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0) | 495 | strlcat(remote->phys, "/input0", sizeof(remote->phys)); |
522 | sprintf(remote->name, "%s %s", remote->name, buf); | ||
523 | 496 | ||
524 | if (!strlen(remote->name)) | 497 | input_dev->name = remote->name; |
525 | sprintf(remote->name, "USB Keyspan Remote %04x:%04x", | 498 | input_dev->phys = remote->phys; |
526 | remote->input.id.vendor, remote->input.id.product); | 499 | usb_to_input_id(udev, &input_dev->id); |
500 | input_dev->cdev.dev = &interface->dev; | ||
527 | 501 | ||
528 | kfree(buf); | 502 | input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ |
503 | for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) | ||
504 | if (keyspan_key_table[i] != KEY_RESERVED) | ||
505 | set_bit(keyspan_key_table[i], input_dev->keybit); | ||
506 | |||
507 | input_dev->private = remote; | ||
508 | input_dev->open = keyspan_open; | ||
509 | input_dev->close = keyspan_close; | ||
529 | 510 | ||
530 | /* | 511 | /* |
531 | * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() | 512 | * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() |
@@ -538,27 +519,17 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic | |||
538 | remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 519 | remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
539 | 520 | ||
540 | /* we can register the device now, as it is ready */ | 521 | /* we can register the device now, as it is ready */ |
541 | input_register_device(&remote->input); | 522 | input_register_device(remote->input); |
542 | 523 | ||
543 | /* save our data pointer in this interface device */ | 524 | /* save our data pointer in this interface device */ |
544 | usb_set_intfdata(interface, remote); | 525 | usb_set_intfdata(interface, remote); |
545 | 526 | ||
546 | /* let the user know what node this device is now attached to */ | ||
547 | info("connected: %s on %s", remote->name, path); | ||
548 | return 0; | 527 | return 0; |
549 | 528 | ||
550 | error: | 529 | fail3: usb_free_urb(remote->irq_urb); |
551 | /* | 530 | fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); |
552 | * In case of error we need to clean up any allocated buffers | 531 | fail1: kfree(remote); |
553 | */ | 532 | input_free_device(input_dev); |
554 | if (remote->irq_urb) | ||
555 | usb_free_urb(remote->irq_urb); | ||
556 | |||
557 | if (remote->in_buffer) | ||
558 | usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); | ||
559 | |||
560 | if (remote) | ||
561 | kfree(remote); | ||
562 | 533 | ||
563 | return retval; | 534 | return retval; |
564 | } | 535 | } |
@@ -570,23 +541,16 @@ static void keyspan_disconnect(struct usb_interface *interface) | |||
570 | { | 541 | { |
571 | struct usb_keyspan *remote; | 542 | struct usb_keyspan *remote; |
572 | 543 | ||
573 | /* prevent keyspan_open() from racing keyspan_disconnect() */ | ||
574 | lock_kernel(); | ||
575 | |||
576 | remote = usb_get_intfdata(interface); | 544 | remote = usb_get_intfdata(interface); |
577 | usb_set_intfdata(interface, NULL); | 545 | usb_set_intfdata(interface, NULL); |
578 | 546 | ||
579 | if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ | 547 | if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ |
580 | input_unregister_device(&remote->input); | 548 | input_unregister_device(remote->input); |
581 | usb_kill_urb(remote->irq_urb); | 549 | usb_kill_urb(remote->irq_urb); |
582 | usb_free_urb(remote->irq_urb); | 550 | usb_free_urb(remote->irq_urb); |
583 | usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma); | 551 | usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); |
584 | kfree(remote); | 552 | kfree(remote); |
585 | } | 553 | } |
586 | |||
587 | unlock_kernel(); | ||
588 | |||
589 | info("USB Keyspan now disconnected"); | ||
590 | } | 554 | } |
591 | 555 | ||
592 | /* | 556 | /* |