diff options
Diffstat (limited to 'drivers/usb/misc/phidgetkit.c')
| -rw-r--r-- | drivers/usb/misc/phidgetkit.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 9a8d137d39f9..78e419904abf 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
| @@ -44,20 +44,25 @@ struct driver_interfacekit { | |||
| 44 | int inputs; | 44 | int inputs; |
| 45 | int outputs; | 45 | int outputs; |
| 46 | int has_lcd; | 46 | int has_lcd; |
| 47 | int amnesiac; | ||
| 47 | }; | 48 | }; |
| 48 | #define ifkit(_sensors, _inputs, _outputs, _lcd) \ | 49 | |
| 49 | static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = { \ | 50 | #define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \ |
| 51 | { \ | ||
| 50 | .sensors = _sensors, \ | 52 | .sensors = _sensors, \ |
| 51 | .inputs = _inputs, \ | 53 | .inputs = _inputs, \ |
| 52 | .outputs = _outputs, \ | 54 | .outputs = _outputs, \ |
| 53 | .has_lcd = _lcd, \ | 55 | .has_lcd = _lcd, \ |
| 56 | .amnesiac = _amnesiac \ | ||
| 54 | }; | 57 | }; |
| 55 | ifkit(0, 0, 4, 0); | 58 | |
| 56 | ifkit(8, 8, 8, 0); | 59 | static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0); |
| 57 | ifkit(0, 4, 7, 1); | 60 | static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1); |
| 58 | ifkit(8, 8, 4, 0); | 61 | static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0); |
| 59 | ifkit(0, 8, 8, 1); | 62 | static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0); |
| 60 | ifkit(0, 16, 16, 0); | 63 | static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0); |
| 64 | static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0); | ||
| 65 | static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0); | ||
| 61 | 66 | ||
| 62 | static unsigned long device_no; | 67 | static unsigned long device_no; |
| 63 | 68 | ||
| @@ -77,6 +82,7 @@ struct interfacekit { | |||
| 77 | dma_addr_t data_dma; | 82 | dma_addr_t data_dma; |
| 78 | 83 | ||
| 79 | struct work_struct do_notify; | 84 | struct work_struct do_notify; |
| 85 | struct work_struct do_resubmit; | ||
| 80 | unsigned long input_events; | 86 | unsigned long input_events; |
| 81 | unsigned long sensor_events; | 87 | unsigned long sensor_events; |
| 82 | }; | 88 | }; |
| @@ -84,8 +90,10 @@ struct interfacekit { | |||
| 84 | static struct usb_device_id id_table[] = { | 90 | static struct usb_device_id id_table[] = { |
| 85 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), | 91 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), |
| 86 | .driver_info = (kernel_ulong_t)&ph_004}, | 92 | .driver_info = (kernel_ulong_t)&ph_004}, |
| 87 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888), | 93 | {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814), |
| 88 | .driver_info = (kernel_ulong_t)&ph_888}, | 94 | .driver_info = (kernel_ulong_t)&ph_888o}, |
| 95 | {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff), | ||
| 96 | .driver_info = (kernel_ulong_t)&ph_888n}, | ||
| 89 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), | 97 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), |
| 90 | .driver_info = (kernel_ulong_t)&ph_047}, | 98 | .driver_info = (kernel_ulong_t)&ph_047}, |
| 91 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), | 99 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), |
| @@ -98,16 +106,11 @@ static struct usb_device_id id_table[] = { | |||
| 98 | }; | 106 | }; |
| 99 | MODULE_DEVICE_TABLE(usb, id_table); | 107 | MODULE_DEVICE_TABLE(usb, id_table); |
| 100 | 108 | ||
| 101 | static int change_outputs(struct interfacekit *kit, int output_num, int enable) | 109 | static int set_outputs(struct interfacekit *kit) |
| 102 | { | 110 | { |
| 103 | u8 *buffer; | 111 | u8 *buffer; |
| 104 | int retval; | 112 | int retval; |
| 105 | 113 | ||
| 106 | if (enable) | ||
| 107 | set_bit(output_num, &kit->outputs); | ||
| 108 | else | ||
| 109 | clear_bit(output_num, &kit->outputs); | ||
| 110 | |||
| 111 | buffer = kzalloc(4, GFP_KERNEL); | 114 | buffer = kzalloc(4, GFP_KERNEL); |
| 112 | if (!buffer) { | 115 | if (!buffer) { |
| 113 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); | 116 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); |
| @@ -127,6 +130,9 @@ static int change_outputs(struct interfacekit *kit, int output_num, int enable) | |||
| 127 | retval); | 130 | retval); |
| 128 | kfree(buffer); | 131 | kfree(buffer); |
| 129 | 132 | ||
| 133 | if (kit->ifkit->amnesiac) | ||
| 134 | schedule_delayed_work(&kit->do_resubmit, HZ / 2); | ||
| 135 | |||
| 130 | return retval < 0 ? retval : 0; | 136 | return retval < 0 ? retval : 0; |
| 131 | } | 137 | } |
| 132 | 138 | ||
| @@ -399,19 +405,29 @@ static void do_notify(void *data) | |||
| 399 | } | 405 | } |
| 400 | } | 406 | } |
| 401 | 407 | ||
| 408 | static void do_resubmit(void *data) | ||
| 409 | { | ||
| 410 | set_outputs(data); | ||
| 411 | } | ||
| 412 | |||
| 402 | #define show_set_output(value) \ | 413 | #define show_set_output(value) \ |
| 403 | static ssize_t set_output##value(struct device *dev, \ | 414 | static ssize_t set_output##value(struct device *dev, \ |
| 404 | struct device_attribute *attr, \ | 415 | struct device_attribute *attr, \ |
| 405 | const char *buf, size_t count) \ | 416 | const char *buf, size_t count) \ |
| 406 | { \ | 417 | { \ |
| 407 | struct interfacekit *kit = dev_get_drvdata(dev); \ | 418 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
| 408 | int enabled; \ | 419 | int enable; \ |
| 409 | int retval; \ | 420 | int retval; \ |
| 410 | \ | 421 | \ |
| 411 | if (sscanf(buf, "%d", &enabled) < 1) \ | 422 | if (sscanf(buf, "%d", &enable) < 1) \ |
| 412 | return -EINVAL; \ | 423 | return -EINVAL; \ |
| 413 | \ | 424 | \ |
| 414 | retval = change_outputs(kit, value - 1, enabled); \ | 425 | if (enable) \ |
| 426 | set_bit(value - 1, &kit->outputs); \ | ||
| 427 | else \ | ||
| 428 | clear_bit(value - 1, &kit->outputs); \ | ||
| 429 | \ | ||
| 430 | retval = set_outputs(kit); \ | ||
| 415 | \ | 431 | \ |
| 416 | return retval ? retval : count; \ | 432 | return retval ? retval : count; \ |
| 417 | } \ | 433 | } \ |
| @@ -560,6 +576,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 560 | kit->udev = usb_get_dev(dev); | 576 | kit->udev = usb_get_dev(dev); |
| 561 | kit->intf = intf; | 577 | kit->intf = intf; |
| 562 | INIT_WORK(&kit->do_notify, do_notify, kit); | 578 | INIT_WORK(&kit->do_notify, do_notify, kit); |
| 579 | INIT_WORK(&kit->do_resubmit, do_resubmit, kit); | ||
| 563 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, | 580 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, |
| 564 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, | 581 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, |
| 565 | interfacekit_irq, kit, endpoint->bInterval); | 582 | interfacekit_irq, kit, endpoint->bInterval); |
| @@ -663,6 +680,7 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
| 663 | usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); | 680 | usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); |
| 664 | 681 | ||
| 665 | cancel_delayed_work(&kit->do_notify); | 682 | cancel_delayed_work(&kit->do_notify); |
| 683 | cancel_delayed_work(&kit->do_resubmit); | ||
| 666 | 684 | ||
| 667 | for (i=0; i<kit->ifkit->outputs; i++) | 685 | for (i=0; i<kit->ifkit->outputs; i++) |
| 668 | device_remove_file(kit->dev, &dev_output_attrs[i]); | 686 | device_remove_file(kit->dev, &dev_output_attrs[i]); |
