diff options
Diffstat (limited to 'drivers/usb/misc/phidgetkit.c')
| -rw-r--r-- | drivers/usb/misc/phidgetkit.c | 316 |
1 files changed, 161 insertions, 155 deletions
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index bfbbbfbb92bc..9a8d137d39f9 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
| 22 | 22 | ||
| 23 | #include "phidget.h" | ||
| 24 | |||
| 23 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 25 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
| 24 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" | 26 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" |
| 25 | 27 | ||
| @@ -57,11 +59,15 @@ ifkit(8, 8, 4, 0); | |||
| 57 | ifkit(0, 8, 8, 1); | 59 | ifkit(0, 8, 8, 1); |
| 58 | ifkit(0, 16, 16, 0); | 60 | ifkit(0, 16, 16, 0); |
| 59 | 61 | ||
| 62 | static unsigned long device_no; | ||
| 63 | |||
| 60 | struct interfacekit { | 64 | struct interfacekit { |
| 61 | struct usb_device *udev; | 65 | struct usb_device *udev; |
| 62 | struct usb_interface *intf; | 66 | struct usb_interface *intf; |
| 63 | struct driver_interfacekit *ifkit; | 67 | struct driver_interfacekit *ifkit; |
| 68 | struct device *dev; | ||
| 64 | unsigned long outputs; | 69 | unsigned long outputs; |
| 70 | int dev_no; | ||
| 65 | u8 inputs[MAX_INTERFACES]; | 71 | u8 inputs[MAX_INTERFACES]; |
| 66 | u16 sensors[MAX_INTERFACES]; | 72 | u16 sensors[MAX_INTERFACES]; |
| 67 | u8 lcd_files_on; | 73 | u8 lcd_files_on; |
| @@ -180,21 +186,24 @@ exit: | |||
| 180 | } | 186 | } |
| 181 | 187 | ||
| 182 | #define set_lcd_line(number) \ | 188 | #define set_lcd_line(number) \ |
| 183 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 189 | static ssize_t lcd_line_##number(struct device *dev, \ |
| 184 | { \ | 190 | struct device_attribute *attr, \ |
| 185 | struct usb_interface *intf = to_usb_interface(dev); \ | 191 | const char *buf, size_t count) \ |
| 186 | struct interfacekit *kit = usb_get_intfdata(intf); \ | 192 | { \ |
| 187 | change_string(kit, buf, number - 1); \ | 193 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
| 188 | return count; \ | 194 | change_string(kit, buf, number - 1); \ |
| 189 | } \ | 195 | return count; \ |
| 190 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); | 196 | } |
| 197 | |||
| 198 | #define lcd_line_attr(number) \ | ||
| 199 | __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) | ||
| 200 | |||
| 191 | set_lcd_line(1); | 201 | set_lcd_line(1); |
| 192 | set_lcd_line(2); | 202 | set_lcd_line(2); |
| 193 | 203 | ||
| 194 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 204 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 195 | { | 205 | { |
| 196 | struct usb_interface *intf = to_usb_interface(dev); | 206 | struct interfacekit *kit = dev_get_drvdata(dev); |
| 197 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
| 198 | int enabled; | 207 | int enabled; |
| 199 | unsigned char *buffer; | 208 | unsigned char *buffer; |
| 200 | int retval = -ENOMEM; | 209 | int retval = -ENOMEM; |
| @@ -226,23 +235,30 @@ exit: | |||
| 226 | kfree(buffer); | 235 | kfree(buffer); |
| 227 | return retval; | 236 | return retval; |
| 228 | } | 237 | } |
| 229 | 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 | }; | ||
| 230 | 244 | ||
| 231 | static void remove_lcd_files(struct interfacekit *kit) | 245 | static void remove_lcd_files(struct interfacekit *kit) |
| 232 | { | 246 | { |
| 247 | int i; | ||
| 248 | |||
| 233 | if (kit->lcd_files_on) { | 249 | if (kit->lcd_files_on) { |
| 234 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 250 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
| 235 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 251 | |
| 236 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 252 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) |
| 237 | device_remove_file(&kit->intf->dev, &dev_attr_backlight); | 253 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); |
| 238 | } | 254 | } |
| 239 | } | 255 | } |
| 240 | 256 | ||
| 241 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 257 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 242 | { | 258 | { |
| 243 | struct usb_interface *intf = to_usb_interface(dev); | 259 | struct interfacekit *kit = dev_get_drvdata(dev); |
| 244 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
| 245 | int enable; | 260 | int enable; |
| 261 | int i, rc; | ||
| 246 | 262 | ||
| 247 | if (kit->ifkit->has_lcd == 0) | 263 | if (kit->ifkit->has_lcd == 0) |
| 248 | return -ENODEV; | 264 | return -ENODEV; |
| @@ -253,9 +269,12 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
| 253 | if (enable) { | 269 | if (enable) { |
| 254 | if (!kit->lcd_files_on) { | 270 | if (!kit->lcd_files_on) { |
| 255 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); | 271 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); |
| 256 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 272 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) { |
| 257 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 273 | rc = device_create_file(kit->dev, |
| 258 | device_create_file(&kit->intf->dev, &dev_attr_backlight); | 274 | &dev_lcd_line_attrs[i]); |
| 275 | if (rc) | ||
| 276 | goto out; | ||
| 277 | } | ||
| 259 | kit->lcd_files_on = 1; | 278 | kit->lcd_files_on = 1; |
| 260 | } | 279 | } |
| 261 | } else { | 280 | } else { |
| @@ -266,7 +285,13 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
| 266 | } | 285 | } |
| 267 | 286 | ||
| 268 | 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; | ||
| 269 | } | 293 | } |
| 294 | |||
| 270 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); | 295 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); |
| 271 | 296 | ||
| 272 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | 297 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) |
| @@ -362,24 +387,24 @@ static void do_notify(void *data) | |||
| 362 | for (i=0; i<kit->ifkit->inputs; i++) { | 387 | for (i=0; i<kit->ifkit->inputs; i++) { |
| 363 | if (test_and_clear_bit(i, &kit->input_events)) { | 388 | if (test_and_clear_bit(i, &kit->input_events)) { |
| 364 | sprintf(sysfs_file, "input%d", i + 1); | 389 | sprintf(sysfs_file, "input%d", i + 1); |
| 365 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 390 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
| 366 | } | 391 | } |
| 367 | } | 392 | } |
| 368 | 393 | ||
| 369 | for (i=0; i<kit->ifkit->sensors; i++) { | 394 | for (i=0; i<kit->ifkit->sensors; i++) { |
| 370 | if (test_and_clear_bit(i, &kit->sensor_events)) { | 395 | if (test_and_clear_bit(i, &kit->sensor_events)) { |
| 371 | sprintf(sysfs_file, "sensor%d", i + 1); | 396 | sprintf(sysfs_file, "sensor%d", i + 1); |
| 372 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 397 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
| 373 | } | 398 | } |
| 374 | } | 399 | } |
| 375 | } | 400 | } |
| 376 | 401 | ||
| 377 | #define show_set_output(value) \ | 402 | #define show_set_output(value) \ |
| 378 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | 403 | static ssize_t set_output##value(struct device *dev, \ |
| 379 | size_t count) \ | 404 | struct device_attribute *attr, \ |
| 405 | const char *buf, size_t count) \ | ||
| 380 | { \ | 406 | { \ |
| 381 | struct usb_interface *intf = to_usb_interface(dev); \ | 407 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
| 382 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
| 383 | int enabled; \ | 408 | int enabled; \ |
| 384 | int retval; \ | 409 | int retval; \ |
| 385 | \ | 410 | \ |
| @@ -391,15 +416,19 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at | |||
| 391 | return retval ? retval : count; \ | 416 | return retval ? retval : count; \ |
| 392 | } \ | 417 | } \ |
| 393 | \ | 418 | \ |
| 394 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 419 | static ssize_t show_output##value(struct device *dev, \ |
| 420 | struct device_attribute *attr, \ | ||
| 421 | char *buf) \ | ||
| 395 | { \ | 422 | { \ |
| 396 | struct usb_interface *intf = to_usb_interface(dev); \ | 423 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
| 397 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
| 398 | \ | 424 | \ |
| 399 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ | 425 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
| 400 | } \ | 426 | } |
| 401 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ | 427 | |
| 402 | 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 | |||
| 403 | show_set_output(1); | 432 | show_set_output(1); |
| 404 | show_set_output(2); | 433 | show_set_output(2); |
| 405 | show_set_output(3); | 434 | show_set_output(3); |
| @@ -417,15 +446,24 @@ show_set_output(14); | |||
| 417 | show_set_output(15); | 446 | show_set_output(15); |
| 418 | show_set_output(16); | 447 | show_set_output(16); |
| 419 | 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 | |||
| 420 | #define show_input(value) \ | 456 | #define show_input(value) \ |
| 421 | 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) \ | ||
| 422 | { \ | 459 | { \ |
| 423 | struct usb_interface *intf = to_usb_interface(dev); \ | 460 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
| 424 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
| 425 | \ | 461 | \ |
| 426 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ | 462 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
| 427 | } \ | 463 | } |
| 428 | 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) | ||
| 429 | 467 | ||
| 430 | show_input(1); | 468 | show_input(1); |
| 431 | show_input(2); | 469 | show_input(2); |
| @@ -444,15 +482,25 @@ show_input(14); | |||
| 444 | show_input(15); | 482 | show_input(15); |
| 445 | show_input(16); | 483 | show_input(16); |
| 446 | 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 | |||
| 447 | #define show_sensor(value) \ | 492 | #define show_sensor(value) \ |
| 448 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 493 | static ssize_t show_sensor##value(struct device *dev, \ |
| 494 | struct device_attribute *attr, \ | ||
| 495 | char *buf) \ | ||
| 449 | { \ | 496 | { \ |
| 450 | struct usb_interface *intf = to_usb_interface(dev); \ | 497 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
| 451 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
| 452 | \ | 498 | \ |
| 453 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ | 499 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
| 454 | } \ | 500 | } |
| 455 | 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) | ||
| 456 | 504 | ||
| 457 | show_sensor(1); | 505 | show_sensor(1); |
| 458 | show_sensor(2); | 506 | show_sensor(2); |
| @@ -463,6 +511,11 @@ show_sensor(6); | |||
| 463 | show_sensor(7); | 511 | show_sensor(7); |
| 464 | show_sensor(8); | 512 | show_sensor(8); |
| 465 | 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 | |||
| 466 | 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) |
| 467 | { | 520 | { |
| 468 | struct usb_device *dev = interface_to_usbdev(intf); | 521 | struct usb_device *dev = interface_to_usbdev(intf); |
| @@ -471,6 +524,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 471 | struct interfacekit *kit; | 524 | struct interfacekit *kit; |
| 472 | struct driver_interfacekit *ifkit; | 525 | struct driver_interfacekit *ifkit; |
| 473 | int pipe, maxp, rc = -ENOMEM; | 526 | int pipe, maxp, rc = -ENOMEM; |
| 527 | int bit, value, i; | ||
| 474 | 528 | ||
| 475 | ifkit = (struct driver_interfacekit *)id->driver_info; | 529 | ifkit = (struct driver_interfacekit *)id->driver_info; |
| 476 | if (!ifkit) | 530 | if (!ifkit) |
| @@ -493,6 +547,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 493 | if (!kit) | 547 | if (!kit) |
| 494 | goto out; | 548 | goto out; |
| 495 | 549 | ||
| 550 | kit->dev_no = -1; | ||
| 496 | kit->ifkit = ifkit; | 551 | kit->ifkit = ifkit; |
| 497 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); | 552 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
| 498 | if (!kit->data) | 553 | if (!kit->data) |
| @@ -513,85 +568,80 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 513 | 568 | ||
| 514 | usb_set_intfdata(intf, kit); | 569 | usb_set_intfdata(intf, kit); |
| 515 | 570 | ||
| 571 | do { | ||
| 572 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
| 573 | value = test_and_set_bit(bit, &device_no); | ||
| 574 | } while(value); | ||
| 575 | kit->dev_no = bit; | ||
| 576 | |||
| 577 | kit->dev = device_create(phidget_class, &kit->udev->dev, 0, | ||
| 578 | "interfacekit%d", kit->dev_no); | ||
| 579 | if (IS_ERR(kit->dev)) { | ||
| 580 | rc = PTR_ERR(kit->dev); | ||
| 581 | kit->dev = NULL; | ||
| 582 | goto out; | ||
| 583 | } | ||
| 584 | dev_set_drvdata(kit->dev, kit); | ||
| 585 | |||
| 516 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 586 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
| 517 | rc = -EIO; | 587 | rc = -EIO; |
| 518 | goto out; | 588 | goto out; |
| 519 | } | 589 | } |
| 520 | 590 | ||
| 521 | if (ifkit->outputs >= 4) { | 591 | for (i=0; i<ifkit->outputs; i++ ) { |
| 522 | device_create_file(&intf->dev, &dev_attr_output1); | 592 | rc = device_create_file(kit->dev, &dev_output_attrs[i]); |
| 523 | device_create_file(&intf->dev, &dev_attr_output2); | 593 | if (rc) |
| 524 | device_create_file(&intf->dev, &dev_attr_output3); | 594 | goto out2; |
| 525 | device_create_file(&intf->dev, &dev_attr_output4); | ||
| 526 | } | ||
| 527 | 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); | ||
| 532 | } | ||
| 533 | 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); | ||
| 542 | } | 595 | } |
| 543 | 596 | ||
| 544 | if (ifkit->inputs >= 4) { | 597 | for (i=0; i<ifkit->inputs; i++ ) { |
| 545 | device_create_file(&intf->dev, &dev_attr_input1); | 598 | rc = device_create_file(kit->dev, &dev_input_attrs[i]); |
| 546 | device_create_file(&intf->dev, &dev_attr_input2); | 599 | if (rc) |
| 547 | device_create_file(&intf->dev, &dev_attr_input3); | 600 | goto out3; |
| 548 | device_create_file(&intf->dev, &dev_attr_input4); | ||
| 549 | } | ||
| 550 | 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); | ||
| 555 | } | ||
| 556 | 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); | ||
| 565 | } | 601 | } |
| 566 | 602 | ||
| 567 | if (ifkit->sensors >= 4) { | 603 | for (i=0; i<ifkit->sensors; i++ ) { |
| 568 | device_create_file(&intf->dev, &dev_attr_sensor1); | 604 | rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); |
| 569 | device_create_file(&intf->dev, &dev_attr_sensor2); | 605 | if (rc) |
| 570 | device_create_file(&intf->dev, &dev_attr_sensor3); | 606 | goto out4; |
| 571 | device_create_file(&intf->dev, &dev_attr_sensor4); | ||
| 572 | } | ||
| 573 | 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); | ||
| 577 | } | 607 | } |
| 578 | if (ifkit->sensors == 8) | ||
| 579 | device_create_file(&intf->dev, &dev_attr_sensor8); | ||
| 580 | 608 | ||
| 581 | if (ifkit->has_lcd) | 609 | if (ifkit->has_lcd) { |
| 582 | device_create_file(&intf->dev, &dev_attr_lcd); | 610 | rc = device_create_file(kit->dev, &dev_attr_lcd); |
| 611 | if (rc) | ||
| 612 | goto out4; | ||
| 613 | |||
| 614 | } | ||
| 583 | 615 | ||
| 584 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", | 616 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", |
| 585 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 617 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
| 586 | 618 | ||
| 587 | return 0; | 619 | return 0; |
| 588 | 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]); | ||
| 589 | out: | 634 | out: |
| 590 | if (kit) { | 635 | if (kit) { |
| 591 | if (kit->irq) | 636 | if (kit->irq) |
| 592 | usb_free_urb(kit->irq); | 637 | usb_free_urb(kit->irq); |
| 593 | if (kit->data) | 638 | if (kit->data) |
| 594 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); | 639 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); |
| 640 | if (kit->dev) | ||
| 641 | device_unregister(kit->dev); | ||
| 642 | if (kit->dev_no >= 0) | ||
| 643 | clear_bit(kit->dev_no, &device_no); | ||
| 644 | |||
| 595 | kfree(kit); | 645 | kfree(kit); |
| 596 | } | 646 | } |
| 597 | 647 | ||
| @@ -601,6 +651,7 @@ out: | |||
| 601 | static void interfacekit_disconnect(struct usb_interface *interface) | 651 | static void interfacekit_disconnect(struct usb_interface *interface) |
| 602 | { | 652 | { |
| 603 | struct interfacekit *kit; | 653 | struct interfacekit *kit; |
| 654 | int i; | ||
| 604 | 655 | ||
| 605 | kit = usb_get_intfdata(interface); | 656 | kit = usb_get_intfdata(interface); |
| 606 | usb_set_intfdata(interface, NULL); | 657 | usb_set_intfdata(interface, NULL); |
| @@ -613,73 +664,28 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
| 613 | 664 | ||
| 614 | cancel_delayed_work(&kit->do_notify); | 665 | cancel_delayed_work(&kit->do_notify); |
| 615 | 666 | ||
| 616 | if (kit->ifkit->outputs >= 4) { | 667 | for (i=0; i<kit->ifkit->outputs; i++) |
| 617 | device_remove_file(&interface->dev, &dev_attr_output1); | 668 | device_remove_file(kit->dev, &dev_output_attrs[i]); |
| 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); | ||
| 621 | } | ||
| 622 | 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); | ||
| 627 | } | ||
| 628 | 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); | ||
| 637 | } | ||
| 638 | 669 | ||
| 639 | if (kit->ifkit->inputs >= 4) { | 670 | for (i=0; i<kit->ifkit->inputs; i++) |
| 640 | device_remove_file(&interface->dev, &dev_attr_input1); | 671 | device_remove_file(kit->dev, &dev_input_attrs[i]); |
| 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); | ||
| 644 | } | ||
| 645 | 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); | ||
| 650 | } | ||
| 651 | 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); | ||
| 660 | } | ||
| 661 | 672 | ||
| 662 | if (kit->ifkit->sensors >= 4) { | 673 | for (i=0; i<kit->ifkit->sensors; i++) |
| 663 | device_remove_file(&interface->dev, &dev_attr_sensor1); | 674 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); |
| 664 | device_remove_file(&interface->dev, &dev_attr_sensor2); | 675 | |
| 665 | device_remove_file(&interface->dev, &dev_attr_sensor3); | 676 | if (kit->ifkit->has_lcd) { |
| 666 | device_remove_file(&interface->dev, &dev_attr_sensor4); | 677 | device_remove_file(kit->dev, &dev_attr_lcd); |
| 667 | } | 678 | remove_lcd_files(kit); |
| 668 | 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); | ||
| 672 | } | 679 | } |
| 673 | if (kit->ifkit->sensors == 8) | ||
| 674 | device_remove_file(&interface->dev, &dev_attr_sensor8); | ||
| 675 | 680 | ||
| 676 | if (kit->ifkit->has_lcd) | 681 | device_unregister(kit->dev); |
| 677 | device_remove_file(&interface->dev, &dev_attr_lcd); | ||
| 678 | 682 | ||
| 679 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", | 683 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
| 680 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); | 684 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
| 681 | 685 | ||
| 682 | usb_put_dev(kit->udev); | 686 | usb_put_dev(kit->udev); |
| 687 | clear_bit(kit->dev_no, &device_no); | ||
| 688 | |||
| 683 | kfree(kit); | 689 | kfree(kit); |
| 684 | } | 690 | } |
| 685 | 691 | ||
