Commit 912b24c333843514ff77ed88961c6945f0f286ce
Committed by
Greg Kroah-Hartman
1 parent
d5176b413d
Exists in
master
and in
7 other branches
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>
Showing 7 changed files with 334 additions and 190 deletions Side-by-side Diff
drivers/usb/misc/Kconfig
... | ... | @@ -115,9 +115,16 @@ |
115 | 115 | To compile this driver as a module, choose M here: the |
116 | 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 | 125 | config USB_PHIDGETKIT |
119 | 126 | tristate "USB PhidgetInterfaceKit support" |
120 | - depends on USB | |
127 | + depends on USB_PHIDGET | |
121 | 128 | help |
122 | 129 | Say Y here if you want to connect a PhidgetInterfaceKit USB device |
123 | 130 | from Phidgets Inc. |
... | ... | @@ -127,7 +134,7 @@ |
127 | 134 | |
128 | 135 | config USB_PHIDGETMOTORCONTROL |
129 | 136 | tristate "USB PhidgetMotorControl support" |
130 | - depends on USB | |
137 | + depends on USB_PHIDGET | |
131 | 138 | help |
132 | 139 | Say Y here if you want to connect a PhidgetMotorControl USB device |
133 | 140 | from Phidgets Inc. |
... | ... | @@ -137,7 +144,7 @@ |
137 | 144 | |
138 | 145 | config USB_PHIDGETSERVO |
139 | 146 | tristate "USB PhidgetServo support" |
140 | - depends on USB | |
147 | + depends on USB_PHIDGET | |
141 | 148 | help |
142 | 149 | Say Y here if you want to connect an 1 or 4 Motor PhidgetServo |
143 | 150 | servo controller version 2.0 or 3.0. |
drivers/usb/misc/Makefile
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | obj-$(CONFIG_USB_LD) += ldusb.o |
14 | 14 | obj-$(CONFIG_USB_LED) += usbled.o |
15 | 15 | obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o |
16 | +obj-$(CONFIG_USB_PHIDGET) += phidget.o | |
16 | 17 | obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o |
17 | 18 | obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o |
18 | 19 | obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o |
drivers/usb/misc/phidget.c
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"); |
drivers/usb/misc/phidget.h
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; |
drivers/usb/misc/phidgetkit.c
... | ... | @@ -20,6 +20,8 @@ |
20 | 20 | #include <linux/module.h> |
21 | 21 | #include <linux/usb.h> |
22 | 22 | |
23 | +#include "phidget.h" | |
24 | + | |
23 | 25 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
24 | 26 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" |
25 | 27 | |
26 | 28 | |
27 | 29 | |
... | ... | @@ -57,11 +59,15 @@ |
57 | 59 | ifkit(0, 8, 8, 1); |
58 | 60 | ifkit(0, 16, 16, 0); |
59 | 61 | |
62 | +static unsigned long device_no; | |
63 | + | |
60 | 64 | struct interfacekit { |
61 | 65 | struct usb_device *udev; |
62 | 66 | struct usb_interface *intf; |
63 | 67 | struct driver_interfacekit *ifkit; |
68 | + struct device *dev; | |
64 | 69 | unsigned long outputs; |
70 | + int dev_no; | |
65 | 71 | u8 inputs[MAX_INTERFACES]; |
66 | 72 | u16 sensors[MAX_INTERFACES]; |
67 | 73 | u8 lcd_files_on; |
68 | 74 | |
... | ... | @@ -180,21 +186,21 @@ |
180 | 186 | } |
181 | 187 | |
182 | 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) \ | |
184 | -{ \ | |
185 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
186 | - struct interfacekit *kit = usb_get_intfdata(intf); \ | |
187 | - change_string(kit, buf, number - 1); \ | |
188 | - return count; \ | |
189 | -} \ | |
189 | +static ssize_t lcd_line_##number(struct device *dev, \ | |
190 | + struct device_attribute *attr, \ | |
191 | + const char *buf, size_t count) \ | |
192 | +{ \ | |
193 | + struct interfacekit *kit = dev_get_drvdata(dev); \ | |
194 | + change_string(kit, buf, number - 1); \ | |
195 | + return count; \ | |
196 | +} \ | |
190 | 197 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); |
191 | 198 | set_lcd_line(1); |
192 | 199 | set_lcd_line(2); |
193 | 200 | |
194 | 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); | |
197 | - struct interfacekit *kit = usb_get_intfdata(intf); | |
203 | + struct interfacekit *kit = dev_get_drvdata(dev); | |
198 | 204 | int enabled; |
199 | 205 | unsigned char *buffer; |
200 | 206 | int retval = -ENOMEM; |
201 | 207 | |
... | ... | @@ -232,16 +238,15 @@ |
232 | 238 | { |
233 | 239 | if (kit->lcd_files_on) { |
234 | 240 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
235 | - device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1); | |
236 | - device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2); | |
237 | - device_remove_file(&kit->intf->dev, &dev_attr_backlight); | |
241 | + device_remove_file(kit->dev, &dev_attr_lcd_line_1); | |
242 | + device_remove_file(kit->dev, &dev_attr_lcd_line_2); | |
243 | + device_remove_file(kit->dev, &dev_attr_backlight); | |
238 | 244 | } |
239 | 245 | } |
240 | 246 | |
241 | 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); | |
244 | - struct interfacekit *kit = usb_get_intfdata(intf); | |
249 | + struct interfacekit *kit = dev_get_drvdata(dev); | |
245 | 250 | int enable; |
246 | 251 | |
247 | 252 | if (kit->ifkit->has_lcd == 0) |
... | ... | @@ -253,9 +258,9 @@ |
253 | 258 | if (enable) { |
254 | 259 | if (!kit->lcd_files_on) { |
255 | 260 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); |
256 | - device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1); | |
257 | - device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2); | |
258 | - device_create_file(&kit->intf->dev, &dev_attr_backlight); | |
261 | + device_create_file(kit->dev, &dev_attr_lcd_line_1); | |
262 | + device_create_file(kit->dev, &dev_attr_lcd_line_2); | |
263 | + device_create_file(kit->dev, &dev_attr_backlight); | |
259 | 264 | kit->lcd_files_on = 1; |
260 | 265 | } |
261 | 266 | } else { |
262 | 267 | |
263 | 268 | |
264 | 269 | |
... | ... | @@ -362,24 +367,24 @@ |
362 | 367 | for (i=0; i<kit->ifkit->inputs; i++) { |
363 | 368 | if (test_and_clear_bit(i, &kit->input_events)) { |
364 | 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 | 374 | for (i=0; i<kit->ifkit->sensors; i++) { |
370 | 375 | if (test_and_clear_bit(i, &kit->sensor_events)) { |
371 | 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 | 382 | #define show_set_output(value) \ |
378 | -static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | |
379 | - size_t count) \ | |
383 | +static ssize_t set_output##value(struct device *dev, \ | |
384 | + struct device_attribute *attr, \ | |
385 | + const char *buf, size_t count) \ | |
380 | 386 | { \ |
381 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
382 | - struct interfacekit *kit = usb_get_intfdata(intf); \ | |
387 | + struct interfacekit *kit = dev_get_drvdata(dev); \ | |
383 | 388 | int enabled; \ |
384 | 389 | int retval; \ |
385 | 390 | \ |
386 | 391 | |
... | ... | @@ -391,10 +396,11 @@ |
391 | 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); \ | |
397 | - struct interfacekit *kit = usb_get_intfdata(intf); \ | |
403 | + struct interfacekit *kit = dev_get_drvdata(dev); \ | |
398 | 404 | \ |
399 | 405 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
400 | 406 | } \ |
... | ... | @@ -420,8 +426,7 @@ |
420 | 426 | #define show_input(value) \ |
421 | 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); \ | |
424 | - struct interfacekit *kit = usb_get_intfdata(intf); \ | |
429 | + struct interfacekit *kit = dev_get_drvdata(dev); \ | |
425 | 430 | \ |
426 | 431 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
427 | 432 | } \ |
428 | 433 | |
... | ... | @@ -445,10 +450,11 @@ |
445 | 450 | show_input(16); |
446 | 451 | |
447 | 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); \ | |
451 | - struct interfacekit *kit = usb_get_intfdata(intf); \ | |
457 | + struct interfacekit *kit = dev_get_drvdata(dev); \ | |
452 | 458 | \ |
453 | 459 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
454 | 460 | } \ |
... | ... | @@ -471,6 +477,7 @@ |
471 | 477 | struct interfacekit *kit; |
472 | 478 | struct driver_interfacekit *ifkit; |
473 | 479 | int pipe, maxp, rc = -ENOMEM; |
480 | + int bit, value; | |
474 | 481 | |
475 | 482 | ifkit = (struct driver_interfacekit *)id->driver_info; |
476 | 483 | if (!ifkit) |
... | ... | @@ -493,6 +500,7 @@ |
493 | 500 | if (!kit) |
494 | 501 | goto out; |
495 | 502 | |
503 | + kit->dev_no = -1; | |
496 | 504 | kit->ifkit = ifkit; |
497 | 505 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
498 | 506 | if (!kit->data) |
499 | 507 | |
500 | 508 | |
501 | 509 | |
502 | 510 | |
503 | 511 | |
504 | 512 | |
505 | 513 | |
506 | 514 | |
507 | 515 | |
508 | 516 | |
... | ... | @@ -513,73 +521,88 @@ |
513 | 521 | |
514 | 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 | 539 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
517 | 540 | rc = -EIO; |
518 | 541 | goto out; |
519 | 542 | } |
520 | 543 | |
521 | 544 | if (ifkit->outputs >= 4) { |
522 | - device_create_file(&intf->dev, &dev_attr_output1); | |
523 | - device_create_file(&intf->dev, &dev_attr_output2); | |
524 | - device_create_file(&intf->dev, &dev_attr_output3); | |
525 | - device_create_file(&intf->dev, &dev_attr_output4); | |
545 | + device_create_file(kit->dev, &dev_attr_output1); | |
546 | + device_create_file(kit->dev, &dev_attr_output2); | |
547 | + device_create_file(kit->dev, &dev_attr_output3); | |
548 | + device_create_file(kit->dev, &dev_attr_output4); | |
526 | 549 | } |
527 | 550 | if (ifkit->outputs >= 8) { |
528 | - device_create_file(&intf->dev, &dev_attr_output5); | |
529 | - device_create_file(&intf->dev, &dev_attr_output6); | |
530 | - device_create_file(&intf->dev, &dev_attr_output7); | |
531 | - device_create_file(&intf->dev, &dev_attr_output8); | |
551 | + device_create_file(kit->dev, &dev_attr_output5); | |
552 | + device_create_file(kit->dev, &dev_attr_output6); | |
553 | + device_create_file(kit->dev, &dev_attr_output7); | |
554 | + device_create_file(kit->dev, &dev_attr_output8); | |
532 | 555 | } |
533 | 556 | if (ifkit->outputs == 16) { |
534 | - device_create_file(&intf->dev, &dev_attr_output9); | |
535 | - device_create_file(&intf->dev, &dev_attr_output10); | |
536 | - device_create_file(&intf->dev, &dev_attr_output11); | |
537 | - device_create_file(&intf->dev, &dev_attr_output12); | |
538 | - device_create_file(&intf->dev, &dev_attr_output13); | |
539 | - device_create_file(&intf->dev, &dev_attr_output14); | |
540 | - device_create_file(&intf->dev, &dev_attr_output15); | |
541 | - device_create_file(&intf->dev, &dev_attr_output16); | |
557 | + device_create_file(kit->dev, &dev_attr_output9); | |
558 | + device_create_file(kit->dev, &dev_attr_output10); | |
559 | + device_create_file(kit->dev, &dev_attr_output11); | |
560 | + device_create_file(kit->dev, &dev_attr_output12); | |
561 | + device_create_file(kit->dev, &dev_attr_output13); | |
562 | + device_create_file(kit->dev, &dev_attr_output14); | |
563 | + device_create_file(kit->dev, &dev_attr_output15); | |
564 | + device_create_file(kit->dev, &dev_attr_output16); | |
542 | 565 | } |
543 | 566 | |
544 | 567 | if (ifkit->inputs >= 4) { |
545 | - device_create_file(&intf->dev, &dev_attr_input1); | |
546 | - device_create_file(&intf->dev, &dev_attr_input2); | |
547 | - device_create_file(&intf->dev, &dev_attr_input3); | |
548 | - device_create_file(&intf->dev, &dev_attr_input4); | |
568 | + device_create_file(kit->dev, &dev_attr_input1); | |
569 | + device_create_file(kit->dev, &dev_attr_input2); | |
570 | + device_create_file(kit->dev, &dev_attr_input3); | |
571 | + device_create_file(kit->dev, &dev_attr_input4); | |
549 | 572 | } |
550 | 573 | if (ifkit->inputs >= 8) { |
551 | - device_create_file(&intf->dev, &dev_attr_input5); | |
552 | - device_create_file(&intf->dev, &dev_attr_input6); | |
553 | - device_create_file(&intf->dev, &dev_attr_input7); | |
554 | - device_create_file(&intf->dev, &dev_attr_input8); | |
574 | + device_create_file(kit->dev, &dev_attr_input5); | |
575 | + device_create_file(kit->dev, &dev_attr_input6); | |
576 | + device_create_file(kit->dev, &dev_attr_input7); | |
577 | + device_create_file(kit->dev, &dev_attr_input8); | |
555 | 578 | } |
556 | 579 | if (ifkit->inputs == 16) { |
557 | - device_create_file(&intf->dev, &dev_attr_input9); | |
558 | - device_create_file(&intf->dev, &dev_attr_input10); | |
559 | - device_create_file(&intf->dev, &dev_attr_input11); | |
560 | - device_create_file(&intf->dev, &dev_attr_input12); | |
561 | - device_create_file(&intf->dev, &dev_attr_input13); | |
562 | - device_create_file(&intf->dev, &dev_attr_input14); | |
563 | - device_create_file(&intf->dev, &dev_attr_input15); | |
564 | - device_create_file(&intf->dev, &dev_attr_input16); | |
580 | + device_create_file(kit->dev, &dev_attr_input9); | |
581 | + device_create_file(kit->dev, &dev_attr_input10); | |
582 | + device_create_file(kit->dev, &dev_attr_input11); | |
583 | + device_create_file(kit->dev, &dev_attr_input12); | |
584 | + device_create_file(kit->dev, &dev_attr_input13); | |
585 | + device_create_file(kit->dev, &dev_attr_input14); | |
586 | + device_create_file(kit->dev, &dev_attr_input15); | |
587 | + device_create_file(kit->dev, &dev_attr_input16); | |
565 | 588 | } |
566 | 589 | |
567 | 590 | if (ifkit->sensors >= 4) { |
568 | - device_create_file(&intf->dev, &dev_attr_sensor1); | |
569 | - device_create_file(&intf->dev, &dev_attr_sensor2); | |
570 | - device_create_file(&intf->dev, &dev_attr_sensor3); | |
571 | - device_create_file(&intf->dev, &dev_attr_sensor4); | |
591 | + device_create_file(kit->dev, &dev_attr_sensor1); | |
592 | + device_create_file(kit->dev, &dev_attr_sensor2); | |
593 | + device_create_file(kit->dev, &dev_attr_sensor3); | |
594 | + device_create_file(kit->dev, &dev_attr_sensor4); | |
572 | 595 | } |
573 | 596 | if (ifkit->sensors >= 7) { |
574 | - device_create_file(&intf->dev, &dev_attr_sensor5); | |
575 | - device_create_file(&intf->dev, &dev_attr_sensor6); | |
576 | - device_create_file(&intf->dev, &dev_attr_sensor7); | |
597 | + device_create_file(kit->dev, &dev_attr_sensor5); | |
598 | + device_create_file(kit->dev, &dev_attr_sensor6); | |
599 | + device_create_file(kit->dev, &dev_attr_sensor7); | |
577 | 600 | } |
578 | 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 | 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 | 607 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", |
585 | 608 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
... | ... | @@ -592,6 +615,11 @@ |
592 | 615 | usb_free_urb(kit->irq); |
593 | 616 | if (kit->data) |
594 | 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 | 623 | kfree(kit); |
596 | 624 | } |
597 | 625 | |
598 | 626 | |
599 | 627 | |
600 | 628 | |
601 | 629 | |
602 | 630 | |
603 | 631 | |
604 | 632 | |
605 | 633 | |
606 | 634 | |
607 | 635 | |
608 | 636 | |
... | ... | @@ -614,72 +642,76 @@ |
614 | 642 | cancel_delayed_work(&kit->do_notify); |
615 | 643 | |
616 | 644 | if (kit->ifkit->outputs >= 4) { |
617 | - device_remove_file(&interface->dev, &dev_attr_output1); | |
618 | - device_remove_file(&interface->dev, &dev_attr_output2); | |
619 | - device_remove_file(&interface->dev, &dev_attr_output3); | |
620 | - device_remove_file(&interface->dev, &dev_attr_output4); | |
645 | + device_remove_file(kit->dev, &dev_attr_output1); | |
646 | + device_remove_file(kit->dev, &dev_attr_output2); | |
647 | + device_remove_file(kit->dev, &dev_attr_output3); | |
648 | + device_remove_file(kit->dev, &dev_attr_output4); | |
621 | 649 | } |
622 | 650 | if (kit->ifkit->outputs >= 8) { |
623 | - device_remove_file(&interface->dev, &dev_attr_output5); | |
624 | - device_remove_file(&interface->dev, &dev_attr_output6); | |
625 | - device_remove_file(&interface->dev, &dev_attr_output7); | |
626 | - device_remove_file(&interface->dev, &dev_attr_output8); | |
651 | + device_remove_file(kit->dev, &dev_attr_output5); | |
652 | + device_remove_file(kit->dev, &dev_attr_output6); | |
653 | + device_remove_file(kit->dev, &dev_attr_output7); | |
654 | + device_remove_file(kit->dev, &dev_attr_output8); | |
627 | 655 | } |
628 | 656 | if (kit->ifkit->outputs == 16) { |
629 | - device_remove_file(&interface->dev, &dev_attr_output9); | |
630 | - device_remove_file(&interface->dev, &dev_attr_output10); | |
631 | - device_remove_file(&interface->dev, &dev_attr_output11); | |
632 | - device_remove_file(&interface->dev, &dev_attr_output12); | |
633 | - device_remove_file(&interface->dev, &dev_attr_output13); | |
634 | - device_remove_file(&interface->dev, &dev_attr_output14); | |
635 | - device_remove_file(&interface->dev, &dev_attr_output15); | |
636 | - device_remove_file(&interface->dev, &dev_attr_output16); | |
657 | + device_remove_file(kit->dev, &dev_attr_output9); | |
658 | + device_remove_file(kit->dev, &dev_attr_output10); | |
659 | + device_remove_file(kit->dev, &dev_attr_output11); | |
660 | + device_remove_file(kit->dev, &dev_attr_output12); | |
661 | + device_remove_file(kit->dev, &dev_attr_output13); | |
662 | + device_remove_file(kit->dev, &dev_attr_output14); | |
663 | + device_remove_file(kit->dev, &dev_attr_output15); | |
664 | + device_remove_file(kit->dev, &dev_attr_output16); | |
637 | 665 | } |
638 | 666 | |
639 | 667 | if (kit->ifkit->inputs >= 4) { |
640 | - device_remove_file(&interface->dev, &dev_attr_input1); | |
641 | - device_remove_file(&interface->dev, &dev_attr_input2); | |
642 | - device_remove_file(&interface->dev, &dev_attr_input3); | |
643 | - device_remove_file(&interface->dev, &dev_attr_input4); | |
668 | + device_remove_file(kit->dev, &dev_attr_input1); | |
669 | + device_remove_file(kit->dev, &dev_attr_input2); | |
670 | + device_remove_file(kit->dev, &dev_attr_input3); | |
671 | + device_remove_file(kit->dev, &dev_attr_input4); | |
644 | 672 | } |
645 | 673 | if (kit->ifkit->inputs >= 8) { |
646 | - device_remove_file(&interface->dev, &dev_attr_input5); | |
647 | - device_remove_file(&interface->dev, &dev_attr_input6); | |
648 | - device_remove_file(&interface->dev, &dev_attr_input7); | |
649 | - device_remove_file(&interface->dev, &dev_attr_input8); | |
674 | + device_remove_file(kit->dev, &dev_attr_input5); | |
675 | + device_remove_file(kit->dev, &dev_attr_input6); | |
676 | + device_remove_file(kit->dev, &dev_attr_input7); | |
677 | + device_remove_file(kit->dev, &dev_attr_input8); | |
650 | 678 | } |
651 | 679 | if (kit->ifkit->inputs == 16) { |
652 | - device_remove_file(&interface->dev, &dev_attr_input9); | |
653 | - device_remove_file(&interface->dev, &dev_attr_input10); | |
654 | - device_remove_file(&interface->dev, &dev_attr_input11); | |
655 | - device_remove_file(&interface->dev, &dev_attr_input12); | |
656 | - device_remove_file(&interface->dev, &dev_attr_input13); | |
657 | - device_remove_file(&interface->dev, &dev_attr_input14); | |
658 | - device_remove_file(&interface->dev, &dev_attr_input15); | |
659 | - device_remove_file(&interface->dev, &dev_attr_input16); | |
680 | + device_remove_file(kit->dev, &dev_attr_input9); | |
681 | + device_remove_file(kit->dev, &dev_attr_input10); | |
682 | + device_remove_file(kit->dev, &dev_attr_input11); | |
683 | + device_remove_file(kit->dev, &dev_attr_input12); | |
684 | + device_remove_file(kit->dev, &dev_attr_input13); | |
685 | + device_remove_file(kit->dev, &dev_attr_input14); | |
686 | + device_remove_file(kit->dev, &dev_attr_input15); | |
687 | + device_remove_file(kit->dev, &dev_attr_input16); | |
660 | 688 | } |
661 | 689 | |
662 | 690 | if (kit->ifkit->sensors >= 4) { |
663 | - device_remove_file(&interface->dev, &dev_attr_sensor1); | |
664 | - device_remove_file(&interface->dev, &dev_attr_sensor2); | |
665 | - device_remove_file(&interface->dev, &dev_attr_sensor3); | |
666 | - device_remove_file(&interface->dev, &dev_attr_sensor4); | |
691 | + device_remove_file(kit->dev, &dev_attr_sensor1); | |
692 | + device_remove_file(kit->dev, &dev_attr_sensor2); | |
693 | + device_remove_file(kit->dev, &dev_attr_sensor3); | |
694 | + device_remove_file(kit->dev, &dev_attr_sensor4); | |
667 | 695 | } |
668 | 696 | if (kit->ifkit->sensors >= 7) { |
669 | - device_remove_file(&interface->dev, &dev_attr_sensor5); | |
670 | - device_remove_file(&interface->dev, &dev_attr_sensor6); | |
671 | - device_remove_file(&interface->dev, &dev_attr_sensor7); | |
697 | + device_remove_file(kit->dev, &dev_attr_sensor5); | |
698 | + device_remove_file(kit->dev, &dev_attr_sensor6); | |
699 | + device_remove_file(kit->dev, &dev_attr_sensor7); | |
672 | 700 | } |
673 | 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 | 704 | if (kit->ifkit->has_lcd) |
677 | - device_remove_file(&interface->dev, &dev_attr_lcd); | |
705 | + device_remove_file(kit->dev, &dev_attr_lcd); | |
678 | 706 | |
707 | + device_unregister(kit->dev); | |
708 | + | |
679 | 709 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
680 | 710 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
681 | 711 | |
682 | 712 | usb_put_dev(kit->udev); |
713 | + clear_bit(kit->dev_no, &device_no); | |
714 | + | |
683 | 715 | kfree(kit); |
684 | 716 | } |
685 | 717 |
drivers/usb/misc/phidgetmotorcontrol.c
... | ... | @@ -15,6 +15,8 @@ |
15 | 15 | #include <linux/module.h> |
16 | 16 | #include <linux/usb.h> |
17 | 17 | |
18 | +#include "phidget.h" | |
19 | + | |
18 | 20 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
19 | 21 | #define DRIVER_DESC "USB PhidgetMotorControl Driver" |
20 | 22 | |
21 | 23 | |
... | ... | @@ -23,9 +25,13 @@ |
23 | 25 | |
24 | 26 | #define URB_INT_SIZE 8 |
25 | 27 | |
28 | +static unsigned long device_no; | |
29 | + | |
26 | 30 | struct motorcontrol { |
27 | 31 | struct usb_device *udev; |
28 | 32 | struct usb_interface *intf; |
33 | + struct device *dev; | |
34 | + int dev_no; | |
29 | 35 | u8 inputs[4]; |
30 | 36 | s8 desired_speed[2]; |
31 | 37 | s8 speed[2]; |
32 | 38 | |
... | ... | @@ -162,14 +168,14 @@ |
162 | 168 | for (i=0; i<4; i++) { |
163 | 169 | if (test_and_clear_bit(i, &mc->input_events)) { |
164 | 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 | 175 | for (i=0; i<2; i++) { |
170 | 176 | if (test_and_clear_bit(i, &mc->speed_events)) { |
171 | 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 | |
176 | 182 | |
... | ... | @@ -181,11 +187,11 @@ |
181 | 187 | } |
182 | 188 | |
183 | 189 | #define show_set_speed(value) \ |
184 | -static ssize_t set_speed##value(struct device *dev, \ | |
185 | - struct device_attribute *attr, const char *buf, size_t count) \ | |
190 | +static ssize_t set_speed##value(struct device *dev, \ | |
191 | + struct device_attribute *attr, \ | |
192 | + const char *buf, size_t count) \ | |
186 | 193 | { \ |
187 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
188 | - struct motorcontrol *mc = usb_get_intfdata(intf); \ | |
194 | + struct motorcontrol *mc = dev_get_drvdata(dev); \ | |
189 | 195 | int speed; \ |
190 | 196 | int retval; \ |
191 | 197 | \ |
192 | 198 | |
... | ... | @@ -202,11 +208,11 @@ |
202 | 208 | return retval ? retval : count; \ |
203 | 209 | } \ |
204 | 210 | \ |
205 | -static ssize_t show_speed##value(struct device *dev, \ | |
206 | - struct device_attribute *attr, char *buf) \ | |
211 | +static ssize_t show_speed##value(struct device *dev, \ | |
212 | + struct device_attribute *attr, \ | |
213 | + char *buf) \ | |
207 | 214 | { \ |
208 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
209 | - struct motorcontrol *mc = usb_get_intfdata(intf); \ | |
215 | + struct motorcontrol *mc = dev_get_drvdata(dev); \ | |
210 | 216 | \ |
211 | 217 | return sprintf(buf, "%d\n", mc->speed[value]); \ |
212 | 218 | } \ |
213 | 219 | |
... | ... | @@ -217,10 +223,10 @@ |
217 | 223 | |
218 | 224 | #define show_set_acceleration(value) \ |
219 | 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); \ | |
223 | - struct motorcontrol *mc = usb_get_intfdata(intf); \ | |
229 | + struct motorcontrol *mc = dev_get_drvdata(dev); \ | |
224 | 230 | int acceleration; \ |
225 | 231 | int retval; \ |
226 | 232 | \ |
227 | 233 | |
... | ... | @@ -237,11 +243,11 @@ |
237 | 243 | return retval ? retval : count; \ |
238 | 244 | } \ |
239 | 245 | \ |
240 | -static ssize_t show_acceleration##value(struct device *dev, \ | |
241 | - struct device_attribute *attr, char *buf) \ | |
246 | +static ssize_t show_acceleration##value(struct device *dev, \ | |
247 | + struct device_attribute *attr, \ | |
248 | + char *buf) \ | |
242 | 249 | { \ |
243 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
244 | - struct motorcontrol *mc = usb_get_intfdata(intf); \ | |
250 | + struct motorcontrol *mc = dev_get_drvdata(dev); \ | |
245 | 251 | \ |
246 | 252 | return sprintf(buf, "%d\n", mc->acceleration[value]); \ |
247 | 253 | } \ |
248 | 254 | |
... | ... | @@ -251,11 +257,11 @@ |
251 | 257 | show_set_acceleration(1); |
252 | 258 | |
253 | 259 | #define show_current(value) \ |
254 | -static ssize_t show_current##value(struct device *dev, \ | |
255 | - struct device_attribute *attr, char *buf) \ | |
260 | +static ssize_t show_current##value(struct device *dev, \ | |
261 | + struct device_attribute *attr, \ | |
262 | + char *buf) \ | |
256 | 263 | { \ |
257 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
258 | - struct motorcontrol *mc = usb_get_intfdata(intf); \ | |
264 | + struct motorcontrol *mc = dev_get_drvdata(dev); \ | |
259 | 265 | \ |
260 | 266 | return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ |
261 | 267 | } \ |
262 | 268 | |
... | ... | @@ -265,11 +271,11 @@ |
265 | 271 | show_current(1); |
266 | 272 | |
267 | 273 | #define show_input(value) \ |
268 | -static ssize_t show_input##value(struct device *dev, \ | |
269 | - struct device_attribute *attr, char *buf) \ | |
274 | +static ssize_t show_input##value(struct device *dev, \ | |
275 | + struct device_attribute *attr, \ | |
276 | + char *buf) \ | |
270 | 277 | { \ |
271 | - struct usb_interface *intf = to_usb_interface(dev); \ | |
272 | - struct motorcontrol *mc = usb_get_intfdata(intf); \ | |
278 | + struct motorcontrol *mc = dev_get_drvdata(dev); \ | |
273 | 279 | \ |
274 | 280 | return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ |
275 | 281 | } \ |
... | ... | @@ -287,6 +293,7 @@ |
287 | 293 | struct usb_endpoint_descriptor *endpoint; |
288 | 294 | struct motorcontrol *mc; |
289 | 295 | int pipe, maxp, rc = -ENOMEM; |
296 | + int bit, value; | |
290 | 297 | |
291 | 298 | interface = intf->cur_altsetting; |
292 | 299 | if (interface->desc.bNumEndpoints != 1) |
... | ... | @@ -306,6 +313,7 @@ |
306 | 313 | if (!mc) |
307 | 314 | goto out; |
308 | 315 | |
316 | + mc->dev_no = -1; | |
309 | 317 | mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma); |
310 | 318 | if (!mc->data) |
311 | 319 | goto out; |
312 | 320 | |
313 | 321 | |
314 | 322 | |
315 | 323 | |
316 | 324 | |
... | ... | @@ -326,26 +334,42 @@ |
326 | 334 | |
327 | 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 | 353 | if (usb_submit_urb(mc->irq, GFP_KERNEL)) { |
330 | 354 | rc = -EIO; |
331 | 355 | goto out; |
332 | 356 | } |
333 | 357 | |
334 | - device_create_file(&intf->dev, &dev_attr_input0); | |
335 | - device_create_file(&intf->dev, &dev_attr_input1); | |
336 | - device_create_file(&intf->dev, &dev_attr_input2); | |
337 | - device_create_file(&intf->dev, &dev_attr_input3); | |
358 | + device_create_file(mc->dev, &dev_attr_input0); | |
359 | + device_create_file(mc->dev, &dev_attr_input1); | |
360 | + device_create_file(mc->dev, &dev_attr_input2); | |
361 | + device_create_file(mc->dev, &dev_attr_input3); | |
338 | 362 | |
339 | - device_create_file(&intf->dev, &dev_attr_speed0); | |
340 | - device_create_file(&intf->dev, &dev_attr_speed1); | |
363 | + device_create_file(mc->dev, &dev_attr_speed0); | |
364 | + device_create_file(mc->dev, &dev_attr_speed1); | |
341 | 365 | |
342 | - device_create_file(&intf->dev, &dev_attr_acceleration0); | |
343 | - device_create_file(&intf->dev, &dev_attr_acceleration1); | |
366 | + device_create_file(mc->dev, &dev_attr_acceleration0); | |
367 | + device_create_file(mc->dev, &dev_attr_acceleration1); | |
344 | 368 | |
345 | - device_create_file(&intf->dev, &dev_attr_current0); | |
346 | - device_create_file(&intf->dev, &dev_attr_current1); | |
369 | + device_create_file(mc->dev, &dev_attr_current0); | |
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 | 374 | return 0; |
351 | 375 | |
... | ... | @@ -355,6 +379,11 @@ |
355 | 379 | usb_free_urb(mc->irq); |
356 | 380 | if (mc->data) |
357 | 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 | 387 | kfree(mc); |
359 | 388 | } |
360 | 389 | |
361 | 390 | |
362 | 391 | |
363 | 392 | |
364 | 393 | |
365 | 394 | |
366 | 395 | |
... | ... | @@ -376,24 +405,27 @@ |
376 | 405 | |
377 | 406 | cancel_delayed_work(&mc->do_notify); |
378 | 407 | |
379 | - device_remove_file(&interface->dev, &dev_attr_input0); | |
380 | - device_remove_file(&interface->dev, &dev_attr_input1); | |
381 | - device_remove_file(&interface->dev, &dev_attr_input2); | |
382 | - device_remove_file(&interface->dev, &dev_attr_input3); | |
408 | + device_remove_file(mc->dev, &dev_attr_input0); | |
409 | + device_remove_file(mc->dev, &dev_attr_input1); | |
410 | + device_remove_file(mc->dev, &dev_attr_input2); | |
411 | + device_remove_file(mc->dev, &dev_attr_input3); | |
383 | 412 | |
384 | - device_remove_file(&interface->dev, &dev_attr_speed0); | |
385 | - device_remove_file(&interface->dev, &dev_attr_speed1); | |
413 | + device_remove_file(mc->dev, &dev_attr_speed0); | |
414 | + device_remove_file(mc->dev, &dev_attr_speed1); | |
386 | 415 | |
387 | - device_remove_file(&interface->dev, &dev_attr_acceleration0); | |
388 | - device_remove_file(&interface->dev, &dev_attr_acceleration1); | |
416 | + device_remove_file(mc->dev, &dev_attr_acceleration0); | |
417 | + device_remove_file(mc->dev, &dev_attr_acceleration1); | |
389 | 418 | |
390 | - device_remove_file(&interface->dev, &dev_attr_current0); | |
391 | - device_remove_file(&interface->dev, &dev_attr_current1); | |
419 | + device_remove_file(mc->dev, &dev_attr_current0); | |
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 | 424 | usb_put_dev(mc->udev); |
425 | + clear_bit(mc->dev_no, &device_no); | |
396 | 426 | kfree(mc); |
427 | + | |
428 | + dev_info(&interface->dev, "USB PhidgetMotorControl detached\n"); | |
397 | 429 | } |
398 | 430 | |
399 | 431 | static struct usb_driver motorcontrol_driver = { |
drivers/usb/misc/phidgetservo.c
... | ... | @@ -15,14 +15,6 @@ |
15 | 15 | * |
16 | 16 | * CAUTION: Generally you should use 0 < degrees < 180 as anything else |
17 | 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 | 20 | #include <linux/kernel.h> |
... | ... | @@ -32,6 +24,8 @@ |
32 | 24 | #include <linux/module.h> |
33 | 25 | #include <linux/usb.h> |
34 | 26 | |
27 | +#include "phidget.h" | |
28 | + | |
35 | 29 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
36 | 30 | #define DRIVER_DESC "USB PhidgetServo Driver" |
37 | 31 | |
38 | 32 | |
... | ... | @@ -70,8 +64,12 @@ |
70 | 64 | |
71 | 65 | MODULE_DEVICE_TABLE(usb, id_table); |
72 | 66 | |
67 | +static int unsigned long device_no; | |
68 | + | |
73 | 69 | struct phidget_servo { |
74 | 70 | struct usb_device *udev; |
71 | + struct device *dev; | |
72 | + int dev_no; | |
75 | 73 | ulong type; |
76 | 74 | int pulse[4]; |
77 | 75 | int degrees[4]; |
78 | 76 | |
79 | 77 | |
... | ... | @@ -203,16 +201,16 @@ |
203 | 201 | } |
204 | 202 | |
205 | 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 | 206 | const char *buf, size_t count) \ |
208 | 207 | { \ |
209 | 208 | int degrees, minutes, retval; \ |
210 | - struct usb_interface *intf = to_usb_interface (dev); \ | |
211 | - struct phidget_servo *servo = usb_get_intfdata (intf); \ | |
209 | + struct phidget_servo *servo = dev_get_drvdata(dev); \ | |
212 | 210 | \ |
213 | 211 | minutes = 0; \ |
214 | 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 | 214 | return -EINVAL; \ |
217 | 215 | } \ |
218 | 216 | \ |
219 | 217 | |
220 | 218 | |
221 | 219 | |
222 | 220 | |
... | ... | @@ -220,21 +218,22 @@ |
220 | 218 | return -EINVAL; \ |
221 | 219 | \ |
222 | 220 | if (servo->type & SERVO_VERSION_30) \ |
223 | - retval = change_position_v30 (servo, value, degrees, \ | |
221 | + retval = change_position_v30(servo, value, degrees, \ | |
224 | 222 | minutes); \ |
225 | 223 | else \ |
226 | - retval = change_position_v20 (servo, value, degrees, \ | |
224 | + retval = change_position_v20(servo, value, degrees, \ | |
227 | 225 | minutes); \ |
228 | 226 | \ |
229 | 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); \ | |
235 | - struct phidget_servo *servo = usb_get_intfdata (intf); \ | |
234 | + struct phidget_servo *servo = dev_get_drvdata(dev); \ | |
236 | 235 | \ |
237 | - return sprintf (buf, "%d.%02d\n", servo->degrees[value], \ | |
236 | + return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ | |
238 | 237 | servo->minutes[value]); \ |
239 | 238 | } \ |
240 | 239 | static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ |
... | ... | @@ -250,6 +249,7 @@ |
250 | 249 | { |
251 | 250 | struct usb_device *udev = interface_to_usbdev(interface); |
252 | 251 | struct phidget_servo *dev; |
252 | + int bit, value; | |
253 | 253 | |
254 | 254 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); |
255 | 255 | if (dev == NULL) { |
256 | 256 | |
257 | 257 | |
... | ... | @@ -261,18 +261,33 @@ |
261 | 261 | dev->type = id->driver_info; |
262 | 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 | 280 | if (dev->type & SERVO_COUNT_QUAD) { |
266 | - device_create_file(&interface->dev, &dev_attr_servo1); | |
267 | - device_create_file(&interface->dev, &dev_attr_servo2); | |
268 | - device_create_file(&interface->dev, &dev_attr_servo3); | |
281 | + device_create_file(dev->dev, &dev_attr_servo1); | |
282 | + device_create_file(dev->dev, &dev_attr_servo2); | |
283 | + device_create_file(dev->dev, &dev_attr_servo3); | |
269 | 284 | } |
270 | 285 | |
271 | 286 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", |
272 | 287 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, |
273 | 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 | 291 | dev_info(&interface->dev, |
277 | 292 | "WARNING: v2.0 not tested! Please report if it works.\n"); |
278 | 293 | |
279 | 294 | |
280 | 295 | |
281 | 296 | |
... | ... | @@ -287,19 +302,21 @@ |
287 | 302 | dev = usb_get_intfdata(interface); |
288 | 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 | 306 | if (dev->type & SERVO_COUNT_QUAD) { |
292 | - device_remove_file(&interface->dev, &dev_attr_servo1); | |
293 | - device_remove_file(&interface->dev, &dev_attr_servo2); | |
294 | - device_remove_file(&interface->dev, &dev_attr_servo3); | |
307 | + device_remove_file(dev->dev, &dev_attr_servo1); | |
308 | + device_remove_file(dev->dev, &dev_attr_servo2); | |
309 | + device_remove_file(dev->dev, &dev_attr_servo3); | |
295 | 310 | } |
296 | 311 | |
312 | + device_unregister(dev->dev); | |
297 | 313 | usb_put_dev(dev->udev); |
298 | 314 | |
299 | 315 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", |
300 | 316 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, |
301 | 317 | dev->type & SERVO_VERSION_30 ? 3 : 2); |
302 | 318 | |
319 | + clear_bit(dev->dev_no, &device_no); | |
303 | 320 | kfree(dev); |
304 | 321 | } |
305 | 322 |