diff options
-rw-r--r-- | drivers/usb/misc/Kconfig | 13 | ||||
-rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/misc/phidget.c | 43 | ||||
-rw-r--r-- | drivers/usb/misc/phidget.h | 12 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetkit.c | 258 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetmotorcontrol.c | 126 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetservo.c | 71 |
7 files changed, 334 insertions, 190 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 8affc137d618..20539cf9394b 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
@@ -115,9 +115,16 @@ config USB_CYTHERM | |||
115 | To compile this driver as a module, choose M here: the | 115 | To compile this driver as a module, choose M here: the |
116 | module will be called cytherm. | 116 | module will be called cytherm. |
117 | 117 | ||
118 | config USB_PHIDGET | ||
119 | tristate "USB Phidgets drivers" | ||
120 | depends on USB | ||
121 | help | ||
122 | Say Y here to enable the various drivers for devices from | ||
123 | Phidgets inc. | ||
124 | |||
118 | config USB_PHIDGETKIT | 125 | config USB_PHIDGETKIT |
119 | tristate "USB PhidgetInterfaceKit support" | 126 | tristate "USB PhidgetInterfaceKit support" |
120 | depends on USB | 127 | depends on USB_PHIDGET |
121 | help | 128 | help |
122 | Say Y here if you want to connect a PhidgetInterfaceKit USB device | 129 | Say Y here if you want to connect a PhidgetInterfaceKit USB device |
123 | from Phidgets Inc. | 130 | from Phidgets Inc. |
@@ -127,7 +134,7 @@ config USB_PHIDGETKIT | |||
127 | 134 | ||
128 | config USB_PHIDGETMOTORCONTROL | 135 | config USB_PHIDGETMOTORCONTROL |
129 | tristate "USB PhidgetMotorControl support" | 136 | tristate "USB PhidgetMotorControl support" |
130 | depends on USB | 137 | depends on USB_PHIDGET |
131 | help | 138 | help |
132 | Say Y here if you want to connect a PhidgetMotorControl USB device | 139 | Say Y here if you want to connect a PhidgetMotorControl USB device |
133 | from Phidgets Inc. | 140 | from Phidgets Inc. |
@@ -137,7 +144,7 @@ config USB_PHIDGETMOTORCONTROL | |||
137 | 144 | ||
138 | config USB_PHIDGETSERVO | 145 | config USB_PHIDGETSERVO |
139 | tristate "USB PhidgetServo support" | 146 | tristate "USB PhidgetServo support" |
140 | depends on USB | 147 | depends on USB_PHIDGET |
141 | help | 148 | help |
142 | Say Y here if you want to connect an 1 or 4 Motor PhidgetServo | 149 | Say Y here if you want to connect an 1 or 4 Motor PhidgetServo |
143 | servo controller version 2.0 or 3.0. | 150 | servo controller version 2.0 or 3.0. |
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 5f329176451a..d12a84a1c0a4 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_LCD) += usblcd.o | |||
13 | obj-$(CONFIG_USB_LD) += ldusb.o | 13 | obj-$(CONFIG_USB_LD) += ldusb.o |
14 | obj-$(CONFIG_USB_LED) += usbled.o | 14 | obj-$(CONFIG_USB_LED) += usbled.o |
15 | obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o | 15 | obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o |
16 | obj-$(CONFIG_USB_PHIDGET) += phidget.o | ||
16 | obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o | 17 | obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o |
17 | obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o | 18 | obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o |
18 | obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o | 19 | obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o |
diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c new file mode 100644 index 000000000000..735ed33f4f7f --- /dev/null +++ b/drivers/usb/misc/phidget.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * USB Phidgets class | ||
3 | * | ||
4 | * Copyright (C) 2006 Sean Young <sean@mess.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/device.h> | ||
17 | |||
18 | struct class *phidget_class; | ||
19 | |||
20 | static int __init init_phidget(void) | ||
21 | { | ||
22 | phidget_class = class_create(THIS_MODULE, "phidget"); | ||
23 | |||
24 | if (IS_ERR(phidget_class)) | ||
25 | return PTR_ERR(phidget_class); | ||
26 | |||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | static void __exit cleanup_phidget(void) | ||
31 | { | ||
32 | class_destroy(phidget_class); | ||
33 | } | ||
34 | |||
35 | EXPORT_SYMBOL_GPL(phidget_class); | ||
36 | |||
37 | module_init(init_phidget); | ||
38 | module_exit(cleanup_phidget); | ||
39 | |||
40 | MODULE_LICENSE("GPL"); | ||
41 | MODULE_AUTHOR("Sean Young <sean@mess.org>"); | ||
42 | MODULE_DESCRIPTION("Container module for phidget class"); | ||
43 | |||
diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h new file mode 100644 index 000000000000..c4011907d431 --- /dev/null +++ b/drivers/usb/misc/phidget.h | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * USB Phidgets class | ||
3 | * | ||
4 | * Copyright (C) 2006 Sean Young <sean@mess.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | extern struct class *phidget_class; | ||
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index bfbbbfbb92bc..3f508957def9 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | 22 | ||
23 | #include "phidget.h" | ||
24 | |||
23 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 25 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
24 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" | 26 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" |
25 | 27 | ||
@@ -57,11 +59,15 @@ ifkit(8, 8, 4, 0); | |||
57 | ifkit(0, 8, 8, 1); | 59 | ifkit(0, 8, 8, 1); |
58 | ifkit(0, 16, 16, 0); | 60 | ifkit(0, 16, 16, 0); |
59 | 61 | ||
62 | static unsigned long device_no; | ||
63 | |||
60 | struct interfacekit { | 64 | struct interfacekit { |
61 | struct usb_device *udev; | 65 | struct usb_device *udev; |
62 | struct usb_interface *intf; | 66 | struct usb_interface *intf; |
63 | struct driver_interfacekit *ifkit; | 67 | struct driver_interfacekit *ifkit; |
68 | struct device *dev; | ||
64 | unsigned long outputs; | 69 | unsigned long outputs; |
70 | int dev_no; | ||
65 | u8 inputs[MAX_INTERFACES]; | 71 | u8 inputs[MAX_INTERFACES]; |
66 | u16 sensors[MAX_INTERFACES]; | 72 | u16 sensors[MAX_INTERFACES]; |
67 | u8 lcd_files_on; | 73 | u8 lcd_files_on; |
@@ -180,21 +186,21 @@ exit: | |||
180 | } | 186 | } |
181 | 187 | ||
182 | #define set_lcd_line(number) \ | 188 | #define set_lcd_line(number) \ |
183 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 189 | static ssize_t lcd_line_##number(struct device *dev, \ |
184 | { \ | 190 | struct device_attribute *attr, \ |
185 | struct usb_interface *intf = to_usb_interface(dev); \ | 191 | const char *buf, size_t count) \ |
186 | struct interfacekit *kit = usb_get_intfdata(intf); \ | 192 | { \ |
187 | change_string(kit, buf, number - 1); \ | 193 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
188 | return count; \ | 194 | change_string(kit, buf, number - 1); \ |
189 | } \ | 195 | return count; \ |
196 | } \ | ||
190 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); | 197 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); |
191 | set_lcd_line(1); | 198 | set_lcd_line(1); |
192 | set_lcd_line(2); | 199 | set_lcd_line(2); |
193 | 200 | ||
194 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 201 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
195 | { | 202 | { |
196 | struct usb_interface *intf = to_usb_interface(dev); | 203 | struct interfacekit *kit = dev_get_drvdata(dev); |
197 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
198 | int enabled; | 204 | int enabled; |
199 | unsigned char *buffer; | 205 | unsigned char *buffer; |
200 | int retval = -ENOMEM; | 206 | int retval = -ENOMEM; |
@@ -232,16 +238,15 @@ static void remove_lcd_files(struct interfacekit *kit) | |||
232 | { | 238 | { |
233 | if (kit->lcd_files_on) { | 239 | if (kit->lcd_files_on) { |
234 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 240 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
235 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 241 | device_remove_file(kit->dev, &dev_attr_lcd_line_1); |
236 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 242 | device_remove_file(kit->dev, &dev_attr_lcd_line_2); |
237 | device_remove_file(&kit->intf->dev, &dev_attr_backlight); | 243 | device_remove_file(kit->dev, &dev_attr_backlight); |
238 | } | 244 | } |
239 | } | 245 | } |
240 | 246 | ||
241 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 247 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
242 | { | 248 | { |
243 | struct usb_interface *intf = to_usb_interface(dev); | 249 | struct interfacekit *kit = dev_get_drvdata(dev); |
244 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
245 | int enable; | 250 | int enable; |
246 | 251 | ||
247 | if (kit->ifkit->has_lcd == 0) | 252 | if (kit->ifkit->has_lcd == 0) |
@@ -253,9 +258,9 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
253 | if (enable) { | 258 | if (enable) { |
254 | if (!kit->lcd_files_on) { | 259 | if (!kit->lcd_files_on) { |
255 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); | 260 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); |
256 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 261 | device_create_file(kit->dev, &dev_attr_lcd_line_1); |
257 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 262 | device_create_file(kit->dev, &dev_attr_lcd_line_2); |
258 | device_create_file(&kit->intf->dev, &dev_attr_backlight); | 263 | device_create_file(kit->dev, &dev_attr_backlight); |
259 | kit->lcd_files_on = 1; | 264 | kit->lcd_files_on = 1; |
260 | } | 265 | } |
261 | } else { | 266 | } else { |
@@ -362,24 +367,24 @@ static void do_notify(void *data) | |||
362 | for (i=0; i<kit->ifkit->inputs; i++) { | 367 | for (i=0; i<kit->ifkit->inputs; i++) { |
363 | if (test_and_clear_bit(i, &kit->input_events)) { | 368 | if (test_and_clear_bit(i, &kit->input_events)) { |
364 | sprintf(sysfs_file, "input%d", i + 1); | 369 | sprintf(sysfs_file, "input%d", i + 1); |
365 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 370 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
366 | } | 371 | } |
367 | } | 372 | } |
368 | 373 | ||
369 | for (i=0; i<kit->ifkit->sensors; i++) { | 374 | for (i=0; i<kit->ifkit->sensors; i++) { |
370 | if (test_and_clear_bit(i, &kit->sensor_events)) { | 375 | if (test_and_clear_bit(i, &kit->sensor_events)) { |
371 | sprintf(sysfs_file, "sensor%d", i + 1); | 376 | sprintf(sysfs_file, "sensor%d", i + 1); |
372 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 377 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
373 | } | 378 | } |
374 | } | 379 | } |
375 | } | 380 | } |
376 | 381 | ||
377 | #define show_set_output(value) \ | 382 | #define show_set_output(value) \ |
378 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | 383 | static ssize_t set_output##value(struct device *dev, \ |
379 | size_t count) \ | 384 | struct device_attribute *attr, \ |
385 | const char *buf, size_t count) \ | ||
380 | { \ | 386 | { \ |
381 | struct usb_interface *intf = to_usb_interface(dev); \ | 387 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
382 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
383 | int enabled; \ | 388 | int enabled; \ |
384 | int retval; \ | 389 | int retval; \ |
385 | \ | 390 | \ |
@@ -391,10 +396,11 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at | |||
391 | return retval ? retval : count; \ | 396 | return retval ? retval : count; \ |
392 | } \ | 397 | } \ |
393 | \ | 398 | \ |
394 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 399 | static ssize_t show_output##value(struct device *dev, \ |
400 | struct device_attribute *attr, \ | ||
401 | char *buf) \ | ||
395 | { \ | 402 | { \ |
396 | struct usb_interface *intf = to_usb_interface(dev); \ | 403 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
397 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
398 | \ | 404 | \ |
399 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ | 405 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
400 | } \ | 406 | } \ |
@@ -420,8 +426,7 @@ show_set_output(16); | |||
420 | #define show_input(value) \ | 426 | #define show_input(value) \ |
421 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 427 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
422 | { \ | 428 | { \ |
423 | struct usb_interface *intf = to_usb_interface(dev); \ | 429 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
424 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
425 | \ | 430 | \ |
426 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ | 431 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
427 | } \ | 432 | } \ |
@@ -445,10 +450,11 @@ show_input(15); | |||
445 | show_input(16); | 450 | show_input(16); |
446 | 451 | ||
447 | #define show_sensor(value) \ | 452 | #define show_sensor(value) \ |
448 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 453 | static ssize_t show_sensor##value(struct device *dev, \ |
454 | struct device_attribute *attr, \ | ||
455 | char *buf) \ | ||
449 | { \ | 456 | { \ |
450 | struct usb_interface *intf = to_usb_interface(dev); \ | 457 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
451 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
452 | \ | 458 | \ |
453 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ | 459 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
454 | } \ | 460 | } \ |
@@ -471,6 +477,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
471 | struct interfacekit *kit; | 477 | struct interfacekit *kit; |
472 | struct driver_interfacekit *ifkit; | 478 | struct driver_interfacekit *ifkit; |
473 | int pipe, maxp, rc = -ENOMEM; | 479 | int pipe, maxp, rc = -ENOMEM; |
480 | int bit, value; | ||
474 | 481 | ||
475 | ifkit = (struct driver_interfacekit *)id->driver_info; | 482 | ifkit = (struct driver_interfacekit *)id->driver_info; |
476 | if (!ifkit) | 483 | if (!ifkit) |
@@ -493,6 +500,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
493 | if (!kit) | 500 | if (!kit) |
494 | goto out; | 501 | goto out; |
495 | 502 | ||
503 | kit->dev_no = -1; | ||
496 | kit->ifkit = ifkit; | 504 | kit->ifkit = ifkit; |
497 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); | 505 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
498 | if (!kit->data) | 506 | if (!kit->data) |
@@ -513,73 +521,88 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
513 | 521 | ||
514 | usb_set_intfdata(intf, kit); | 522 | usb_set_intfdata(intf, kit); |
515 | 523 | ||
524 | do { | ||
525 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
526 | value = test_and_set_bit(bit, &device_no); | ||
527 | } while(value); | ||
528 | kit->dev_no = bit; | ||
529 | |||
530 | kit->dev = device_create(phidget_class, &kit->udev->dev, 0, | ||
531 | "interfacekit%d", kit->dev_no); | ||
532 | if (IS_ERR(kit->dev)) { | ||
533 | rc = PTR_ERR(kit->dev); | ||
534 | kit->dev = NULL; | ||
535 | goto out; | ||
536 | } | ||
537 | dev_set_drvdata(kit->dev, kit); | ||
538 | |||
516 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 539 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
517 | rc = -EIO; | 540 | rc = -EIO; |
518 | goto out; | 541 | goto out; |
519 | } | 542 | } |
520 | 543 | ||
521 | if (ifkit->outputs >= 4) { | 544 | if (ifkit->outputs >= 4) { |
522 | device_create_file(&intf->dev, &dev_attr_output1); | 545 | device_create_file(kit->dev, &dev_attr_output1); |
523 | device_create_file(&intf->dev, &dev_attr_output2); | 546 | device_create_file(kit->dev, &dev_attr_output2); |
524 | device_create_file(&intf->dev, &dev_attr_output3); | 547 | device_create_file(kit->dev, &dev_attr_output3); |
525 | device_create_file(&intf->dev, &dev_attr_output4); | 548 | device_create_file(kit->dev, &dev_attr_output4); |
526 | } | 549 | } |
527 | if (ifkit->outputs >= 8) { | 550 | if (ifkit->outputs >= 8) { |
528 | device_create_file(&intf->dev, &dev_attr_output5); | 551 | device_create_file(kit->dev, &dev_attr_output5); |
529 | device_create_file(&intf->dev, &dev_attr_output6); | 552 | device_create_file(kit->dev, &dev_attr_output6); |
530 | device_create_file(&intf->dev, &dev_attr_output7); | 553 | device_create_file(kit->dev, &dev_attr_output7); |
531 | device_create_file(&intf->dev, &dev_attr_output8); | 554 | device_create_file(kit->dev, &dev_attr_output8); |
532 | } | 555 | } |
533 | if (ifkit->outputs == 16) { | 556 | if (ifkit->outputs == 16) { |
534 | device_create_file(&intf->dev, &dev_attr_output9); | 557 | device_create_file(kit->dev, &dev_attr_output9); |
535 | device_create_file(&intf->dev, &dev_attr_output10); | 558 | device_create_file(kit->dev, &dev_attr_output10); |
536 | device_create_file(&intf->dev, &dev_attr_output11); | 559 | device_create_file(kit->dev, &dev_attr_output11); |
537 | device_create_file(&intf->dev, &dev_attr_output12); | 560 | device_create_file(kit->dev, &dev_attr_output12); |
538 | device_create_file(&intf->dev, &dev_attr_output13); | 561 | device_create_file(kit->dev, &dev_attr_output13); |
539 | device_create_file(&intf->dev, &dev_attr_output14); | 562 | device_create_file(kit->dev, &dev_attr_output14); |
540 | device_create_file(&intf->dev, &dev_attr_output15); | 563 | device_create_file(kit->dev, &dev_attr_output15); |
541 | device_create_file(&intf->dev, &dev_attr_output16); | 564 | device_create_file(kit->dev, &dev_attr_output16); |
542 | } | 565 | } |
543 | 566 | ||
544 | if (ifkit->inputs >= 4) { | 567 | if (ifkit->inputs >= 4) { |
545 | device_create_file(&intf->dev, &dev_attr_input1); | 568 | device_create_file(kit->dev, &dev_attr_input1); |
546 | device_create_file(&intf->dev, &dev_attr_input2); | 569 | device_create_file(kit->dev, &dev_attr_input2); |
547 | device_create_file(&intf->dev, &dev_attr_input3); | 570 | device_create_file(kit->dev, &dev_attr_input3); |
548 | device_create_file(&intf->dev, &dev_attr_input4); | 571 | device_create_file(kit->dev, &dev_attr_input4); |
549 | } | 572 | } |
550 | if (ifkit->inputs >= 8) { | 573 | if (ifkit->inputs >= 8) { |
551 | device_create_file(&intf->dev, &dev_attr_input5); | 574 | device_create_file(kit->dev, &dev_attr_input5); |
552 | device_create_file(&intf->dev, &dev_attr_input6); | 575 | device_create_file(kit->dev, &dev_attr_input6); |
553 | device_create_file(&intf->dev, &dev_attr_input7); | 576 | device_create_file(kit->dev, &dev_attr_input7); |
554 | device_create_file(&intf->dev, &dev_attr_input8); | 577 | device_create_file(kit->dev, &dev_attr_input8); |
555 | } | 578 | } |
556 | if (ifkit->inputs == 16) { | 579 | if (ifkit->inputs == 16) { |
557 | device_create_file(&intf->dev, &dev_attr_input9); | 580 | device_create_file(kit->dev, &dev_attr_input9); |
558 | device_create_file(&intf->dev, &dev_attr_input10); | 581 | device_create_file(kit->dev, &dev_attr_input10); |
559 | device_create_file(&intf->dev, &dev_attr_input11); | 582 | device_create_file(kit->dev, &dev_attr_input11); |
560 | device_create_file(&intf->dev, &dev_attr_input12); | 583 | device_create_file(kit->dev, &dev_attr_input12); |
561 | device_create_file(&intf->dev, &dev_attr_input13); | 584 | device_create_file(kit->dev, &dev_attr_input13); |
562 | device_create_file(&intf->dev, &dev_attr_input14); | 585 | device_create_file(kit->dev, &dev_attr_input14); |
563 | device_create_file(&intf->dev, &dev_attr_input15); | 586 | device_create_file(kit->dev, &dev_attr_input15); |
564 | device_create_file(&intf->dev, &dev_attr_input16); | 587 | device_create_file(kit->dev, &dev_attr_input16); |
565 | } | 588 | } |
566 | 589 | ||
567 | if (ifkit->sensors >= 4) { | 590 | if (ifkit->sensors >= 4) { |
568 | device_create_file(&intf->dev, &dev_attr_sensor1); | 591 | device_create_file(kit->dev, &dev_attr_sensor1); |
569 | device_create_file(&intf->dev, &dev_attr_sensor2); | 592 | device_create_file(kit->dev, &dev_attr_sensor2); |
570 | device_create_file(&intf->dev, &dev_attr_sensor3); | 593 | device_create_file(kit->dev, &dev_attr_sensor3); |
571 | device_create_file(&intf->dev, &dev_attr_sensor4); | 594 | device_create_file(kit->dev, &dev_attr_sensor4); |
572 | } | 595 | } |
573 | if (ifkit->sensors >= 7) { | 596 | if (ifkit->sensors >= 7) { |
574 | device_create_file(&intf->dev, &dev_attr_sensor5); | 597 | device_create_file(kit->dev, &dev_attr_sensor5); |
575 | device_create_file(&intf->dev, &dev_attr_sensor6); | 598 | device_create_file(kit->dev, &dev_attr_sensor6); |
576 | device_create_file(&intf->dev, &dev_attr_sensor7); | 599 | device_create_file(kit->dev, &dev_attr_sensor7); |
577 | } | 600 | } |
578 | if (ifkit->sensors == 8) | 601 | if (ifkit->sensors == 8) |
579 | device_create_file(&intf->dev, &dev_attr_sensor8); | 602 | device_create_file(kit->dev, &dev_attr_sensor8); |
580 | 603 | ||
581 | if (ifkit->has_lcd) | 604 | if (ifkit->has_lcd) |
582 | device_create_file(&intf->dev, &dev_attr_lcd); | 605 | device_create_file(kit->dev, &dev_attr_lcd); |
583 | 606 | ||
584 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", | 607 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", |
585 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 608 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
@@ -592,6 +615,11 @@ out: | |||
592 | usb_free_urb(kit->irq); | 615 | usb_free_urb(kit->irq); |
593 | if (kit->data) | 616 | if (kit->data) |
594 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); | 617 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); |
618 | if (kit->dev) | ||
619 | device_unregister(kit->dev); | ||
620 | if (kit->dev_no >= 0) | ||
621 | clear_bit(kit->dev_no, &device_no); | ||
622 | |||
595 | kfree(kit); | 623 | kfree(kit); |
596 | } | 624 | } |
597 | 625 | ||
@@ -614,72 +642,76 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
614 | cancel_delayed_work(&kit->do_notify); | 642 | cancel_delayed_work(&kit->do_notify); |
615 | 643 | ||
616 | if (kit->ifkit->outputs >= 4) { | 644 | if (kit->ifkit->outputs >= 4) { |
617 | device_remove_file(&interface->dev, &dev_attr_output1); | 645 | device_remove_file(kit->dev, &dev_attr_output1); |
618 | device_remove_file(&interface->dev, &dev_attr_output2); | 646 | device_remove_file(kit->dev, &dev_attr_output2); |
619 | device_remove_file(&interface->dev, &dev_attr_output3); | 647 | device_remove_file(kit->dev, &dev_attr_output3); |
620 | device_remove_file(&interface->dev, &dev_attr_output4); | 648 | device_remove_file(kit->dev, &dev_attr_output4); |
621 | } | 649 | } |
622 | if (kit->ifkit->outputs >= 8) { | 650 | if (kit->ifkit->outputs >= 8) { |
623 | device_remove_file(&interface->dev, &dev_attr_output5); | 651 | device_remove_file(kit->dev, &dev_attr_output5); |
624 | device_remove_file(&interface->dev, &dev_attr_output6); | 652 | device_remove_file(kit->dev, &dev_attr_output6); |
625 | device_remove_file(&interface->dev, &dev_attr_output7); | 653 | device_remove_file(kit->dev, &dev_attr_output7); |
626 | device_remove_file(&interface->dev, &dev_attr_output8); | 654 | device_remove_file(kit->dev, &dev_attr_output8); |
627 | } | 655 | } |
628 | if (kit->ifkit->outputs == 16) { | 656 | if (kit->ifkit->outputs == 16) { |
629 | device_remove_file(&interface->dev, &dev_attr_output9); | 657 | device_remove_file(kit->dev, &dev_attr_output9); |
630 | device_remove_file(&interface->dev, &dev_attr_output10); | 658 | device_remove_file(kit->dev, &dev_attr_output10); |
631 | device_remove_file(&interface->dev, &dev_attr_output11); | 659 | device_remove_file(kit->dev, &dev_attr_output11); |
632 | device_remove_file(&interface->dev, &dev_attr_output12); | 660 | device_remove_file(kit->dev, &dev_attr_output12); |
633 | device_remove_file(&interface->dev, &dev_attr_output13); | 661 | device_remove_file(kit->dev, &dev_attr_output13); |
634 | device_remove_file(&interface->dev, &dev_attr_output14); | 662 | device_remove_file(kit->dev, &dev_attr_output14); |
635 | device_remove_file(&interface->dev, &dev_attr_output15); | 663 | device_remove_file(kit->dev, &dev_attr_output15); |
636 | device_remove_file(&interface->dev, &dev_attr_output16); | 664 | device_remove_file(kit->dev, &dev_attr_output16); |
637 | } | 665 | } |
638 | 666 | ||
639 | if (kit->ifkit->inputs >= 4) { | 667 | if (kit->ifkit->inputs >= 4) { |
640 | device_remove_file(&interface->dev, &dev_attr_input1); | 668 | device_remove_file(kit->dev, &dev_attr_input1); |
641 | device_remove_file(&interface->dev, &dev_attr_input2); | 669 | device_remove_file(kit->dev, &dev_attr_input2); |
642 | device_remove_file(&interface->dev, &dev_attr_input3); | 670 | device_remove_file(kit->dev, &dev_attr_input3); |
643 | device_remove_file(&interface->dev, &dev_attr_input4); | 671 | device_remove_file(kit->dev, &dev_attr_input4); |
644 | } | 672 | } |
645 | if (kit->ifkit->inputs >= 8) { | 673 | if (kit->ifkit->inputs >= 8) { |
646 | device_remove_file(&interface->dev, &dev_attr_input5); | 674 | device_remove_file(kit->dev, &dev_attr_input5); |
647 | device_remove_file(&interface->dev, &dev_attr_input6); | 675 | device_remove_file(kit->dev, &dev_attr_input6); |
648 | device_remove_file(&interface->dev, &dev_attr_input7); | 676 | device_remove_file(kit->dev, &dev_attr_input7); |
649 | device_remove_file(&interface->dev, &dev_attr_input8); | 677 | device_remove_file(kit->dev, &dev_attr_input8); |
650 | } | 678 | } |
651 | if (kit->ifkit->inputs == 16) { | 679 | if (kit->ifkit->inputs == 16) { |
652 | device_remove_file(&interface->dev, &dev_attr_input9); | 680 | device_remove_file(kit->dev, &dev_attr_input9); |
653 | device_remove_file(&interface->dev, &dev_attr_input10); | 681 | device_remove_file(kit->dev, &dev_attr_input10); |
654 | device_remove_file(&interface->dev, &dev_attr_input11); | 682 | device_remove_file(kit->dev, &dev_attr_input11); |
655 | device_remove_file(&interface->dev, &dev_attr_input12); | 683 | device_remove_file(kit->dev, &dev_attr_input12); |
656 | device_remove_file(&interface->dev, &dev_attr_input13); | 684 | device_remove_file(kit->dev, &dev_attr_input13); |
657 | device_remove_file(&interface->dev, &dev_attr_input14); | 685 | device_remove_file(kit->dev, &dev_attr_input14); |
658 | device_remove_file(&interface->dev, &dev_attr_input15); | 686 | device_remove_file(kit->dev, &dev_attr_input15); |
659 | device_remove_file(&interface->dev, &dev_attr_input16); | 687 | device_remove_file(kit->dev, &dev_attr_input16); |
660 | } | 688 | } |
661 | 689 | ||
662 | if (kit->ifkit->sensors >= 4) { | 690 | if (kit->ifkit->sensors >= 4) { |
663 | device_remove_file(&interface->dev, &dev_attr_sensor1); | 691 | device_remove_file(kit->dev, &dev_attr_sensor1); |
664 | device_remove_file(&interface->dev, &dev_attr_sensor2); | 692 | device_remove_file(kit->dev, &dev_attr_sensor2); |
665 | device_remove_file(&interface->dev, &dev_attr_sensor3); | 693 | device_remove_file(kit->dev, &dev_attr_sensor3); |
666 | device_remove_file(&interface->dev, &dev_attr_sensor4); | 694 | device_remove_file(kit->dev, &dev_attr_sensor4); |
667 | } | 695 | } |
668 | if (kit->ifkit->sensors >= 7) { | 696 | if (kit->ifkit->sensors >= 7) { |
669 | device_remove_file(&interface->dev, &dev_attr_sensor5); | 697 | device_remove_file(kit->dev, &dev_attr_sensor5); |
670 | device_remove_file(&interface->dev, &dev_attr_sensor6); | 698 | device_remove_file(kit->dev, &dev_attr_sensor6); |
671 | device_remove_file(&interface->dev, &dev_attr_sensor7); | 699 | device_remove_file(kit->dev, &dev_attr_sensor7); |
672 | } | 700 | } |
673 | if (kit->ifkit->sensors == 8) | 701 | if (kit->ifkit->sensors == 8) |
674 | device_remove_file(&interface->dev, &dev_attr_sensor8); | 702 | device_remove_file(kit->dev, &dev_attr_sensor8); |
675 | 703 | ||
676 | if (kit->ifkit->has_lcd) | 704 | if (kit->ifkit->has_lcd) |
677 | device_remove_file(&interface->dev, &dev_attr_lcd); | 705 | device_remove_file(kit->dev, &dev_attr_lcd); |
706 | |||
707 | device_unregister(kit->dev); | ||
678 | 708 | ||
679 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", | 709 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
680 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); | 710 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
681 | 711 | ||
682 | usb_put_dev(kit->udev); | 712 | usb_put_dev(kit->udev); |
713 | clear_bit(kit->dev_no, &device_no); | ||
714 | |||
683 | kfree(kit); | 715 | kfree(kit); |
684 | } | 716 | } |
685 | 717 | ||
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 2972dc2eb27f..d9ac7f97f8c8 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/usb.h> | 16 | #include <linux/usb.h> |
17 | 17 | ||
18 | #include "phidget.h" | ||
19 | |||
18 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 20 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
19 | #define DRIVER_DESC "USB PhidgetMotorControl Driver" | 21 | #define DRIVER_DESC "USB PhidgetMotorControl Driver" |
20 | 22 | ||
@@ -23,9 +25,13 @@ | |||
23 | 25 | ||
24 | #define URB_INT_SIZE 8 | 26 | #define URB_INT_SIZE 8 |
25 | 27 | ||
28 | static unsigned long device_no; | ||
29 | |||
26 | struct motorcontrol { | 30 | struct motorcontrol { |
27 | struct usb_device *udev; | 31 | struct usb_device *udev; |
28 | struct usb_interface *intf; | 32 | struct usb_interface *intf; |
33 | struct device *dev; | ||
34 | int dev_no; | ||
29 | u8 inputs[4]; | 35 | u8 inputs[4]; |
30 | s8 desired_speed[2]; | 36 | s8 desired_speed[2]; |
31 | s8 speed[2]; | 37 | s8 speed[2]; |
@@ -162,14 +168,14 @@ static void do_notify(void *data) | |||
162 | for (i=0; i<4; i++) { | 168 | for (i=0; i<4; i++) { |
163 | if (test_and_clear_bit(i, &mc->input_events)) { | 169 | if (test_and_clear_bit(i, &mc->input_events)) { |
164 | sprintf(sysfs_file, "input%d", i); | 170 | sprintf(sysfs_file, "input%d", i); |
165 | sysfs_notify(&mc->intf->dev.kobj, NULL, sysfs_file); | 171 | sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); |
166 | } | 172 | } |
167 | } | 173 | } |
168 | 174 | ||
169 | for (i=0; i<2; i++) { | 175 | for (i=0; i<2; i++) { |
170 | if (test_and_clear_bit(i, &mc->speed_events)) { | 176 | if (test_and_clear_bit(i, &mc->speed_events)) { |
171 | sprintf(sysfs_file, "speed%d", i); | 177 | sprintf(sysfs_file, "speed%d", i); |
172 | sysfs_notify(&mc->intf->dev.kobj, NULL, sysfs_file); | 178 | sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); |
173 | } | 179 | } |
174 | } | 180 | } |
175 | 181 | ||
@@ -181,11 +187,11 @@ static void do_notify(void *data) | |||
181 | } | 187 | } |
182 | 188 | ||
183 | #define show_set_speed(value) \ | 189 | #define show_set_speed(value) \ |
184 | static ssize_t set_speed##value(struct device *dev, \ | 190 | static ssize_t set_speed##value(struct device *dev, \ |
185 | struct device_attribute *attr, const char *buf, size_t count) \ | 191 | struct device_attribute *attr, \ |
192 | const char *buf, size_t count) \ | ||
186 | { \ | 193 | { \ |
187 | struct usb_interface *intf = to_usb_interface(dev); \ | 194 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
188 | struct motorcontrol *mc = usb_get_intfdata(intf); \ | ||
189 | int speed; \ | 195 | int speed; \ |
190 | int retval; \ | 196 | int retval; \ |
191 | \ | 197 | \ |
@@ -202,11 +208,11 @@ static ssize_t set_speed##value(struct device *dev, \ | |||
202 | return retval ? retval : count; \ | 208 | return retval ? retval : count; \ |
203 | } \ | 209 | } \ |
204 | \ | 210 | \ |
205 | static ssize_t show_speed##value(struct device *dev, \ | 211 | static ssize_t show_speed##value(struct device *dev, \ |
206 | struct device_attribute *attr, char *buf) \ | 212 | struct device_attribute *attr, \ |
213 | char *buf) \ | ||
207 | { \ | 214 | { \ |
208 | struct usb_interface *intf = to_usb_interface(dev); \ | 215 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
209 | struct motorcontrol *mc = usb_get_intfdata(intf); \ | ||
210 | \ | 216 | \ |
211 | return sprintf(buf, "%d\n", mc->speed[value]); \ | 217 | return sprintf(buf, "%d\n", mc->speed[value]); \ |
212 | } \ | 218 | } \ |
@@ -217,10 +223,10 @@ show_set_speed(1); | |||
217 | 223 | ||
218 | #define show_set_acceleration(value) \ | 224 | #define show_set_acceleration(value) \ |
219 | static ssize_t set_acceleration##value(struct device *dev, \ | 225 | static ssize_t set_acceleration##value(struct device *dev, \ |
220 | struct device_attribute *attr, const char *buf, size_t count) \ | 226 | struct device_attribute *attr, \ |
227 | const char *buf, size_t count) \ | ||
221 | { \ | 228 | { \ |
222 | struct usb_interface *intf = to_usb_interface(dev); \ | 229 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
223 | struct motorcontrol *mc = usb_get_intfdata(intf); \ | ||
224 | int acceleration; \ | 230 | int acceleration; \ |
225 | int retval; \ | 231 | int retval; \ |
226 | \ | 232 | \ |
@@ -237,11 +243,11 @@ static ssize_t set_acceleration##value(struct device *dev, \ | |||
237 | return retval ? retval : count; \ | 243 | return retval ? retval : count; \ |
238 | } \ | 244 | } \ |
239 | \ | 245 | \ |
240 | static ssize_t show_acceleration##value(struct device *dev, \ | 246 | static ssize_t show_acceleration##value(struct device *dev, \ |
241 | struct device_attribute *attr, char *buf) \ | 247 | struct device_attribute *attr, \ |
248 | char *buf) \ | ||
242 | { \ | 249 | { \ |
243 | struct usb_interface *intf = to_usb_interface(dev); \ | 250 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
244 | struct motorcontrol *mc = usb_get_intfdata(intf); \ | ||
245 | \ | 251 | \ |
246 | return sprintf(buf, "%d\n", mc->acceleration[value]); \ | 252 | return sprintf(buf, "%d\n", mc->acceleration[value]); \ |
247 | } \ | 253 | } \ |
@@ -251,11 +257,11 @@ show_set_acceleration(0); | |||
251 | show_set_acceleration(1); | 257 | show_set_acceleration(1); |
252 | 258 | ||
253 | #define show_current(value) \ | 259 | #define show_current(value) \ |
254 | static ssize_t show_current##value(struct device *dev, \ | 260 | static ssize_t show_current##value(struct device *dev, \ |
255 | struct device_attribute *attr, char *buf) \ | 261 | struct device_attribute *attr, \ |
262 | char *buf) \ | ||
256 | { \ | 263 | { \ |
257 | struct usb_interface *intf = to_usb_interface(dev); \ | 264 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
258 | struct motorcontrol *mc = usb_get_intfdata(intf); \ | ||
259 | \ | 265 | \ |
260 | return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ | 266 | return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ |
261 | } \ | 267 | } \ |
@@ -265,11 +271,11 @@ show_current(0); | |||
265 | show_current(1); | 271 | show_current(1); |
266 | 272 | ||
267 | #define show_input(value) \ | 273 | #define show_input(value) \ |
268 | static ssize_t show_input##value(struct device *dev, \ | 274 | static ssize_t show_input##value(struct device *dev, \ |
269 | struct device_attribute *attr, char *buf) \ | 275 | struct device_attribute *attr, \ |
276 | char *buf) \ | ||
270 | { \ | 277 | { \ |
271 | struct usb_interface *intf = to_usb_interface(dev); \ | 278 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
272 | struct motorcontrol *mc = usb_get_intfdata(intf); \ | ||
273 | \ | 279 | \ |
274 | return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ | 280 | return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ |
275 | } \ | 281 | } \ |
@@ -287,6 +293,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic | |||
287 | struct usb_endpoint_descriptor *endpoint; | 293 | struct usb_endpoint_descriptor *endpoint; |
288 | struct motorcontrol *mc; | 294 | struct motorcontrol *mc; |
289 | int pipe, maxp, rc = -ENOMEM; | 295 | int pipe, maxp, rc = -ENOMEM; |
296 | int bit, value; | ||
290 | 297 | ||
291 | interface = intf->cur_altsetting; | 298 | interface = intf->cur_altsetting; |
292 | if (interface->desc.bNumEndpoints != 1) | 299 | if (interface->desc.bNumEndpoints != 1) |
@@ -306,6 +313,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic | |||
306 | if (!mc) | 313 | if (!mc) |
307 | goto out; | 314 | goto out; |
308 | 315 | ||
316 | mc->dev_no = -1; | ||
309 | mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma); | 317 | mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma); |
310 | if (!mc->data) | 318 | if (!mc->data) |
311 | goto out; | 319 | goto out; |
@@ -326,26 +334,42 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic | |||
326 | 334 | ||
327 | usb_set_intfdata(intf, mc); | 335 | usb_set_intfdata(intf, mc); |
328 | 336 | ||
337 | do { | ||
338 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
339 | value = test_and_set_bit(bit, &device_no); | ||
340 | } while(value); | ||
341 | mc->dev_no = bit; | ||
342 | |||
343 | mc->dev = device_create(phidget_class, &mc->udev->dev, 0, | ||
344 | "motorcontrol%d", mc->dev_no); | ||
345 | if (IS_ERR(mc->dev)) { | ||
346 | rc = PTR_ERR(mc->dev); | ||
347 | mc->dev = NULL; | ||
348 | goto out; | ||
349 | } | ||
350 | |||
351 | dev_set_drvdata(mc->dev, mc); | ||
352 | |||
329 | if (usb_submit_urb(mc->irq, GFP_KERNEL)) { | 353 | if (usb_submit_urb(mc->irq, GFP_KERNEL)) { |
330 | rc = -EIO; | 354 | rc = -EIO; |
331 | goto out; | 355 | goto out; |
332 | } | 356 | } |
333 | 357 | ||
334 | device_create_file(&intf->dev, &dev_attr_input0); | 358 | device_create_file(mc->dev, &dev_attr_input0); |
335 | device_create_file(&intf->dev, &dev_attr_input1); | 359 | device_create_file(mc->dev, &dev_attr_input1); |
336 | device_create_file(&intf->dev, &dev_attr_input2); | 360 | device_create_file(mc->dev, &dev_attr_input2); |
337 | device_create_file(&intf->dev, &dev_attr_input3); | 361 | device_create_file(mc->dev, &dev_attr_input3); |
338 | 362 | ||
339 | device_create_file(&intf->dev, &dev_attr_speed0); | 363 | device_create_file(mc->dev, &dev_attr_speed0); |
340 | device_create_file(&intf->dev, &dev_attr_speed1); | 364 | device_create_file(mc->dev, &dev_attr_speed1); |
341 | 365 | ||
342 | device_create_file(&intf->dev, &dev_attr_acceleration0); | 366 | device_create_file(mc->dev, &dev_attr_acceleration0); |
343 | device_create_file(&intf->dev, &dev_attr_acceleration1); | 367 | device_create_file(mc->dev, &dev_attr_acceleration1); |
344 | 368 | ||
345 | device_create_file(&intf->dev, &dev_attr_current0); | 369 | device_create_file(mc->dev, &dev_attr_current0); |
346 | device_create_file(&intf->dev, &dev_attr_current1); | 370 | device_create_file(mc->dev, &dev_attr_current1); |
347 | 371 | ||
348 | dev_info(&intf->dev, "USB Phidget MotorControl attached\n"); | 372 | dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); |
349 | 373 | ||
350 | return 0; | 374 | return 0; |
351 | 375 | ||
@@ -355,6 +379,11 @@ out: | |||
355 | usb_free_urb(mc->irq); | 379 | usb_free_urb(mc->irq); |
356 | if (mc->data) | 380 | if (mc->data) |
357 | usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); | 381 | usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); |
382 | if (mc->dev) | ||
383 | device_unregister(mc->dev); | ||
384 | if (mc->dev_no >= 0) | ||
385 | clear_bit(mc->dev_no, &device_no); | ||
386 | |||
358 | kfree(mc); | 387 | kfree(mc); |
359 | } | 388 | } |
360 | 389 | ||
@@ -376,24 +405,27 @@ static void motorcontrol_disconnect(struct usb_interface *interface) | |||
376 | 405 | ||
377 | cancel_delayed_work(&mc->do_notify); | 406 | cancel_delayed_work(&mc->do_notify); |
378 | 407 | ||
379 | device_remove_file(&interface->dev, &dev_attr_input0); | 408 | device_remove_file(mc->dev, &dev_attr_input0); |
380 | device_remove_file(&interface->dev, &dev_attr_input1); | 409 | device_remove_file(mc->dev, &dev_attr_input1); |
381 | device_remove_file(&interface->dev, &dev_attr_input2); | 410 | device_remove_file(mc->dev, &dev_attr_input2); |
382 | device_remove_file(&interface->dev, &dev_attr_input3); | 411 | device_remove_file(mc->dev, &dev_attr_input3); |
383 | 412 | ||
384 | device_remove_file(&interface->dev, &dev_attr_speed0); | 413 | device_remove_file(mc->dev, &dev_attr_speed0); |
385 | device_remove_file(&interface->dev, &dev_attr_speed1); | 414 | device_remove_file(mc->dev, &dev_attr_speed1); |
386 | 415 | ||
387 | device_remove_file(&interface->dev, &dev_attr_acceleration0); | 416 | device_remove_file(mc->dev, &dev_attr_acceleration0); |
388 | device_remove_file(&interface->dev, &dev_attr_acceleration1); | 417 | device_remove_file(mc->dev, &dev_attr_acceleration1); |
389 | 418 | ||
390 | device_remove_file(&interface->dev, &dev_attr_current0); | 419 | device_remove_file(mc->dev, &dev_attr_current0); |
391 | device_remove_file(&interface->dev, &dev_attr_current1); | 420 | device_remove_file(mc->dev, &dev_attr_current1); |
392 | 421 | ||
393 | dev_info(&interface->dev, "USB Phidget MotorControl disconnected\n"); | 422 | device_unregister(mc->dev); |
394 | 423 | ||
395 | usb_put_dev(mc->udev); | 424 | usb_put_dev(mc->udev); |
425 | clear_bit(mc->dev_no, &device_no); | ||
396 | kfree(mc); | 426 | kfree(mc); |
427 | |||
428 | dev_info(&interface->dev, "USB PhidgetMotorControl detached\n"); | ||
397 | } | 429 | } |
398 | 430 | ||
399 | static struct usb_driver motorcontrol_driver = { | 431 | static struct usb_driver motorcontrol_driver = { |
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index c0df79c96538..66be9513fd6f 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c | |||
@@ -15,14 +15,6 @@ | |||
15 | * | 15 | * |
16 | * CAUTION: Generally you should use 0 < degrees < 180 as anything else | 16 | * CAUTION: Generally you should use 0 < degrees < 180 as anything else |
17 | * is probably beyond the range of your servo and may damage it. | 17 | * is probably beyond the range of your servo and may damage it. |
18 | * | ||
19 | * Jun 16, 2004: Sean Young <sean@mess.org> | ||
20 | * - cleanups | ||
21 | * - was using memory after kfree() | ||
22 | * Aug 8, 2004: Sean Young <sean@mess.org> | ||
23 | * - set the highest angle as high as the hardware allows, there are | ||
24 | * some odd servos out there | ||
25 | * | ||
26 | */ | 18 | */ |
27 | 19 | ||
28 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
@@ -32,6 +24,8 @@ | |||
32 | #include <linux/module.h> | 24 | #include <linux/module.h> |
33 | #include <linux/usb.h> | 25 | #include <linux/usb.h> |
34 | 26 | ||
27 | #include "phidget.h" | ||
28 | |||
35 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 29 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
36 | #define DRIVER_DESC "USB PhidgetServo Driver" | 30 | #define DRIVER_DESC "USB PhidgetServo Driver" |
37 | 31 | ||
@@ -70,8 +64,12 @@ static struct usb_device_id id_table[] = { | |||
70 | 64 | ||
71 | MODULE_DEVICE_TABLE(usb, id_table); | 65 | MODULE_DEVICE_TABLE(usb, id_table); |
72 | 66 | ||
67 | static int unsigned long device_no; | ||
68 | |||
73 | struct phidget_servo { | 69 | struct phidget_servo { |
74 | struct usb_device *udev; | 70 | struct usb_device *udev; |
71 | struct device *dev; | ||
72 | int dev_no; | ||
75 | ulong type; | 73 | ulong type; |
76 | int pulse[4]; | 74 | int pulse[4]; |
77 | int degrees[4]; | 75 | int degrees[4]; |
@@ -203,16 +201,16 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, | |||
203 | } | 201 | } |
204 | 202 | ||
205 | #define show_set(value) \ | 203 | #define show_set(value) \ |
206 | static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr, \ | 204 | static ssize_t set_servo##value (struct device *dev, \ |
205 | struct device_attribute *attr, \ | ||
207 | const char *buf, size_t count) \ | 206 | const char *buf, size_t count) \ |
208 | { \ | 207 | { \ |
209 | int degrees, minutes, retval; \ | 208 | int degrees, minutes, retval; \ |
210 | struct usb_interface *intf = to_usb_interface (dev); \ | 209 | struct phidget_servo *servo = dev_get_drvdata(dev); \ |
211 | struct phidget_servo *servo = usb_get_intfdata (intf); \ | ||
212 | \ | 210 | \ |
213 | minutes = 0; \ | 211 | minutes = 0; \ |
214 | /* must at least convert degrees */ \ | 212 | /* must at least convert degrees */ \ |
215 | if (sscanf (buf, "%d.%d", °rees, &minutes) < 1) { \ | 213 | if (sscanf(buf, "%d.%d", °rees, &minutes) < 1) { \ |
216 | return -EINVAL; \ | 214 | return -EINVAL; \ |
217 | } \ | 215 | } \ |
218 | \ | 216 | \ |
@@ -220,21 +218,22 @@ static ssize_t set_servo##value (struct device *dev, struct device_attribute *at | |||
220 | return -EINVAL; \ | 218 | return -EINVAL; \ |
221 | \ | 219 | \ |
222 | if (servo->type & SERVO_VERSION_30) \ | 220 | if (servo->type & SERVO_VERSION_30) \ |
223 | retval = change_position_v30 (servo, value, degrees, \ | 221 | retval = change_position_v30(servo, value, degrees, \ |
224 | minutes); \ | 222 | minutes); \ |
225 | else \ | 223 | else \ |
226 | retval = change_position_v20 (servo, value, degrees, \ | 224 | retval = change_position_v20(servo, value, degrees, \ |
227 | minutes); \ | 225 | minutes); \ |
228 | \ | 226 | \ |
229 | return retval < 0 ? retval : count; \ | 227 | return retval < 0 ? retval : count; \ |
230 | } \ | 228 | } \ |
231 | \ | 229 | \ |
232 | static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) \ | 230 | static ssize_t show_servo##value (struct device *dev, \ |
231 | struct device_attribute *attr, \ | ||
232 | char *buf) \ | ||
233 | { \ | 233 | { \ |
234 | struct usb_interface *intf = to_usb_interface (dev); \ | 234 | struct phidget_servo *servo = dev_get_drvdata(dev); \ |
235 | struct phidget_servo *servo = usb_get_intfdata (intf); \ | ||
236 | \ | 235 | \ |
237 | return sprintf (buf, "%d.%02d\n", servo->degrees[value], \ | 236 | return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ |
238 | servo->minutes[value]); \ | 237 | servo->minutes[value]); \ |
239 | } \ | 238 | } \ |
240 | static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ | 239 | static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ |
@@ -250,6 +249,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id) | |||
250 | { | 249 | { |
251 | struct usb_device *udev = interface_to_usbdev(interface); | 250 | struct usb_device *udev = interface_to_usbdev(interface); |
252 | struct phidget_servo *dev; | 251 | struct phidget_servo *dev; |
252 | int bit, value; | ||
253 | 253 | ||
254 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); | 254 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); |
255 | if (dev == NULL) { | 255 | if (dev == NULL) { |
@@ -261,18 +261,33 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id) | |||
261 | dev->type = id->driver_info; | 261 | dev->type = id->driver_info; |
262 | usb_set_intfdata(interface, dev); | 262 | usb_set_intfdata(interface, dev); |
263 | 263 | ||
264 | device_create_file(&interface->dev, &dev_attr_servo0); | 264 | do { |
265 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
266 | value = test_and_set_bit(bit, &device_no); | ||
267 | } while(value); | ||
268 | dev->dev_no = bit; | ||
269 | |||
270 | dev->dev = device_create(phidget_class, &dev->udev->dev, 0, | ||
271 | "servo%d", dev->dev_no); | ||
272 | if (IS_ERR(dev->dev)) { | ||
273 | int rc = PTR_ERR(dev->dev); | ||
274 | clear_bit(dev->dev_no, &device_no); | ||
275 | kfree(dev); | ||
276 | return rc; | ||
277 | } | ||
278 | |||
279 | device_create_file(dev->dev, &dev_attr_servo0); | ||
265 | if (dev->type & SERVO_COUNT_QUAD) { | 280 | if (dev->type & SERVO_COUNT_QUAD) { |
266 | device_create_file(&interface->dev, &dev_attr_servo1); | 281 | device_create_file(dev->dev, &dev_attr_servo1); |
267 | device_create_file(&interface->dev, &dev_attr_servo2); | 282 | device_create_file(dev->dev, &dev_attr_servo2); |
268 | device_create_file(&interface->dev, &dev_attr_servo3); | 283 | device_create_file(dev->dev, &dev_attr_servo3); |
269 | } | 284 | } |
270 | 285 | ||
271 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", | 286 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", |
272 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, | 287 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, |
273 | dev->type & SERVO_VERSION_30 ? 3 : 2); | 288 | dev->type & SERVO_VERSION_30 ? 3 : 2); |
274 | 289 | ||
275 | if(!(dev->type & SERVO_VERSION_30)) | 290 | if (!(dev->type & SERVO_VERSION_30)) |
276 | dev_info(&interface->dev, | 291 | dev_info(&interface->dev, |
277 | "WARNING: v2.0 not tested! Please report if it works.\n"); | 292 | "WARNING: v2.0 not tested! Please report if it works.\n"); |
278 | 293 | ||
@@ -287,19 +302,21 @@ servo_disconnect(struct usb_interface *interface) | |||
287 | dev = usb_get_intfdata(interface); | 302 | dev = usb_get_intfdata(interface); |
288 | usb_set_intfdata(interface, NULL); | 303 | usb_set_intfdata(interface, NULL); |
289 | 304 | ||
290 | device_remove_file(&interface->dev, &dev_attr_servo0); | 305 | device_remove_file(dev->dev, &dev_attr_servo0); |
291 | if (dev->type & SERVO_COUNT_QUAD) { | 306 | if (dev->type & SERVO_COUNT_QUAD) { |
292 | device_remove_file(&interface->dev, &dev_attr_servo1); | 307 | device_remove_file(dev->dev, &dev_attr_servo1); |
293 | device_remove_file(&interface->dev, &dev_attr_servo2); | 308 | device_remove_file(dev->dev, &dev_attr_servo2); |
294 | device_remove_file(&interface->dev, &dev_attr_servo3); | 309 | device_remove_file(dev->dev, &dev_attr_servo3); |
295 | } | 310 | } |
296 | 311 | ||
312 | device_unregister(dev->dev); | ||
297 | usb_put_dev(dev->udev); | 313 | usb_put_dev(dev->udev); |
298 | 314 | ||
299 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", | 315 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", |
300 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, | 316 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, |
301 | dev->type & SERVO_VERSION_30 ? 3 : 2); | 317 | dev->type & SERVO_VERSION_30 ? 3 : 2); |
302 | 318 | ||
319 | clear_bit(dev->dev_no, &device_no); | ||
303 | kfree(dev); | 320 | kfree(dev); |
304 | } | 321 | } |
305 | 322 | ||