diff options
Diffstat (limited to 'drivers/usb/misc/phidgetkit.c')
-rw-r--r-- | drivers/usb/misc/phidgetkit.c | 373 |
1 files changed, 198 insertions, 175 deletions
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 13aeea2026c..78e419904ab 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
@@ -13,7 +13,6 @@ | |||
13 | * This is a driver for the USB PhidgetInterfaceKit. | 13 | * This is a driver for the USB PhidgetInterfaceKit. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
@@ -21,6 +20,8 @@ | |||
21 | #include <linux/module.h> | 20 | #include <linux/module.h> |
22 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
23 | 22 | ||
23 | #include "phidget.h" | ||
24 | |||
24 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 25 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
25 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" | 26 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" |
26 | 27 | ||
@@ -43,26 +44,35 @@ struct driver_interfacekit { | |||
43 | int inputs; | 44 | int inputs; |
44 | int outputs; | 45 | int outputs; |
45 | int has_lcd; | 46 | int has_lcd; |
47 | int amnesiac; | ||
46 | }; | 48 | }; |
47 | #define ifkit(_sensors, _inputs, _outputs, _lcd) \ | 49 | |
48 | static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = { \ | 50 | #define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \ |
51 | { \ | ||
49 | .sensors = _sensors, \ | 52 | .sensors = _sensors, \ |
50 | .inputs = _inputs, \ | 53 | .inputs = _inputs, \ |
51 | .outputs = _outputs, \ | 54 | .outputs = _outputs, \ |
52 | .has_lcd = _lcd, \ | 55 | .has_lcd = _lcd, \ |
56 | .amnesiac = _amnesiac \ | ||
53 | }; | 57 | }; |
54 | ifkit(0, 0, 4, 0); | 58 | |
55 | ifkit(8, 8, 8, 0); | 59 | static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0); |
56 | ifkit(0, 4, 7, 1); | 60 | static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1); |
57 | ifkit(8, 8, 4, 0); | 61 | static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0); |
58 | ifkit(0, 8, 8, 1); | 62 | static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0); |
59 | 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); | ||
66 | |||
67 | static unsigned long device_no; | ||
60 | 68 | ||
61 | struct interfacekit { | 69 | struct interfacekit { |
62 | struct usb_device *udev; | 70 | struct usb_device *udev; |
63 | struct usb_interface *intf; | 71 | struct usb_interface *intf; |
64 | struct driver_interfacekit *ifkit; | 72 | struct driver_interfacekit *ifkit; |
73 | struct device *dev; | ||
65 | unsigned long outputs; | 74 | unsigned long outputs; |
75 | int dev_no; | ||
66 | u8 inputs[MAX_INTERFACES]; | 76 | u8 inputs[MAX_INTERFACES]; |
67 | u16 sensors[MAX_INTERFACES]; | 77 | u16 sensors[MAX_INTERFACES]; |
68 | u8 lcd_files_on; | 78 | u8 lcd_files_on; |
@@ -72,6 +82,7 @@ struct interfacekit { | |||
72 | dma_addr_t data_dma; | 82 | dma_addr_t data_dma; |
73 | 83 | ||
74 | struct work_struct do_notify; | 84 | struct work_struct do_notify; |
85 | struct work_struct do_resubmit; | ||
75 | unsigned long input_events; | 86 | unsigned long input_events; |
76 | unsigned long sensor_events; | 87 | unsigned long sensor_events; |
77 | }; | 88 | }; |
@@ -79,8 +90,10 @@ struct interfacekit { | |||
79 | static struct usb_device_id id_table[] = { | 90 | static struct usb_device_id id_table[] = { |
80 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), | 91 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), |
81 | .driver_info = (kernel_ulong_t)&ph_004}, | 92 | .driver_info = (kernel_ulong_t)&ph_004}, |
82 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888), | 93 | {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814), |
83 | .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}, | ||
84 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), | 97 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), |
85 | .driver_info = (kernel_ulong_t)&ph_047}, | 98 | .driver_info = (kernel_ulong_t)&ph_047}, |
86 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), | 99 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), |
@@ -93,16 +106,11 @@ static struct usb_device_id id_table[] = { | |||
93 | }; | 106 | }; |
94 | MODULE_DEVICE_TABLE(usb, id_table); | 107 | MODULE_DEVICE_TABLE(usb, id_table); |
95 | 108 | ||
96 | static int change_outputs(struct interfacekit *kit, int output_num, int enable) | 109 | static int set_outputs(struct interfacekit *kit) |
97 | { | 110 | { |
98 | u8 *buffer; | 111 | u8 *buffer; |
99 | int retval; | 112 | int retval; |
100 | 113 | ||
101 | if (enable) | ||
102 | set_bit(output_num, &kit->outputs); | ||
103 | else | ||
104 | clear_bit(output_num, &kit->outputs); | ||
105 | |||
106 | buffer = kzalloc(4, GFP_KERNEL); | 114 | buffer = kzalloc(4, GFP_KERNEL); |
107 | if (!buffer) { | 115 | if (!buffer) { |
108 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); | 116 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); |
@@ -122,6 +130,9 @@ static int change_outputs(struct interfacekit *kit, int output_num, int enable) | |||
122 | retval); | 130 | retval); |
123 | kfree(buffer); | 131 | kfree(buffer); |
124 | 132 | ||
133 | if (kit->ifkit->amnesiac) | ||
134 | schedule_delayed_work(&kit->do_resubmit, HZ / 2); | ||
135 | |||
125 | return retval < 0 ? retval : 0; | 136 | return retval < 0 ? retval : 0; |
126 | } | 137 | } |
127 | 138 | ||
@@ -181,21 +192,24 @@ exit: | |||
181 | } | 192 | } |
182 | 193 | ||
183 | #define set_lcd_line(number) \ | 194 | #define set_lcd_line(number) \ |
184 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 195 | static ssize_t lcd_line_##number(struct device *dev, \ |
185 | { \ | 196 | struct device_attribute *attr, \ |
186 | struct usb_interface *intf = to_usb_interface(dev); \ | 197 | const char *buf, size_t count) \ |
187 | struct interfacekit *kit = usb_get_intfdata(intf); \ | 198 | { \ |
188 | change_string(kit, buf, number - 1); \ | 199 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
189 | return count; \ | 200 | change_string(kit, buf, number - 1); \ |
190 | } \ | 201 | return count; \ |
191 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); | 202 | } |
203 | |||
204 | #define lcd_line_attr(number) \ | ||
205 | __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) | ||
206 | |||
192 | set_lcd_line(1); | 207 | set_lcd_line(1); |
193 | set_lcd_line(2); | 208 | set_lcd_line(2); |
194 | 209 | ||
195 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 210 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
196 | { | 211 | { |
197 | struct usb_interface *intf = to_usb_interface(dev); | 212 | struct interfacekit *kit = dev_get_drvdata(dev); |
198 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
199 | int enabled; | 213 | int enabled; |
200 | unsigned char *buffer; | 214 | unsigned char *buffer; |
201 | int retval = -ENOMEM; | 215 | int retval = -ENOMEM; |
@@ -227,23 +241,30 @@ exit: | |||
227 | kfree(buffer); | 241 | kfree(buffer); |
228 | return retval; | 242 | return retval; |
229 | } | 243 | } |
230 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); | 244 | |
245 | static struct device_attribute dev_lcd_line_attrs[] = { | ||
246 | lcd_line_attr(1), | ||
247 | lcd_line_attr(2), | ||
248 | __ATTR(backlight, S_IWUGO, NULL, set_backlight) | ||
249 | }; | ||
231 | 250 | ||
232 | static void remove_lcd_files(struct interfacekit *kit) | 251 | static void remove_lcd_files(struct interfacekit *kit) |
233 | { | 252 | { |
253 | int i; | ||
254 | |||
234 | if (kit->lcd_files_on) { | 255 | if (kit->lcd_files_on) { |
235 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 256 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
236 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 257 | |
237 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 258 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) |
238 | device_remove_file(&kit->intf->dev, &dev_attr_backlight); | 259 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); |
239 | } | 260 | } |
240 | } | 261 | } |
241 | 262 | ||
242 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 263 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
243 | { | 264 | { |
244 | struct usb_interface *intf = to_usb_interface(dev); | 265 | struct interfacekit *kit = dev_get_drvdata(dev); |
245 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
246 | int enable; | 266 | int enable; |
267 | int i, rc; | ||
247 | 268 | ||
248 | if (kit->ifkit->has_lcd == 0) | 269 | if (kit->ifkit->has_lcd == 0) |
249 | return -ENODEV; | 270 | return -ENODEV; |
@@ -254,9 +275,12 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
254 | if (enable) { | 275 | if (enable) { |
255 | if (!kit->lcd_files_on) { | 276 | if (!kit->lcd_files_on) { |
256 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); | 277 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); |
257 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 278 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) { |
258 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 279 | rc = device_create_file(kit->dev, |
259 | device_create_file(&kit->intf->dev, &dev_attr_backlight); | 280 | &dev_lcd_line_attrs[i]); |
281 | if (rc) | ||
282 | goto out; | ||
283 | } | ||
260 | kit->lcd_files_on = 1; | 284 | kit->lcd_files_on = 1; |
261 | } | 285 | } |
262 | } else { | 286 | } else { |
@@ -267,7 +291,13 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
267 | } | 291 | } |
268 | 292 | ||
269 | return count; | 293 | return count; |
294 | out: | ||
295 | while (i-- > 0) | ||
296 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); | ||
297 | |||
298 | return rc; | ||
270 | } | 299 | } |
300 | |||
271 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); | 301 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); |
272 | 302 | ||
273 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | 303 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) |
@@ -363,44 +393,58 @@ static void do_notify(void *data) | |||
363 | for (i=0; i<kit->ifkit->inputs; i++) { | 393 | for (i=0; i<kit->ifkit->inputs; i++) { |
364 | if (test_and_clear_bit(i, &kit->input_events)) { | 394 | if (test_and_clear_bit(i, &kit->input_events)) { |
365 | sprintf(sysfs_file, "input%d", i + 1); | 395 | sprintf(sysfs_file, "input%d", i + 1); |
366 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 396 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
367 | } | 397 | } |
368 | } | 398 | } |
369 | 399 | ||
370 | for (i=0; i<kit->ifkit->sensors; i++) { | 400 | for (i=0; i<kit->ifkit->sensors; i++) { |
371 | if (test_and_clear_bit(i, &kit->sensor_events)) { | 401 | if (test_and_clear_bit(i, &kit->sensor_events)) { |
372 | sprintf(sysfs_file, "sensor%d", i + 1); | 402 | sprintf(sysfs_file, "sensor%d", i + 1); |
373 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 403 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
374 | } | 404 | } |
375 | } | 405 | } |
376 | } | 406 | } |
377 | 407 | ||
408 | static void do_resubmit(void *data) | ||
409 | { | ||
410 | set_outputs(data); | ||
411 | } | ||
412 | |||
378 | #define show_set_output(value) \ | 413 | #define show_set_output(value) \ |
379 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | 414 | static ssize_t set_output##value(struct device *dev, \ |
380 | size_t count) \ | 415 | struct device_attribute *attr, \ |
416 | const char *buf, size_t count) \ | ||
381 | { \ | 417 | { \ |
382 | struct usb_interface *intf = to_usb_interface(dev); \ | 418 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
383 | struct interfacekit *kit = usb_get_intfdata(intf); \ | 419 | int enable; \ |
384 | int enabled; \ | ||
385 | int retval; \ | 420 | int retval; \ |
386 | \ | 421 | \ |
387 | if (sscanf(buf, "%d", &enabled) < 1) \ | 422 | if (sscanf(buf, "%d", &enable) < 1) \ |
388 | return -EINVAL; \ | 423 | return -EINVAL; \ |
389 | \ | 424 | \ |
390 | 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); \ | ||
391 | \ | 431 | \ |
392 | return retval ? retval : count; \ | 432 | return retval ? retval : count; \ |
393 | } \ | 433 | } \ |
394 | \ | 434 | \ |
395 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 435 | static ssize_t show_output##value(struct device *dev, \ |
436 | struct device_attribute *attr, \ | ||
437 | char *buf) \ | ||
396 | { \ | 438 | { \ |
397 | struct usb_interface *intf = to_usb_interface(dev); \ | 439 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
398 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
399 | \ | 440 | \ |
400 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ | 441 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
401 | } \ | 442 | } |
402 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ | 443 | |
403 | show_output##value, set_output##value); | 444 | #define output_attr(value) \ |
445 | __ATTR(output##value, S_IWUGO | S_IRUGO, \ | ||
446 | show_output##value, set_output##value) | ||
447 | |||
404 | show_set_output(1); | 448 | show_set_output(1); |
405 | show_set_output(2); | 449 | show_set_output(2); |
406 | show_set_output(3); | 450 | show_set_output(3); |
@@ -418,15 +462,24 @@ show_set_output(14); | |||
418 | show_set_output(15); | 462 | show_set_output(15); |
419 | show_set_output(16); | 463 | show_set_output(16); |
420 | 464 | ||
465 | static struct device_attribute dev_output_attrs[] = { | ||
466 | output_attr(1), output_attr(2), output_attr(3), output_attr(4), | ||
467 | output_attr(5), output_attr(6), output_attr(7), output_attr(8), | ||
468 | output_attr(9), output_attr(10), output_attr(11), output_attr(12), | ||
469 | output_attr(13), output_attr(14), output_attr(15), output_attr(16) | ||
470 | }; | ||
471 | |||
421 | #define show_input(value) \ | 472 | #define show_input(value) \ |
422 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 473 | static ssize_t show_input##value(struct device *dev, \ |
474 | struct device_attribute *attr, char *buf) \ | ||
423 | { \ | 475 | { \ |
424 | struct usb_interface *intf = to_usb_interface(dev); \ | 476 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
425 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
426 | \ | 477 | \ |
427 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ | 478 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
428 | } \ | 479 | } |
429 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); | 480 | |
481 | #define input_attr(value) \ | ||
482 | __ATTR(input##value, S_IRUGO, show_input##value, NULL) | ||
430 | 483 | ||
431 | show_input(1); | 484 | show_input(1); |
432 | show_input(2); | 485 | show_input(2); |
@@ -445,15 +498,25 @@ show_input(14); | |||
445 | show_input(15); | 498 | show_input(15); |
446 | show_input(16); | 499 | show_input(16); |
447 | 500 | ||
501 | static struct device_attribute dev_input_attrs[] = { | ||
502 | input_attr(1), input_attr(2), input_attr(3), input_attr(4), | ||
503 | input_attr(5), input_attr(6), input_attr(7), input_attr(8), | ||
504 | input_attr(9), input_attr(10), input_attr(11), input_attr(12), | ||
505 | input_attr(13), input_attr(14), input_attr(15), input_attr(16) | ||
506 | }; | ||
507 | |||
448 | #define show_sensor(value) \ | 508 | #define show_sensor(value) \ |
449 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 509 | static ssize_t show_sensor##value(struct device *dev, \ |
510 | struct device_attribute *attr, \ | ||
511 | char *buf) \ | ||
450 | { \ | 512 | { \ |
451 | struct usb_interface *intf = to_usb_interface(dev); \ | 513 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
452 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
453 | \ | 514 | \ |
454 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ | 515 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
455 | } \ | 516 | } |
456 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); | 517 | |
518 | #define sensor_attr(value) \ | ||
519 | __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL) | ||
457 | 520 | ||
458 | show_sensor(1); | 521 | show_sensor(1); |
459 | show_sensor(2); | 522 | show_sensor(2); |
@@ -464,6 +527,11 @@ show_sensor(6); | |||
464 | show_sensor(7); | 527 | show_sensor(7); |
465 | show_sensor(8); | 528 | show_sensor(8); |
466 | 529 | ||
530 | static struct device_attribute dev_sensor_attrs[] = { | ||
531 | sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4), | ||
532 | sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8) | ||
533 | }; | ||
534 | |||
467 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) | 535 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) |
468 | { | 536 | { |
469 | struct usb_device *dev = interface_to_usbdev(intf); | 537 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -472,6 +540,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
472 | struct interfacekit *kit; | 540 | struct interfacekit *kit; |
473 | struct driver_interfacekit *ifkit; | 541 | struct driver_interfacekit *ifkit; |
474 | int pipe, maxp, rc = -ENOMEM; | 542 | int pipe, maxp, rc = -ENOMEM; |
543 | int bit, value, i; | ||
475 | 544 | ||
476 | ifkit = (struct driver_interfacekit *)id->driver_info; | 545 | ifkit = (struct driver_interfacekit *)id->driver_info; |
477 | if (!ifkit) | 546 | if (!ifkit) |
@@ -494,6 +563,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
494 | if (!kit) | 563 | if (!kit) |
495 | goto out; | 564 | goto out; |
496 | 565 | ||
566 | kit->dev_no = -1; | ||
497 | kit->ifkit = ifkit; | 567 | kit->ifkit = ifkit; |
498 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); | 568 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
499 | if (!kit->data) | 569 | if (!kit->data) |
@@ -506,6 +576,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
506 | kit->udev = usb_get_dev(dev); | 576 | kit->udev = usb_get_dev(dev); |
507 | kit->intf = intf; | 577 | kit->intf = intf; |
508 | 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); | ||
509 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, | 580 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, |
510 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, | 581 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, |
511 | interfacekit_irq, kit, endpoint->bInterval); | 582 | interfacekit_irq, kit, endpoint->bInterval); |
@@ -514,85 +585,80 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
514 | 585 | ||
515 | usb_set_intfdata(intf, kit); | 586 | usb_set_intfdata(intf, kit); |
516 | 587 | ||
588 | do { | ||
589 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
590 | value = test_and_set_bit(bit, &device_no); | ||
591 | } while(value); | ||
592 | kit->dev_no = bit; | ||
593 | |||
594 | kit->dev = device_create(phidget_class, &kit->udev->dev, 0, | ||
595 | "interfacekit%d", kit->dev_no); | ||
596 | if (IS_ERR(kit->dev)) { | ||
597 | rc = PTR_ERR(kit->dev); | ||
598 | kit->dev = NULL; | ||
599 | goto out; | ||
600 | } | ||
601 | dev_set_drvdata(kit->dev, kit); | ||
602 | |||
517 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 603 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
518 | rc = -EIO; | 604 | rc = -EIO; |
519 | goto out; | 605 | goto out; |
520 | } | 606 | } |
521 | 607 | ||
522 | if (ifkit->outputs >= 4) { | 608 | for (i=0; i<ifkit->outputs; i++ ) { |
523 | device_create_file(&intf->dev, &dev_attr_output1); | 609 | rc = device_create_file(kit->dev, &dev_output_attrs[i]); |
524 | device_create_file(&intf->dev, &dev_attr_output2); | 610 | if (rc) |
525 | device_create_file(&intf->dev, &dev_attr_output3); | 611 | goto out2; |
526 | device_create_file(&intf->dev, &dev_attr_output4); | ||
527 | } | ||
528 | if (ifkit->outputs >= 8) { | ||
529 | device_create_file(&intf->dev, &dev_attr_output5); | ||
530 | device_create_file(&intf->dev, &dev_attr_output6); | ||
531 | device_create_file(&intf->dev, &dev_attr_output7); | ||
532 | device_create_file(&intf->dev, &dev_attr_output8); | ||
533 | } | ||
534 | if (ifkit->outputs == 16) { | ||
535 | device_create_file(&intf->dev, &dev_attr_output9); | ||
536 | device_create_file(&intf->dev, &dev_attr_output10); | ||
537 | device_create_file(&intf->dev, &dev_attr_output11); | ||
538 | device_create_file(&intf->dev, &dev_attr_output12); | ||
539 | device_create_file(&intf->dev, &dev_attr_output13); | ||
540 | device_create_file(&intf->dev, &dev_attr_output14); | ||
541 | device_create_file(&intf->dev, &dev_attr_output15); | ||
542 | device_create_file(&intf->dev, &dev_attr_output16); | ||
543 | } | 612 | } |
544 | 613 | ||
545 | if (ifkit->inputs >= 4) { | 614 | for (i=0; i<ifkit->inputs; i++ ) { |
546 | device_create_file(&intf->dev, &dev_attr_input1); | 615 | rc = device_create_file(kit->dev, &dev_input_attrs[i]); |
547 | device_create_file(&intf->dev, &dev_attr_input2); | 616 | if (rc) |
548 | device_create_file(&intf->dev, &dev_attr_input3); | 617 | goto out3; |
549 | device_create_file(&intf->dev, &dev_attr_input4); | ||
550 | } | ||
551 | if (ifkit->inputs >= 8) { | ||
552 | device_create_file(&intf->dev, &dev_attr_input5); | ||
553 | device_create_file(&intf->dev, &dev_attr_input6); | ||
554 | device_create_file(&intf->dev, &dev_attr_input7); | ||
555 | device_create_file(&intf->dev, &dev_attr_input8); | ||
556 | } | ||
557 | if (ifkit->inputs == 16) { | ||
558 | device_create_file(&intf->dev, &dev_attr_input9); | ||
559 | device_create_file(&intf->dev, &dev_attr_input10); | ||
560 | device_create_file(&intf->dev, &dev_attr_input11); | ||
561 | device_create_file(&intf->dev, &dev_attr_input12); | ||
562 | device_create_file(&intf->dev, &dev_attr_input13); | ||
563 | device_create_file(&intf->dev, &dev_attr_input14); | ||
564 | device_create_file(&intf->dev, &dev_attr_input15); | ||
565 | device_create_file(&intf->dev, &dev_attr_input16); | ||
566 | } | 618 | } |
567 | 619 | ||
568 | if (ifkit->sensors >= 4) { | 620 | for (i=0; i<ifkit->sensors; i++ ) { |
569 | device_create_file(&intf->dev, &dev_attr_sensor1); | 621 | rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); |
570 | device_create_file(&intf->dev, &dev_attr_sensor2); | 622 | if (rc) |
571 | device_create_file(&intf->dev, &dev_attr_sensor3); | 623 | goto out4; |
572 | device_create_file(&intf->dev, &dev_attr_sensor4); | ||
573 | } | 624 | } |
574 | if (ifkit->sensors >= 7) { | ||
575 | device_create_file(&intf->dev, &dev_attr_sensor5); | ||
576 | device_create_file(&intf->dev, &dev_attr_sensor6); | ||
577 | device_create_file(&intf->dev, &dev_attr_sensor7); | ||
578 | } | ||
579 | if (ifkit->sensors == 8) | ||
580 | device_create_file(&intf->dev, &dev_attr_sensor8); | ||
581 | 625 | ||
582 | if (ifkit->has_lcd) | 626 | if (ifkit->has_lcd) { |
583 | device_create_file(&intf->dev, &dev_attr_lcd); | 627 | rc = device_create_file(kit->dev, &dev_attr_lcd); |
628 | if (rc) | ||
629 | goto out4; | ||
630 | |||
631 | } | ||
584 | 632 | ||
585 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", | 633 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", |
586 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 634 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
587 | 635 | ||
588 | return 0; | 636 | return 0; |
589 | 637 | ||
638 | out4: | ||
639 | while (i-- > 0) | ||
640 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); | ||
641 | |||
642 | i = ifkit->inputs; | ||
643 | out3: | ||
644 | while (i-- > 0) | ||
645 | device_remove_file(kit->dev, &dev_input_attrs[i]); | ||
646 | |||
647 | i = ifkit->outputs; | ||
648 | out2: | ||
649 | while (i-- > 0) | ||
650 | device_remove_file(kit->dev, &dev_output_attrs[i]); | ||
590 | out: | 651 | out: |
591 | if (kit) { | 652 | if (kit) { |
592 | if (kit->irq) | 653 | if (kit->irq) |
593 | usb_free_urb(kit->irq); | 654 | usb_free_urb(kit->irq); |
594 | if (kit->data) | 655 | if (kit->data) |
595 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); | 656 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); |
657 | if (kit->dev) | ||
658 | device_unregister(kit->dev); | ||
659 | if (kit->dev_no >= 0) | ||
660 | clear_bit(kit->dev_no, &device_no); | ||
661 | |||
596 | kfree(kit); | 662 | kfree(kit); |
597 | } | 663 | } |
598 | 664 | ||
@@ -602,6 +668,7 @@ out: | |||
602 | static void interfacekit_disconnect(struct usb_interface *interface) | 668 | static void interfacekit_disconnect(struct usb_interface *interface) |
603 | { | 669 | { |
604 | struct interfacekit *kit; | 670 | struct interfacekit *kit; |
671 | int i; | ||
605 | 672 | ||
606 | kit = usb_get_intfdata(interface); | 673 | kit = usb_get_intfdata(interface); |
607 | usb_set_intfdata(interface, NULL); | 674 | usb_set_intfdata(interface, NULL); |
@@ -613,74 +680,30 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
613 | 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); |
614 | 681 | ||
615 | cancel_delayed_work(&kit->do_notify); | 682 | cancel_delayed_work(&kit->do_notify); |
683 | cancel_delayed_work(&kit->do_resubmit); | ||
616 | 684 | ||
617 | if (kit->ifkit->outputs >= 4) { | 685 | for (i=0; i<kit->ifkit->outputs; i++) |
618 | device_remove_file(&interface->dev, &dev_attr_output1); | 686 | device_remove_file(kit->dev, &dev_output_attrs[i]); |
619 | device_remove_file(&interface->dev, &dev_attr_output2); | ||
620 | device_remove_file(&interface->dev, &dev_attr_output3); | ||
621 | device_remove_file(&interface->dev, &dev_attr_output4); | ||
622 | } | ||
623 | if (kit->ifkit->outputs >= 8) { | ||
624 | device_remove_file(&interface->dev, &dev_attr_output5); | ||
625 | device_remove_file(&interface->dev, &dev_attr_output6); | ||
626 | device_remove_file(&interface->dev, &dev_attr_output7); | ||
627 | device_remove_file(&interface->dev, &dev_attr_output8); | ||
628 | } | ||
629 | if (kit->ifkit->outputs == 16) { | ||
630 | device_remove_file(&interface->dev, &dev_attr_output9); | ||
631 | device_remove_file(&interface->dev, &dev_attr_output10); | ||
632 | device_remove_file(&interface->dev, &dev_attr_output11); | ||
633 | device_remove_file(&interface->dev, &dev_attr_output12); | ||
634 | device_remove_file(&interface->dev, &dev_attr_output13); | ||
635 | device_remove_file(&interface->dev, &dev_attr_output14); | ||
636 | device_remove_file(&interface->dev, &dev_attr_output15); | ||
637 | device_remove_file(&interface->dev, &dev_attr_output16); | ||
638 | } | ||
639 | 687 | ||
640 | if (kit->ifkit->inputs >= 4) { | 688 | for (i=0; i<kit->ifkit->inputs; i++) |
641 | device_remove_file(&interface->dev, &dev_attr_input1); | 689 | device_remove_file(kit->dev, &dev_input_attrs[i]); |
642 | device_remove_file(&interface->dev, &dev_attr_input2); | ||
643 | device_remove_file(&interface->dev, &dev_attr_input3); | ||
644 | device_remove_file(&interface->dev, &dev_attr_input4); | ||
645 | } | ||
646 | if (kit->ifkit->inputs >= 8) { | ||
647 | device_remove_file(&interface->dev, &dev_attr_input5); | ||
648 | device_remove_file(&interface->dev, &dev_attr_input6); | ||
649 | device_remove_file(&interface->dev, &dev_attr_input7); | ||
650 | device_remove_file(&interface->dev, &dev_attr_input8); | ||
651 | } | ||
652 | if (kit->ifkit->inputs == 16) { | ||
653 | device_remove_file(&interface->dev, &dev_attr_input9); | ||
654 | device_remove_file(&interface->dev, &dev_attr_input10); | ||
655 | device_remove_file(&interface->dev, &dev_attr_input11); | ||
656 | device_remove_file(&interface->dev, &dev_attr_input12); | ||
657 | device_remove_file(&interface->dev, &dev_attr_input13); | ||
658 | device_remove_file(&interface->dev, &dev_attr_input14); | ||
659 | device_remove_file(&interface->dev, &dev_attr_input15); | ||
660 | device_remove_file(&interface->dev, &dev_attr_input16); | ||
661 | } | ||
662 | 690 | ||
663 | if (kit->ifkit->sensors >= 4) { | 691 | for (i=0; i<kit->ifkit->sensors; i++) |
664 | device_remove_file(&interface->dev, &dev_attr_sensor1); | 692 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); |
665 | device_remove_file(&interface->dev, &dev_attr_sensor2); | 693 | |
666 | device_remove_file(&interface->dev, &dev_attr_sensor3); | 694 | if (kit->ifkit->has_lcd) { |
667 | device_remove_file(&interface->dev, &dev_attr_sensor4); | 695 | device_remove_file(kit->dev, &dev_attr_lcd); |
668 | } | 696 | remove_lcd_files(kit); |
669 | if (kit->ifkit->sensors >= 7) { | ||
670 | device_remove_file(&interface->dev, &dev_attr_sensor5); | ||
671 | device_remove_file(&interface->dev, &dev_attr_sensor6); | ||
672 | device_remove_file(&interface->dev, &dev_attr_sensor7); | ||
673 | } | 697 | } |
674 | if (kit->ifkit->sensors == 8) | ||
675 | device_remove_file(&interface->dev, &dev_attr_sensor8); | ||
676 | 698 | ||
677 | if (kit->ifkit->has_lcd) | 699 | device_unregister(kit->dev); |
678 | device_remove_file(&interface->dev, &dev_attr_lcd); | ||
679 | 700 | ||
680 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", | 701 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
681 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); | 702 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
682 | 703 | ||
683 | usb_put_dev(kit->udev); | 704 | usb_put_dev(kit->udev); |
705 | clear_bit(kit->dev_no, &device_no); | ||
706 | |||
684 | kfree(kit); | 707 | kfree(kit); |
685 | } | 708 | } |
686 | 709 | ||