aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2006-08-11 05:28:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:49 -0400
commitda308e8da700637d6271dddda08128094691b980 (patch)
tree07d132503e754915db98171cd00e106c27138b64 /drivers/usb/misc
parent912b24c333843514ff77ed88961c6945f0f286ce (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.c238
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c83
-rw-r--r--drivers/usb/misc/phidgetservo.c74
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}
197static 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
198set_lcd_line(1); 201set_lcd_line(1);
199set_lcd_line(2); 202set_lcd_line(2);
200 203
@@ -232,15 +235,22 @@ exit:
232 kfree(buffer); 235 kfree(buffer);
233 return retval; 236 return retval;
234} 237}
235static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); 238
239static 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
237static void remove_lcd_files(struct interfacekit *kit) 245static 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;
288out:
289 while (i-- > 0)
290 device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
291
292 return rc;
274} 293}
294
275static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); 295static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
276 296
277static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) 297static 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}
407static 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
409show_set_output(1); 432show_set_output(1);
410show_set_output(2); 433show_set_output(2);
411show_set_output(3); 434show_set_output(3);
@@ -423,14 +446,24 @@ show_set_output(14);
423show_set_output(15); 446show_set_output(15);
424show_set_output(16); 447show_set_output(16);
425 448
449static 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) \
427static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ 457static 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}
433static 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
435show_input(1); 468show_input(1);
436show_input(2); 469show_input(2);
@@ -449,6 +482,13 @@ show_input(14);
449show_input(15); 482show_input(15);
450show_input(16); 483show_input(16);
451 484
485static 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) \
453static ssize_t show_sensor##value(struct device *dev, \ 493static 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}
461static 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
463show_sensor(1); 505show_sensor(1);
464show_sensor(2); 506show_sensor(2);
@@ -469,6 +511,11 @@ show_sensor(6);
469show_sensor(7); 511show_sensor(7);
470show_sensor(8); 512show_sensor(8);
471 513
514static 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
472static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) 519static 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
621out4:
622 while (i-- > 0)
623 device_remove_file(kit->dev, &dev_sensor_attrs[i]);
624
625 i = ifkit->inputs;
626out3:
627 while (i-- > 0)
628 device_remove_file(kit->dev, &dev_input_attrs[i]);
629
630 i = ifkit->outputs;
631out2:
632 while (i-- > 0)
633 device_remove_file(kit->dev, &dev_output_attrs[i]);
612out: 634out:
613 if (kit) { 635 if (kit) {
614 if (kit->irq) 636 if (kit->irq)
@@ -629,6 +651,7 @@ out:
629static void interfacekit_disconnect(struct usb_interface *interface) 651static 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}
219static 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
221show_set_speed(0); 224show_set_speed(0);
222show_set_speed(1); 225show_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}
254static 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
256show_set_acceleration(0); 262show_set_acceleration(0);
257show_set_acceleration(1); 263show_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}
268static 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
270show_current(0); 278show_current(0);
271show_current(1); 279show_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}
282static 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
284show_input(0); 294show_input(0);
285show_input(1); 295show_input(1);
286show_input(2); 296show_input(2);
287show_input(3); 297show_input(3);
288 298
299static 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
289static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) 312static 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 390out2:
391 while (i-- > 0)
392 device_remove_file(mc->dev, &dev_attrs[i]);
376out: 393out:
377 if (mc) { 394 if (mc) {
378 if (mc->irq) 395 if (mc->irq)
@@ -393,6 +410,7 @@ out:
393static void motorcontrol_disconnect(struct usb_interface *interface) 410static 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}
239static 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)
242show_set(0); 243show_set(0);
243show_set(1); 244show_set(1);
244show_set(2); 245show_set(2);
245show_set(3); 246show_set(3);
246 247
248static struct device_attribute dev_attrs[] = {
249 servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3)
250};
251
247static int 252static int
248servo_probe(struct usb_interface *interface, const struct usb_device_id *id) 253servo_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;
302out2:
303 while (i-- > 0)
304 device_remove_file(dev->dev, &dev_attrs[i]);
305out:
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
297static void 318static void
298servo_disconnect(struct usb_interface *interface) 319servo_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);