diff options
Diffstat (limited to 'drivers/usb')
-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]); |