diff options
author | Sean Young <sean@mess.org> | 2006-08-11 05:28:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:49 -0400 |
commit | da308e8da700637d6271dddda08128094691b980 (patch) | |
tree | 07d132503e754915db98171cd00e106c27138b64 /drivers/usb/misc | |
parent | 912b24c333843514ff77ed88961c6945f0f286ce (diff) |
USB: Phidgets should check create_device_file() return value
device_create_file() could fail, add proper error paths for this condition.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/phidgetkit.c | 238 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetmotorcontrol.c | 83 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetservo.c | 74 |
3 files changed, 199 insertions, 196 deletions
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 3f508957def9..9a8d137d39f9 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
@@ -193,8 +193,11 @@ static ssize_t lcd_line_##number(struct device *dev, \ | |||
193 | struct interfacekit *kit = dev_get_drvdata(dev); \ | 193 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
194 | change_string(kit, buf, number - 1); \ | 194 | change_string(kit, buf, number - 1); \ |
195 | return count; \ | 195 | return count; \ |
196 | } \ | 196 | } |
197 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); | 197 | |
198 | #define lcd_line_attr(number) \ | ||
199 | __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) | ||
200 | |||
198 | set_lcd_line(1); | 201 | set_lcd_line(1); |
199 | set_lcd_line(2); | 202 | set_lcd_line(2); |
200 | 203 | ||
@@ -232,15 +235,22 @@ exit: | |||
232 | kfree(buffer); | 235 | kfree(buffer); |
233 | return retval; | 236 | return retval; |
234 | } | 237 | } |
235 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); | 238 | |
239 | static struct device_attribute dev_lcd_line_attrs[] = { | ||
240 | lcd_line_attr(1), | ||
241 | lcd_line_attr(2), | ||
242 | __ATTR(backlight, S_IWUGO, NULL, set_backlight) | ||
243 | }; | ||
236 | 244 | ||
237 | static void remove_lcd_files(struct interfacekit *kit) | 245 | static void remove_lcd_files(struct interfacekit *kit) |
238 | { | 246 | { |
247 | int i; | ||
248 | |||
239 | if (kit->lcd_files_on) { | 249 | if (kit->lcd_files_on) { |
240 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 250 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
241 | device_remove_file(kit->dev, &dev_attr_lcd_line_1); | 251 | |
242 | device_remove_file(kit->dev, &dev_attr_lcd_line_2); | 252 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) |
243 | device_remove_file(kit->dev, &dev_attr_backlight); | 253 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); |
244 | } | 254 | } |
245 | } | 255 | } |
246 | 256 | ||
@@ -248,6 +258,7 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
248 | { | 258 | { |
249 | struct interfacekit *kit = dev_get_drvdata(dev); | 259 | struct interfacekit *kit = dev_get_drvdata(dev); |
250 | int enable; | 260 | int enable; |
261 | int i, rc; | ||
251 | 262 | ||
252 | if (kit->ifkit->has_lcd == 0) | 263 | if (kit->ifkit->has_lcd == 0) |
253 | return -ENODEV; | 264 | return -ENODEV; |
@@ -258,9 +269,12 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
258 | if (enable) { | 269 | if (enable) { |
259 | if (!kit->lcd_files_on) { | 270 | if (!kit->lcd_files_on) { |
260 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); | 271 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); |
261 | device_create_file(kit->dev, &dev_attr_lcd_line_1); | 272 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) { |
262 | device_create_file(kit->dev, &dev_attr_lcd_line_2); | 273 | rc = device_create_file(kit->dev, |
263 | device_create_file(kit->dev, &dev_attr_backlight); | 274 | &dev_lcd_line_attrs[i]); |
275 | if (rc) | ||
276 | goto out; | ||
277 | } | ||
264 | kit->lcd_files_on = 1; | 278 | kit->lcd_files_on = 1; |
265 | } | 279 | } |
266 | } else { | 280 | } else { |
@@ -271,7 +285,13 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
271 | } | 285 | } |
272 | 286 | ||
273 | return count; | 287 | return count; |
288 | out: | ||
289 | while (i-- > 0) | ||
290 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); | ||
291 | |||
292 | return rc; | ||
274 | } | 293 | } |
294 | |||
275 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); | 295 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); |
276 | 296 | ||
277 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | 297 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) |
@@ -403,9 +423,12 @@ static ssize_t show_output##value(struct device *dev, \ | |||
403 | struct interfacekit *kit = dev_get_drvdata(dev); \ | 423 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
404 | \ | 424 | \ |
405 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ | 425 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
406 | } \ | 426 | } |
407 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ | 427 | |
408 | show_output##value, set_output##value); | 428 | #define output_attr(value) \ |
429 | __ATTR(output##value, S_IWUGO | S_IRUGO, \ | ||
430 | show_output##value, set_output##value) | ||
431 | |||
409 | show_set_output(1); | 432 | show_set_output(1); |
410 | show_set_output(2); | 433 | show_set_output(2); |
411 | show_set_output(3); | 434 | show_set_output(3); |
@@ -423,14 +446,24 @@ show_set_output(14); | |||
423 | show_set_output(15); | 446 | show_set_output(15); |
424 | show_set_output(16); | 447 | show_set_output(16); |
425 | 448 | ||
449 | static struct device_attribute dev_output_attrs[] = { | ||
450 | output_attr(1), output_attr(2), output_attr(3), output_attr(4), | ||
451 | output_attr(5), output_attr(6), output_attr(7), output_attr(8), | ||
452 | output_attr(9), output_attr(10), output_attr(11), output_attr(12), | ||
453 | output_attr(13), output_attr(14), output_attr(15), output_attr(16) | ||
454 | }; | ||
455 | |||
426 | #define show_input(value) \ | 456 | #define show_input(value) \ |
427 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 457 | static ssize_t show_input##value(struct device *dev, \ |
458 | struct device_attribute *attr, char *buf) \ | ||
428 | { \ | 459 | { \ |
429 | struct interfacekit *kit = dev_get_drvdata(dev); \ | 460 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
430 | \ | 461 | \ |
431 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ | 462 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
432 | } \ | 463 | } |
433 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); | 464 | |
465 | #define input_attr(value) \ | ||
466 | __ATTR(input##value, S_IRUGO, show_input##value, NULL) | ||
434 | 467 | ||
435 | show_input(1); | 468 | show_input(1); |
436 | show_input(2); | 469 | show_input(2); |
@@ -449,6 +482,13 @@ show_input(14); | |||
449 | show_input(15); | 482 | show_input(15); |
450 | show_input(16); | 483 | show_input(16); |
451 | 484 | ||
485 | static struct device_attribute dev_input_attrs[] = { | ||
486 | input_attr(1), input_attr(2), input_attr(3), input_attr(4), | ||
487 | input_attr(5), input_attr(6), input_attr(7), input_attr(8), | ||
488 | input_attr(9), input_attr(10), input_attr(11), input_attr(12), | ||
489 | input_attr(13), input_attr(14), input_attr(15), input_attr(16) | ||
490 | }; | ||
491 | |||
452 | #define show_sensor(value) \ | 492 | #define show_sensor(value) \ |
453 | static ssize_t show_sensor##value(struct device *dev, \ | 493 | static ssize_t show_sensor##value(struct device *dev, \ |
454 | struct device_attribute *attr, \ | 494 | struct device_attribute *attr, \ |
@@ -457,8 +497,10 @@ static ssize_t show_sensor##value(struct device *dev, \ | |||
457 | struct interfacekit *kit = dev_get_drvdata(dev); \ | 497 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
458 | \ | 498 | \ |
459 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ | 499 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
460 | } \ | 500 | } |
461 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); | 501 | |
502 | #define sensor_attr(value) \ | ||
503 | __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL) | ||
462 | 504 | ||
463 | show_sensor(1); | 505 | show_sensor(1); |
464 | show_sensor(2); | 506 | show_sensor(2); |
@@ -469,6 +511,11 @@ show_sensor(6); | |||
469 | show_sensor(7); | 511 | show_sensor(7); |
470 | show_sensor(8); | 512 | show_sensor(8); |
471 | 513 | ||
514 | static struct device_attribute dev_sensor_attrs[] = { | ||
515 | sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4), | ||
516 | sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8) | ||
517 | }; | ||
518 | |||
472 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) | 519 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) |
473 | { | 520 | { |
474 | struct usb_device *dev = interface_to_usbdev(intf); | 521 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -477,7 +524,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
477 | struct interfacekit *kit; | 524 | struct interfacekit *kit; |
478 | struct driver_interfacekit *ifkit; | 525 | struct driver_interfacekit *ifkit; |
479 | int pipe, maxp, rc = -ENOMEM; | 526 | int pipe, maxp, rc = -ENOMEM; |
480 | int bit, value; | 527 | int bit, value, i; |
481 | 528 | ||
482 | ifkit = (struct driver_interfacekit *)id->driver_info; | 529 | ifkit = (struct driver_interfacekit *)id->driver_info; |
483 | if (!ifkit) | 530 | if (!ifkit) |
@@ -541,74 +588,49 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
541 | goto out; | 588 | goto out; |
542 | } | 589 | } |
543 | 590 | ||
544 | if (ifkit->outputs >= 4) { | 591 | for (i=0; i<ifkit->outputs; i++ ) { |
545 | device_create_file(kit->dev, &dev_attr_output1); | 592 | rc = device_create_file(kit->dev, &dev_output_attrs[i]); |
546 | device_create_file(kit->dev, &dev_attr_output2); | 593 | if (rc) |
547 | device_create_file(kit->dev, &dev_attr_output3); | 594 | goto out2; |
548 | device_create_file(kit->dev, &dev_attr_output4); | ||
549 | } | ||
550 | if (ifkit->outputs >= 8) { | ||
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); | ||
555 | } | ||
556 | if (ifkit->outputs == 16) { | ||
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); | ||
565 | } | 595 | } |
566 | 596 | ||
567 | if (ifkit->inputs >= 4) { | 597 | for (i=0; i<ifkit->inputs; i++ ) { |
568 | device_create_file(kit->dev, &dev_attr_input1); | 598 | rc = device_create_file(kit->dev, &dev_input_attrs[i]); |
569 | device_create_file(kit->dev, &dev_attr_input2); | 599 | if (rc) |
570 | device_create_file(kit->dev, &dev_attr_input3); | 600 | goto out3; |
571 | device_create_file(kit->dev, &dev_attr_input4); | ||
572 | } | ||
573 | if (ifkit->inputs >= 8) { | ||
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); | ||
578 | } | ||
579 | if (ifkit->inputs == 16) { | ||
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); | ||
588 | } | 601 | } |
589 | 602 | ||
590 | if (ifkit->sensors >= 4) { | 603 | for (i=0; i<ifkit->sensors; i++ ) { |
591 | device_create_file(kit->dev, &dev_attr_sensor1); | 604 | rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); |
592 | device_create_file(kit->dev, &dev_attr_sensor2); | 605 | if (rc) |
593 | device_create_file(kit->dev, &dev_attr_sensor3); | 606 | goto out4; |
594 | device_create_file(kit->dev, &dev_attr_sensor4); | ||
595 | } | ||
596 | if (ifkit->sensors >= 7) { | ||
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); | ||
600 | } | 607 | } |
601 | if (ifkit->sensors == 8) | ||
602 | device_create_file(kit->dev, &dev_attr_sensor8); | ||
603 | 608 | ||
604 | if (ifkit->has_lcd) | 609 | if (ifkit->has_lcd) { |
605 | device_create_file(kit->dev, &dev_attr_lcd); | 610 | rc = device_create_file(kit->dev, &dev_attr_lcd); |
611 | if (rc) | ||
612 | goto out4; | ||
613 | |||
614 | } | ||
606 | 615 | ||
607 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", | 616 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", |
608 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 617 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
609 | 618 | ||
610 | return 0; | 619 | return 0; |
611 | 620 | ||
621 | out4: | ||
622 | while (i-- > 0) | ||
623 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); | ||
624 | |||
625 | i = ifkit->inputs; | ||
626 | out3: | ||
627 | while (i-- > 0) | ||
628 | device_remove_file(kit->dev, &dev_input_attrs[i]); | ||
629 | |||
630 | i = ifkit->outputs; | ||
631 | out2: | ||
632 | while (i-- > 0) | ||
633 | device_remove_file(kit->dev, &dev_output_attrs[i]); | ||
612 | out: | 634 | out: |
613 | if (kit) { | 635 | if (kit) { |
614 | if (kit->irq) | 636 | if (kit->irq) |
@@ -629,6 +651,7 @@ out: | |||
629 | static void interfacekit_disconnect(struct usb_interface *interface) | 651 | static void interfacekit_disconnect(struct usb_interface *interface) |
630 | { | 652 | { |
631 | struct interfacekit *kit; | 653 | struct interfacekit *kit; |
654 | int i; | ||
632 | 655 | ||
633 | kit = usb_get_intfdata(interface); | 656 | kit = usb_get_intfdata(interface); |
634 | usb_set_intfdata(interface, NULL); | 657 | usb_set_intfdata(interface, NULL); |
@@ -641,68 +664,19 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
641 | 664 | ||
642 | cancel_delayed_work(&kit->do_notify); | 665 | cancel_delayed_work(&kit->do_notify); |
643 | 666 | ||
644 | if (kit->ifkit->outputs >= 4) { | 667 | for (i=0; i<kit->ifkit->outputs; i++) |
645 | device_remove_file(kit->dev, &dev_attr_output1); | 668 | device_remove_file(kit->dev, &dev_output_attrs[i]); |
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); | ||
649 | } | ||
650 | if (kit->ifkit->outputs >= 8) { | ||
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); | ||
655 | } | ||
656 | if (kit->ifkit->outputs == 16) { | ||
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); | ||
665 | } | ||
666 | 669 | ||
667 | if (kit->ifkit->inputs >= 4) { | 670 | for (i=0; i<kit->ifkit->inputs; i++) |
668 | device_remove_file(kit->dev, &dev_attr_input1); | 671 | device_remove_file(kit->dev, &dev_input_attrs[i]); |
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); | ||
672 | } | ||
673 | if (kit->ifkit->inputs >= 8) { | ||
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); | ||
678 | } | ||
679 | if (kit->ifkit->inputs == 16) { | ||
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); | ||
688 | } | ||
689 | 672 | ||
690 | if (kit->ifkit->sensors >= 4) { | 673 | for (i=0; i<kit->ifkit->sensors; i++) |
691 | device_remove_file(kit->dev, &dev_attr_sensor1); | 674 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); |
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); | ||
695 | } | ||
696 | if (kit->ifkit->sensors >= 7) { | ||
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); | ||
700 | } | ||
701 | if (kit->ifkit->sensors == 8) | ||
702 | device_remove_file(kit->dev, &dev_attr_sensor8); | ||
703 | 675 | ||
704 | if (kit->ifkit->has_lcd) | 676 | if (kit->ifkit->has_lcd) { |
705 | device_remove_file(kit->dev, &dev_attr_lcd); | 677 | device_remove_file(kit->dev, &dev_attr_lcd); |
678 | remove_lcd_files(kit); | ||
679 | } | ||
706 | 680 | ||
707 | device_unregister(kit->dev); | 681 | device_unregister(kit->dev); |
708 | 682 | ||
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index d9ac7f97f8c8..6b59b620d616 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c | |||
@@ -215,9 +215,12 @@ static ssize_t show_speed##value(struct device *dev, \ | |||
215 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | 215 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
216 | \ | 216 | \ |
217 | return sprintf(buf, "%d\n", mc->speed[value]); \ | 217 | return sprintf(buf, "%d\n", mc->speed[value]); \ |
218 | } \ | 218 | } |
219 | static DEVICE_ATTR(speed##value, S_IWUGO | S_IRUGO, \ | 219 | |
220 | show_speed##value, set_speed##value); | 220 | #define speed_attr(value) \ |
221 | __ATTR(speed##value, S_IWUGO | S_IRUGO, \ | ||
222 | show_speed##value, set_speed##value) | ||
223 | |||
221 | show_set_speed(0); | 224 | show_set_speed(0); |
222 | show_set_speed(1); | 225 | show_set_speed(1); |
223 | 226 | ||
@@ -250,9 +253,12 @@ static ssize_t show_acceleration##value(struct device *dev, \ | |||
250 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | 253 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
251 | \ | 254 | \ |
252 | return sprintf(buf, "%d\n", mc->acceleration[value]); \ | 255 | return sprintf(buf, "%d\n", mc->acceleration[value]); \ |
253 | } \ | 256 | } |
254 | static DEVICE_ATTR(acceleration##value, S_IWUGO | S_IRUGO, \ | 257 | |
255 | show_acceleration##value, set_acceleration##value); | 258 | #define acceleration_attr(value) \ |
259 | __ATTR(acceleration##value, S_IWUGO | S_IRUGO, \ | ||
260 | show_acceleration##value, set_acceleration##value) | ||
261 | |||
256 | show_set_acceleration(0); | 262 | show_set_acceleration(0); |
257 | show_set_acceleration(1); | 263 | show_set_acceleration(1); |
258 | 264 | ||
@@ -264,8 +270,10 @@ static ssize_t show_current##value(struct device *dev, \ | |||
264 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | 270 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
265 | \ | 271 | \ |
266 | return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ | 272 | return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ |
267 | } \ | 273 | } |
268 | static DEVICE_ATTR(current##value, S_IRUGO, show_current##value, NULL); | 274 | |
275 | #define current_attr(value) \ | ||
276 | __ATTR(current##value, S_IRUGO, show_current##value, NULL) | ||
269 | 277 | ||
270 | show_current(0); | 278 | show_current(0); |
271 | show_current(1); | 279 | show_current(1); |
@@ -278,14 +286,29 @@ static ssize_t show_input##value(struct device *dev, \ | |||
278 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | 286 | struct motorcontrol *mc = dev_get_drvdata(dev); \ |
279 | \ | 287 | \ |
280 | return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ | 288 | return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ |
281 | } \ | 289 | } |
282 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); | 290 | |
291 | #define input_attr(value) \ | ||
292 | __ATTR(input##value, S_IRUGO, show_input##value, NULL) | ||
283 | 293 | ||
284 | show_input(0); | 294 | show_input(0); |
285 | show_input(1); | 295 | show_input(1); |
286 | show_input(2); | 296 | show_input(2); |
287 | show_input(3); | 297 | show_input(3); |
288 | 298 | ||
299 | static struct device_attribute dev_attrs[] = { | ||
300 | input_attr(0), | ||
301 | input_attr(1), | ||
302 | input_attr(2), | ||
303 | input_attr(3), | ||
304 | speed_attr(0), | ||
305 | speed_attr(1), | ||
306 | acceleration_attr(0), | ||
307 | acceleration_attr(1), | ||
308 | current_attr(0), | ||
309 | current_attr(1) | ||
310 | }; | ||
311 | |||
289 | static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) | 312 | static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) |
290 | { | 313 | { |
291 | struct usb_device *dev = interface_to_usbdev(intf); | 314 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -293,7 +316,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic | |||
293 | struct usb_endpoint_descriptor *endpoint; | 316 | struct usb_endpoint_descriptor *endpoint; |
294 | struct motorcontrol *mc; | 317 | struct motorcontrol *mc; |
295 | int pipe, maxp, rc = -ENOMEM; | 318 | int pipe, maxp, rc = -ENOMEM; |
296 | int bit, value; | 319 | int bit, value, i; |
297 | 320 | ||
298 | interface = intf->cur_altsetting; | 321 | interface = intf->cur_altsetting; |
299 | if (interface->desc.bNumEndpoints != 1) | 322 | if (interface->desc.bNumEndpoints != 1) |
@@ -355,24 +378,18 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic | |||
355 | goto out; | 378 | goto out; |
356 | } | 379 | } |
357 | 380 | ||
358 | device_create_file(mc->dev, &dev_attr_input0); | 381 | for (i=0; i<ARRAY_SIZE(dev_attrs); i++) { |
359 | device_create_file(mc->dev, &dev_attr_input1); | 382 | rc = device_create_file(mc->dev, &dev_attrs[i]); |
360 | device_create_file(mc->dev, &dev_attr_input2); | 383 | if (rc) |
361 | device_create_file(mc->dev, &dev_attr_input3); | 384 | goto out2; |
362 | 385 | } | |
363 | device_create_file(mc->dev, &dev_attr_speed0); | ||
364 | device_create_file(mc->dev, &dev_attr_speed1); | ||
365 | |||
366 | device_create_file(mc->dev, &dev_attr_acceleration0); | ||
367 | device_create_file(mc->dev, &dev_attr_acceleration1); | ||
368 | |||
369 | device_create_file(mc->dev, &dev_attr_current0); | ||
370 | device_create_file(mc->dev, &dev_attr_current1); | ||
371 | 386 | ||
372 | dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); | 387 | dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); |
373 | 388 | ||
374 | return 0; | 389 | return 0; |
375 | 390 | out2: | |
391 | while (i-- > 0) | ||
392 | device_remove_file(mc->dev, &dev_attrs[i]); | ||
376 | out: | 393 | out: |
377 | if (mc) { | 394 | if (mc) { |
378 | if (mc->irq) | 395 | if (mc->irq) |
@@ -393,6 +410,7 @@ out: | |||
393 | static void motorcontrol_disconnect(struct usb_interface *interface) | 410 | static void motorcontrol_disconnect(struct usb_interface *interface) |
394 | { | 411 | { |
395 | struct motorcontrol *mc; | 412 | struct motorcontrol *mc; |
413 | int i; | ||
396 | 414 | ||
397 | mc = usb_get_intfdata(interface); | 415 | mc = usb_get_intfdata(interface); |
398 | usb_set_intfdata(interface, NULL); | 416 | usb_set_intfdata(interface, NULL); |
@@ -405,19 +423,8 @@ static void motorcontrol_disconnect(struct usb_interface *interface) | |||
405 | 423 | ||
406 | cancel_delayed_work(&mc->do_notify); | 424 | cancel_delayed_work(&mc->do_notify); |
407 | 425 | ||
408 | device_remove_file(mc->dev, &dev_attr_input0); | 426 | for (i=0; i<ARRAY_SIZE(dev_attrs); i++) |
409 | device_remove_file(mc->dev, &dev_attr_input1); | 427 | device_remove_file(mc->dev, &dev_attrs[i]); |
410 | device_remove_file(mc->dev, &dev_attr_input2); | ||
411 | device_remove_file(mc->dev, &dev_attr_input3); | ||
412 | |||
413 | device_remove_file(mc->dev, &dev_attr_speed0); | ||
414 | device_remove_file(mc->dev, &dev_attr_speed1); | ||
415 | |||
416 | device_remove_file(mc->dev, &dev_attr_acceleration0); | ||
417 | device_remove_file(mc->dev, &dev_attr_acceleration1); | ||
418 | |||
419 | device_remove_file(mc->dev, &dev_attr_current0); | ||
420 | device_remove_file(mc->dev, &dev_attr_current1); | ||
421 | 428 | ||
422 | device_unregister(mc->dev); | 429 | device_unregister(mc->dev); |
423 | 430 | ||
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index 66be9513fd6f..7163f05c5b27 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * USB PhidgetServo driver 1.0 | 2 | * USB PhidgetServo driver 1.0 |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Sean Young <sean@mess.org> | 4 | * Copyright (C) 2004, 2006 Sean Young <sean@mess.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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 | 7 | * it under the terms of the GNU General Public License as published by |
@@ -235,86 +235,108 @@ static ssize_t show_servo##value (struct device *dev, \ | |||
235 | \ | 235 | \ |
236 | return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ | 236 | return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ |
237 | servo->minutes[value]); \ | 237 | servo->minutes[value]); \ |
238 | } \ | 238 | } |
239 | static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ | ||
240 | show_servo##value, set_servo##value); | ||
241 | 239 | ||
240 | #define servo_attr(value) \ | ||
241 | __ATTR(servo##value, S_IWUGO | S_IRUGO, \ | ||
242 | show_servo##value, set_servo##value) | ||
242 | show_set(0); | 243 | show_set(0); |
243 | show_set(1); | 244 | show_set(1); |
244 | show_set(2); | 245 | show_set(2); |
245 | show_set(3); | 246 | show_set(3); |
246 | 247 | ||
248 | static struct device_attribute dev_attrs[] = { | ||
249 | servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3) | ||
250 | }; | ||
251 | |||
247 | static int | 252 | static int |
248 | servo_probe(struct usb_interface *interface, const struct usb_device_id *id) | 253 | servo_probe(struct usb_interface *interface, const struct usb_device_id *id) |
249 | { | 254 | { |
250 | struct usb_device *udev = interface_to_usbdev(interface); | 255 | struct usb_device *udev = interface_to_usbdev(interface); |
251 | struct phidget_servo *dev; | 256 | struct phidget_servo *dev; |
252 | int bit, value; | 257 | int bit, value, rc; |
258 | int servo_count, i; | ||
253 | 259 | ||
254 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); | 260 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); |
255 | if (dev == NULL) { | 261 | if (dev == NULL) { |
256 | dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); | 262 | dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); |
257 | return -ENOMEM; | 263 | rc = -ENOMEM; |
264 | goto out; | ||
258 | } | 265 | } |
259 | 266 | ||
260 | dev->udev = usb_get_dev(udev); | 267 | dev->udev = usb_get_dev(udev); |
261 | dev->type = id->driver_info; | 268 | dev->type = id->driver_info; |
269 | dev->dev_no = -1; | ||
262 | usb_set_intfdata(interface, dev); | 270 | usb_set_intfdata(interface, dev); |
263 | 271 | ||
264 | do { | 272 | do { |
265 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | 273 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); |
266 | value = test_and_set_bit(bit, &device_no); | 274 | value = test_and_set_bit(bit, &device_no); |
267 | } while(value); | 275 | } while (value); |
268 | dev->dev_no = bit; | 276 | dev->dev_no = bit; |
269 | 277 | ||
270 | dev->dev = device_create(phidget_class, &dev->udev->dev, 0, | 278 | dev->dev = device_create(phidget_class, &dev->udev->dev, 0, |
271 | "servo%d", dev->dev_no); | 279 | "servo%d", dev->dev_no); |
272 | if (IS_ERR(dev->dev)) { | 280 | if (IS_ERR(dev->dev)) { |
273 | int rc = PTR_ERR(dev->dev); | 281 | rc = PTR_ERR(dev->dev); |
274 | clear_bit(dev->dev_no, &device_no); | 282 | dev->dev = NULL; |
275 | kfree(dev); | 283 | goto out; |
276 | return rc; | ||
277 | } | 284 | } |
278 | 285 | ||
279 | device_create_file(dev->dev, &dev_attr_servo0); | 286 | servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; |
280 | if (dev->type & SERVO_COUNT_QUAD) { | 287 | |
281 | device_create_file(dev->dev, &dev_attr_servo1); | 288 | for (i=0; i<servo_count; i++) { |
282 | device_create_file(dev->dev, &dev_attr_servo2); | 289 | rc = device_create_file(dev->dev, &dev_attrs[i]); |
283 | device_create_file(dev->dev, &dev_attr_servo3); | 290 | if (rc) |
291 | goto out2; | ||
284 | } | 292 | } |
285 | 293 | ||
286 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", | 294 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", |
287 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, | 295 | servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); |
288 | dev->type & SERVO_VERSION_30 ? 3 : 2); | ||
289 | 296 | ||
290 | if (!(dev->type & SERVO_VERSION_30)) | 297 | if (!(dev->type & SERVO_VERSION_30)) |
291 | dev_info(&interface->dev, | 298 | dev_info(&interface->dev, |
292 | "WARNING: v2.0 not tested! Please report if it works.\n"); | 299 | "WARNING: v2.0 not tested! Please report if it works.\n"); |
293 | 300 | ||
294 | return 0; | 301 | return 0; |
302 | out2: | ||
303 | while (i-- > 0) | ||
304 | device_remove_file(dev->dev, &dev_attrs[i]); | ||
305 | out: | ||
306 | if (dev) { | ||
307 | if (dev->dev) | ||
308 | device_unregister(dev->dev); | ||
309 | if (dev->dev_no >= 0) | ||
310 | clear_bit(dev->dev_no, &device_no); | ||
311 | |||
312 | kfree(dev); | ||
313 | } | ||
314 | |||
315 | return rc; | ||
295 | } | 316 | } |
296 | 317 | ||
297 | static void | 318 | static void |
298 | servo_disconnect(struct usb_interface *interface) | 319 | servo_disconnect(struct usb_interface *interface) |
299 | { | 320 | { |
300 | struct phidget_servo *dev; | 321 | struct phidget_servo *dev; |
322 | int servo_count, i; | ||
301 | 323 | ||
302 | dev = usb_get_intfdata(interface); | 324 | dev = usb_get_intfdata(interface); |
303 | usb_set_intfdata(interface, NULL); | 325 | usb_set_intfdata(interface, NULL); |
304 | 326 | ||
305 | device_remove_file(dev->dev, &dev_attr_servo0); | 327 | if (!dev) |
306 | if (dev->type & SERVO_COUNT_QUAD) { | 328 | return; |
307 | device_remove_file(dev->dev, &dev_attr_servo1); | 329 | |
308 | device_remove_file(dev->dev, &dev_attr_servo2); | 330 | servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; |
309 | device_remove_file(dev->dev, &dev_attr_servo3); | 331 | |
310 | } | 332 | for (i=0; i<servo_count; i++) |
333 | device_remove_file(dev->dev, &dev_attrs[i]); | ||
311 | 334 | ||
312 | device_unregister(dev->dev); | 335 | device_unregister(dev->dev); |
313 | usb_put_dev(dev->udev); | 336 | usb_put_dev(dev->udev); |
314 | 337 | ||
315 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", | 338 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", |
316 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, | 339 | servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); |
317 | dev->type & SERVO_VERSION_30 ? 3 : 2); | ||
318 | 340 | ||
319 | clear_bit(dev->dev_no, &device_no); | 341 | clear_bit(dev->dev_no, &device_no); |
320 | kfree(dev); | 342 | kfree(dev); |