aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2006-07-10 05:56:25 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:49 -0400
commit912b24c333843514ff77ed88961c6945f0f286ce (patch)
tree16b5617c0b92acb638a88ccf392e4d0d6dc910fc /drivers/usb
parentd5176b413dcce85334e270021fc0d723d1714c84 (diff)
USB: Put phidgets driver in a sysfs class
This patch creates a device class phidget and add the phidget drivers to them. Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/misc/Kconfig13
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/phidget.c43
-rw-r--r--drivers/usb/misc/phidget.h12
-rw-r--r--drivers/usb/misc/phidgetkit.c258
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c126
-rw-r--r--drivers/usb/misc/phidgetservo.c71
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
118config 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
118config USB_PHIDGETKIT 125config 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
128config USB_PHIDGETMOTORCONTROL 135config 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
138config USB_PHIDGETSERVO 145config 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
13obj-$(CONFIG_USB_LD) += ldusb.o 13obj-$(CONFIG_USB_LD) += ldusb.o
14obj-$(CONFIG_USB_LED) += usbled.o 14obj-$(CONFIG_USB_LED) += usbled.o
15obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o 15obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o
16obj-$(CONFIG_USB_PHIDGET) += phidget.o
16obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o 17obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o
17obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o 18obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o
18obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o 19obj-$(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
18struct class *phidget_class;
19
20static 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
30static void __exit cleanup_phidget(void)
31{
32 class_destroy(phidget_class);
33}
34
35EXPORT_SYMBOL_GPL(phidget_class);
36
37module_init(init_phidget);
38module_exit(cleanup_phidget);
39
40MODULE_LICENSE("GPL");
41MODULE_AUTHOR("Sean Young <sean@mess.org>");
42MODULE_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
12extern 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);
57ifkit(0, 8, 8, 1); 59ifkit(0, 8, 8, 1);
58ifkit(0, 16, 16, 0); 60ifkit(0, 16, 16, 0);
59 61
62static unsigned long device_no;
63
60struct interfacekit { 64struct 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) \
183static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 189static 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} \
190static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); 197static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
191set_lcd_line(1); 198set_lcd_line(1);
192set_lcd_line(2); 199set_lcd_line(2);
193 200
194static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 201static 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
241static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 247static 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) \
378static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ 383static 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 \
394static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ 399static 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) \
421static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ 427static 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);
445show_input(16); 450show_input(16);
446 451
447#define show_sensor(value) \ 452#define show_sensor(value) \
448static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ 453static 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
28static unsigned long device_no;
29
26struct motorcontrol { 30struct 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) \
184static ssize_t set_speed##value(struct device *dev, \ 190static 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 \
205static ssize_t show_speed##value(struct device *dev, \ 211static 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) \
219static ssize_t set_acceleration##value(struct device *dev, \ 225static 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 \
240static ssize_t show_acceleration##value(struct device *dev, \ 246static 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);
251show_set_acceleration(1); 257show_set_acceleration(1);
252 258
253#define show_current(value) \ 259#define show_current(value) \
254static ssize_t show_current##value(struct device *dev, \ 260static 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);
265show_current(1); 271show_current(1);
266 272
267#define show_input(value) \ 273#define show_input(value) \
268static ssize_t show_input##value(struct device *dev, \ 274static 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
399static struct usb_driver motorcontrol_driver = { 431static 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
71MODULE_DEVICE_TABLE(usb, id_table); 65MODULE_DEVICE_TABLE(usb, id_table);
72 66
67static int unsigned long device_no;
68
73struct phidget_servo { 69struct 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) \
206static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr, \ 204static 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", &degrees, &minutes) < 1) { \ 213 if (sscanf(buf, "%d.%d", &degrees, &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 \
232static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) \ 230static 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} \
240static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ 239static 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