diff options
Diffstat (limited to 'drivers/usb/misc/phidgetkit.c')
| -rw-r--r-- | drivers/usb/misc/phidgetkit.c | 303 |
1 files changed, 218 insertions, 85 deletions
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 997db5d8e35b..13aeea2026cc 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * USB PhidgetInterfaceKit driver 1.0 | 2 | * USB PhidgetInterfaceKit 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 | * Copyright (C) 2005 Daniel Saakes <daniel@saakes.net> | ||
| 5 | * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> | 6 | * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> |
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| @@ -25,6 +26,7 @@ | |||
| 25 | 26 | ||
| 26 | #define USB_VENDOR_ID_GLAB 0x06c2 | 27 | #define USB_VENDOR_ID_GLAB 0x06c2 |
| 27 | #define USB_DEVICE_ID_INTERFACEKIT004 0x0040 | 28 | #define USB_DEVICE_ID_INTERFACEKIT004 0x0040 |
| 29 | #define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 | ||
| 28 | #define USB_DEVICE_ID_INTERFACEKIT888 0x0045 | 30 | #define USB_DEVICE_ID_INTERFACEKIT888 0x0045 |
| 29 | #define USB_DEVICE_ID_INTERFACEKIT047 0x0051 | 31 | #define USB_DEVICE_ID_INTERFACEKIT047 0x0051 |
| 30 | #define USB_DEVICE_ID_INTERFACEKIT088 0x0053 | 32 | #define USB_DEVICE_ID_INTERFACEKIT088 0x0053 |
| @@ -32,7 +34,9 @@ | |||
| 32 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 34 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
| 33 | #define USB_DEVICE_ID_INTERFACEKIT884 0x8201 | 35 | #define USB_DEVICE_ID_INTERFACEKIT884 0x8201 |
| 34 | 36 | ||
| 35 | #define MAX_INTERFACES 8 | 37 | #define MAX_INTERFACES 16 |
| 38 | |||
| 39 | #define URB_INT_SIZE 8 | ||
| 36 | 40 | ||
| 37 | struct driver_interfacekit { | 41 | struct driver_interfacekit { |
| 38 | int sensors; | 42 | int sensors; |
| @@ -52,19 +56,24 @@ ifkit(8, 8, 8, 0); | |||
| 52 | ifkit(0, 4, 7, 1); | 56 | ifkit(0, 4, 7, 1); |
| 53 | ifkit(8, 8, 4, 0); | 57 | ifkit(8, 8, 4, 0); |
| 54 | ifkit(0, 8, 8, 1); | 58 | ifkit(0, 8, 8, 1); |
| 59 | ifkit(0, 16, 16, 0); | ||
| 55 | 60 | ||
| 56 | struct phidget_interfacekit { | 61 | struct interfacekit { |
| 57 | struct usb_device *udev; | 62 | struct usb_device *udev; |
| 58 | struct usb_interface *intf; | 63 | struct usb_interface *intf; |
| 59 | struct driver_interfacekit *ifkit; | 64 | struct driver_interfacekit *ifkit; |
| 60 | int outputs[MAX_INTERFACES]; | 65 | unsigned long outputs; |
| 61 | int inputs[MAX_INTERFACES]; | 66 | u8 inputs[MAX_INTERFACES]; |
| 62 | int sensors[MAX_INTERFACES]; | 67 | u16 sensors[MAX_INTERFACES]; |
| 63 | u8 lcd_files_on; | 68 | u8 lcd_files_on; |
| 64 | 69 | ||
| 65 | struct urb *irq; | 70 | struct urb *irq; |
| 66 | unsigned char *data; | 71 | unsigned char *data; |
| 67 | dma_addr_t data_dma; | 72 | dma_addr_t data_dma; |
| 73 | |||
| 74 | struct work_struct do_notify; | ||
| 75 | unsigned long input_events; | ||
| 76 | unsigned long sensor_events; | ||
| 68 | }; | 77 | }; |
| 69 | 78 | ||
| 70 | static struct usb_device_id id_table[] = { | 79 | static struct usb_device_id id_table[] = { |
| @@ -76,33 +85,33 @@ static struct usb_device_id id_table[] = { | |||
| 76 | .driver_info = (kernel_ulong_t)&ph_047}, | 85 | .driver_info = (kernel_ulong_t)&ph_047}, |
| 77 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), | 86 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), |
| 78 | .driver_info = (kernel_ulong_t)&ph_088}, | 87 | .driver_info = (kernel_ulong_t)&ph_088}, |
| 88 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), | ||
| 89 | .driver_info = (kernel_ulong_t)&ph_01616}, | ||
| 79 | {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), | 90 | {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), |
| 80 | .driver_info = (kernel_ulong_t)&ph_884}, | 91 | .driver_info = (kernel_ulong_t)&ph_884}, |
| 81 | {} | 92 | {} |
| 82 | }; | 93 | }; |
| 83 | MODULE_DEVICE_TABLE(usb, id_table); | 94 | MODULE_DEVICE_TABLE(usb, id_table); |
| 84 | 95 | ||
| 85 | static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable) | 96 | static int change_outputs(struct interfacekit *kit, int output_num, int enable) |
| 86 | { | 97 | { |
| 87 | unsigned char *buffer; | 98 | u8 *buffer; |
| 88 | int retval; | 99 | int retval; |
| 89 | int n; | 100 | |
| 101 | if (enable) | ||
| 102 | set_bit(output_num, &kit->outputs); | ||
| 103 | else | ||
| 104 | clear_bit(output_num, &kit->outputs); | ||
| 90 | 105 | ||
| 91 | buffer = kzalloc(4, GFP_KERNEL); | 106 | buffer = kzalloc(4, GFP_KERNEL); |
| 92 | if (!buffer) { | 107 | if (!buffer) { |
| 93 | dev_err(&kit->udev->dev, "%s - out of memory\n", | 108 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); |
| 94 | __FUNCTION__); | ||
| 95 | return -ENOMEM; | 109 | return -ENOMEM; |
| 96 | } | 110 | } |
| 111 | buffer[0] = (u8)kit->outputs; | ||
| 112 | buffer[1] = (u8)(kit->outputs >> 8); | ||
| 97 | 113 | ||
| 98 | kit->outputs[output_num] = enable; | 114 | dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); |
| 99 | for (n=0; n<8; n++) { | ||
| 100 | if (kit->outputs[n]) { | ||
| 101 | buffer[0] |= 1 << n; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]); | ||
| 106 | 115 | ||
| 107 | retval = usb_control_msg(kit->udev, | 116 | retval = usb_control_msg(kit->udev, |
| 108 | usb_sndctrlpipe(kit->udev, 0), | 117 | usb_sndctrlpipe(kit->udev, 0), |
| @@ -116,10 +125,10 @@ static int change_outputs(struct phidget_interfacekit *kit, int output_num, int | |||
| 116 | return retval < 0 ? retval : 0; | 125 | return retval < 0 ? retval : 0; |
| 117 | } | 126 | } |
| 118 | 127 | ||
| 119 | static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row) | 128 | static int change_string(struct interfacekit *kit, const char *display, unsigned char row) |
| 120 | { | 129 | { |
| 121 | unsigned char *buffer; | 130 | unsigned char *buffer; |
| 122 | unsigned char *form_buffer; | 131 | unsigned char *form_buffer; |
| 123 | int retval = -ENOMEM; | 132 | int retval = -ENOMEM; |
| 124 | int i,j, len, buf_ptr; | 133 | int i,j, len, buf_ptr; |
| 125 | 134 | ||
| @@ -175,7 +184,7 @@ exit: | |||
| 175 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 184 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ |
| 176 | { \ | 185 | { \ |
| 177 | struct usb_interface *intf = to_usb_interface(dev); \ | 186 | struct usb_interface *intf = to_usb_interface(dev); \ |
| 178 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 187 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
| 179 | change_string(kit, buf, number - 1); \ | 188 | change_string(kit, buf, number - 1); \ |
| 180 | return count; \ | 189 | return count; \ |
| 181 | } \ | 190 | } \ |
| @@ -186,7 +195,7 @@ set_lcd_line(2); | |||
| 186 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 195 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 187 | { | 196 | { |
| 188 | struct usb_interface *intf = to_usb_interface(dev); | 197 | struct usb_interface *intf = to_usb_interface(dev); |
| 189 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); | 198 | struct interfacekit *kit = usb_get_intfdata(intf); |
| 190 | int enabled; | 199 | int enabled; |
| 191 | unsigned char *buffer; | 200 | unsigned char *buffer; |
| 192 | int retval = -ENOMEM; | 201 | int retval = -ENOMEM; |
| @@ -220,7 +229,7 @@ exit: | |||
| 220 | } | 229 | } |
| 221 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); | 230 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); |
| 222 | 231 | ||
| 223 | static void remove_lcd_files(struct phidget_interfacekit *kit) | 232 | static void remove_lcd_files(struct interfacekit *kit) |
| 224 | { | 233 | { |
| 225 | if (kit->lcd_files_on) { | 234 | if (kit->lcd_files_on) { |
| 226 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 235 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
| @@ -233,7 +242,7 @@ static void remove_lcd_files(struct phidget_interfacekit *kit) | |||
| 233 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 242 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 234 | { | 243 | { |
| 235 | struct usb_interface *intf = to_usb_interface(dev); | 244 | struct usb_interface *intf = to_usb_interface(dev); |
| 236 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); | 245 | struct interfacekit *kit = usb_get_intfdata(intf); |
| 237 | int enable; | 246 | int enable; |
| 238 | 247 | ||
| 239 | if (kit->ifkit->has_lcd == 0) | 248 | if (kit->ifkit->has_lcd == 0) |
| @@ -263,10 +272,10 @@ static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); | |||
| 263 | 272 | ||
| 264 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | 273 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) |
| 265 | { | 274 | { |
| 266 | struct phidget_interfacekit *kit = urb->context; | 275 | struct interfacekit *kit = urb->context; |
| 267 | unsigned char *buffer = kit->data; | 276 | unsigned char *buffer = kit->data; |
| 277 | int i, level, sensor; | ||
| 268 | int status; | 278 | int status; |
| 269 | int n; | ||
| 270 | 279 | ||
| 271 | switch (urb->status) { | 280 | switch (urb->status) { |
| 272 | case 0: /* success */ | 281 | case 0: /* success */ |
| @@ -280,22 +289,63 @@ static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | |||
| 280 | goto resubmit; | 289 | goto resubmit; |
| 281 | } | 290 | } |
| 282 | 291 | ||
| 283 | for (n=0; n<8; n++) { | 292 | /* digital inputs */ |
| 284 | kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0; | 293 | if (kit->ifkit->inputs == 16) { |
| 294 | for (i=0; i < 8; i++) { | ||
| 295 | level = (buffer[0] >> i) & 1; | ||
| 296 | if (kit->inputs[i] != level) { | ||
| 297 | kit->inputs[i] = level; | ||
| 298 | set_bit(i, &kit->input_events); | ||
| 299 | } | ||
| 300 | level = (buffer[1] >> i) & 1; | ||
| 301 | if (kit->inputs[8 + i] != level) { | ||
| 302 | kit->inputs[8 + i] = level; | ||
| 303 | set_bit(8 + i, &kit->input_events); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | else if (kit->ifkit->inputs == 8) { | ||
| 308 | for (i=0; i < 8; i++) { | ||
| 309 | level = (buffer[1] >> i) & 1; | ||
| 310 | if (kit->inputs[i] != level) { | ||
| 311 | kit->inputs[i] = level; | ||
| 312 | set_bit(i, &kit->input_events); | ||
| 313 | } | ||
| 314 | } | ||
| 285 | } | 315 | } |
| 286 | 316 | ||
| 287 | if (buffer[0] & 1) { | 317 | /* analog inputs */ |
| 288 | kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256; | 318 | if (kit->ifkit->sensors) { |
| 289 | kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16; | 319 | sensor = (buffer[0] & 1) ? 4 : 0; |
| 290 | kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256; | 320 | |
| 291 | kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16; | 321 | level = buffer[2] + (buffer[3] & 0x0f) * 256; |
| 292 | } else { | 322 | if (level != kit->sensors[sensor]) { |
| 293 | kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256; | 323 | kit->sensors[sensor] = level; |
| 294 | kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16; | 324 | set_bit(sensor, &kit->sensor_events); |
| 295 | kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256; | 325 | } |
| 296 | kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16; | 326 | sensor++; |
| 327 | level = buffer[4] + (buffer[3] & 0xf0) * 16; | ||
| 328 | if (level != kit->sensors[sensor]) { | ||
| 329 | kit->sensors[sensor] = level; | ||
| 330 | set_bit(sensor, &kit->sensor_events); | ||
| 331 | } | ||
| 332 | sensor++; | ||
| 333 | level = buffer[5] + (buffer[6] & 0x0f) * 256; | ||
| 334 | if (level != kit->sensors[sensor]) { | ||
| 335 | kit->sensors[sensor] = level; | ||
| 336 | set_bit(sensor, &kit->sensor_events); | ||
| 337 | } | ||
| 338 | sensor++; | ||
| 339 | level = buffer[7] + (buffer[6] & 0xf0) * 16; | ||
| 340 | if (level != kit->sensors[sensor]) { | ||
| 341 | kit->sensors[sensor] = level; | ||
| 342 | set_bit(sensor, &kit->sensor_events); | ||
| 343 | } | ||
| 297 | } | 344 | } |
| 298 | 345 | ||
| 346 | if (kit->input_events || kit->sensor_events) | ||
| 347 | schedule_work(&kit->do_notify); | ||
| 348 | |||
| 299 | resubmit: | 349 | resubmit: |
| 300 | status = usb_submit_urb(urb, SLAB_ATOMIC); | 350 | status = usb_submit_urb(urb, SLAB_ATOMIC); |
| 301 | if (status) | 351 | if (status) |
| @@ -304,20 +354,40 @@ resubmit: | |||
| 304 | kit->udev->devpath, status); | 354 | kit->udev->devpath, status); |
| 305 | } | 355 | } |
| 306 | 356 | ||
| 357 | static void do_notify(void *data) | ||
| 358 | { | ||
| 359 | struct interfacekit *kit = data; | ||
| 360 | int i; | ||
| 361 | char sysfs_file[8]; | ||
| 362 | |||
| 363 | for (i=0; i<kit->ifkit->inputs; i++) { | ||
| 364 | if (test_and_clear_bit(i, &kit->input_events)) { | ||
| 365 | sprintf(sysfs_file, "input%d", i + 1); | ||
| 366 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | for (i=0; i<kit->ifkit->sensors; i++) { | ||
| 371 | if (test_and_clear_bit(i, &kit->sensor_events)) { | ||
| 372 | sprintf(sysfs_file, "sensor%d", i + 1); | ||
| 373 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 307 | #define show_set_output(value) \ | 378 | #define show_set_output(value) \ |
| 308 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | 379 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ |
| 309 | size_t count) \ | 380 | size_t count) \ |
| 310 | { \ | 381 | { \ |
| 311 | struct usb_interface *intf = to_usb_interface(dev); \ | 382 | struct usb_interface *intf = to_usb_interface(dev); \ |
| 312 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 383 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
| 313 | int enabled; \ | 384 | int enabled; \ |
| 314 | int retval; \ | 385 | int retval; \ |
| 315 | \ | 386 | \ |
| 316 | if (sscanf(buf, "%d", &enabled) < 1) { \ | 387 | if (sscanf(buf, "%d", &enabled) < 1) \ |
| 317 | return -EINVAL; \ | 388 | return -EINVAL; \ |
| 318 | } \ | ||
| 319 | \ | 389 | \ |
| 320 | retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \ | 390 | retval = change_outputs(kit, value - 1, enabled); \ |
| 321 | \ | 391 | \ |
| 322 | return retval ? retval : count; \ | 392 | return retval ? retval : count; \ |
| 323 | } \ | 393 | } \ |
| @@ -325,9 +395,9 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at | |||
| 325 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 395 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
| 326 | { \ | 396 | { \ |
| 327 | struct usb_interface *intf = to_usb_interface(dev); \ | 397 | struct usb_interface *intf = to_usb_interface(dev); \ |
| 328 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 398 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
| 329 | \ | 399 | \ |
| 330 | return sprintf(buf, "%d\n", kit->outputs[value - 1]); \ | 400 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
| 331 | } \ | 401 | } \ |
| 332 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ | 402 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ |
| 333 | show_output##value, set_output##value); | 403 | show_output##value, set_output##value); |
| @@ -338,15 +408,23 @@ show_set_output(4); | |||
| 338 | show_set_output(5); | 408 | show_set_output(5); |
| 339 | show_set_output(6); | 409 | show_set_output(6); |
| 340 | show_set_output(7); | 410 | show_set_output(7); |
| 341 | show_set_output(8); /* should be MAX_INTERFACES - 1 */ | 411 | show_set_output(8); |
| 412 | show_set_output(9); | ||
| 413 | show_set_output(10); | ||
| 414 | show_set_output(11); | ||
| 415 | show_set_output(12); | ||
| 416 | show_set_output(13); | ||
| 417 | show_set_output(14); | ||
| 418 | show_set_output(15); | ||
| 419 | show_set_output(16); | ||
| 342 | 420 | ||
| 343 | #define show_input(value) \ | 421 | #define show_input(value) \ |
| 344 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 422 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
| 345 | { \ | 423 | { \ |
| 346 | struct usb_interface *intf = to_usb_interface(dev); \ | 424 | struct usb_interface *intf = to_usb_interface(dev); \ |
| 347 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 425 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
| 348 | \ | 426 | \ |
| 349 | return sprintf(buf, "%d\n", kit->inputs[value - 1]); \ | 427 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
| 350 | } \ | 428 | } \ |
| 351 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); | 429 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); |
| 352 | 430 | ||
| @@ -357,15 +435,23 @@ show_input(4); | |||
| 357 | show_input(5); | 435 | show_input(5); |
| 358 | show_input(6); | 436 | show_input(6); |
| 359 | show_input(7); | 437 | show_input(7); |
| 360 | show_input(8); /* should be MAX_INTERFACES - 1 */ | 438 | show_input(8); |
| 439 | show_input(9); | ||
| 440 | show_input(10); | ||
| 441 | show_input(11); | ||
| 442 | show_input(12); | ||
| 443 | show_input(13); | ||
| 444 | show_input(14); | ||
| 445 | show_input(15); | ||
| 446 | show_input(16); | ||
| 361 | 447 | ||
| 362 | #define show_sensor(value) \ | 448 | #define show_sensor(value) \ |
| 363 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 449 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
| 364 | { \ | 450 | { \ |
| 365 | struct usb_interface *intf = to_usb_interface(dev); \ | 451 | struct usb_interface *intf = to_usb_interface(dev); \ |
| 366 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 452 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
| 367 | \ | 453 | \ |
| 368 | return sprintf(buf, "%d\n", kit->sensors[value - 1]); \ | 454 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
| 369 | } \ | 455 | } \ |
| 370 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); | 456 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); |
| 371 | 457 | ||
| @@ -376,16 +462,16 @@ show_sensor(4); | |||
| 376 | show_sensor(5); | 462 | show_sensor(5); |
| 377 | show_sensor(6); | 463 | show_sensor(6); |
| 378 | show_sensor(7); | 464 | show_sensor(7); |
| 379 | show_sensor(8); /* should be MAX_INTERFACES - 1 */ | 465 | show_sensor(8); |
| 380 | 466 | ||
| 381 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) | 467 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 382 | { | 468 | { |
| 383 | struct usb_device *dev = interface_to_usbdev(intf); | 469 | struct usb_device *dev = interface_to_usbdev(intf); |
| 384 | struct usb_host_interface *interface; | 470 | struct usb_host_interface *interface; |
| 385 | struct usb_endpoint_descriptor *endpoint; | 471 | struct usb_endpoint_descriptor *endpoint; |
| 386 | struct phidget_interfacekit *kit; | 472 | struct interfacekit *kit; |
| 387 | struct driver_interfacekit *ifkit; | 473 | struct driver_interfacekit *ifkit; |
| 388 | int pipe, maxp; | 474 | int pipe, maxp, rc = -ENOMEM; |
| 389 | 475 | ||
| 390 | ifkit = (struct driver_interfacekit *)id->driver_info; | 476 | ifkit = (struct driver_interfacekit *)id->driver_info; |
| 391 | if (!ifkit) | 477 | if (!ifkit) |
| @@ -405,29 +491,23 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 405 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | 491 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
| 406 | 492 | ||
| 407 | kit = kzalloc(sizeof(*kit), GFP_KERNEL); | 493 | kit = kzalloc(sizeof(*kit), GFP_KERNEL); |
| 408 | if (kit == NULL) { | 494 | if (!kit) |
| 409 | dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__); | 495 | goto out; |
| 410 | return -ENOMEM; | ||
| 411 | } | ||
| 412 | kit->ifkit = ifkit; | ||
| 413 | 496 | ||
| 414 | kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma); | 497 | kit->ifkit = ifkit; |
| 415 | if (!kit->data) { | 498 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
| 416 | kfree(kit); | 499 | if (!kit->data) |
| 417 | return -ENOMEM; | 500 | goto out; |
| 418 | } | ||
| 419 | 501 | ||
| 420 | kit->irq = usb_alloc_urb(0, GFP_KERNEL); | 502 | kit->irq = usb_alloc_urb(0, GFP_KERNEL); |
| 421 | if (!kit->irq) { | 503 | if (!kit->irq) |
| 422 | usb_buffer_free(dev, 8, kit->data, kit->data_dma); | 504 | goto out; |
| 423 | kfree(kit); | ||
| 424 | return -ENOMEM; | ||
| 425 | } | ||
| 426 | 505 | ||
| 427 | kit->udev = usb_get_dev(dev); | 506 | kit->udev = usb_get_dev(dev); |
| 428 | kit->intf = intf; | 507 | kit->intf = intf; |
| 508 | INIT_WORK(&kit->do_notify, do_notify, kit); | ||
| 429 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, | 509 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, |
| 430 | (maxp > 8 ? 8 : maxp), | 510 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, |
| 431 | interfacekit_irq, kit, endpoint->bInterval); | 511 | interfacekit_irq, kit, endpoint->bInterval); |
| 432 | kit->irq->transfer_dma = kit->data_dma; | 512 | kit->irq->transfer_dma = kit->data_dma; |
| 433 | kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 513 | kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| @@ -435,7 +515,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 435 | usb_set_intfdata(intf, kit); | 515 | usb_set_intfdata(intf, kit); |
| 436 | 516 | ||
| 437 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 517 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
| 438 | return -EIO; | 518 | rc = -EIO; |
| 519 | goto out; | ||
| 439 | } | 520 | } |
| 440 | 521 | ||
| 441 | if (ifkit->outputs >= 4) { | 522 | if (ifkit->outputs >= 4) { |
| @@ -444,12 +525,22 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 444 | device_create_file(&intf->dev, &dev_attr_output3); | 525 | device_create_file(&intf->dev, &dev_attr_output3); |
| 445 | device_create_file(&intf->dev, &dev_attr_output4); | 526 | device_create_file(&intf->dev, &dev_attr_output4); |
| 446 | } | 527 | } |
| 447 | if (ifkit->outputs == 8) { | 528 | if (ifkit->outputs >= 8) { |
| 448 | device_create_file(&intf->dev, &dev_attr_output5); | 529 | device_create_file(&intf->dev, &dev_attr_output5); |
| 449 | device_create_file(&intf->dev, &dev_attr_output6); | 530 | device_create_file(&intf->dev, &dev_attr_output6); |
| 450 | device_create_file(&intf->dev, &dev_attr_output7); | 531 | device_create_file(&intf->dev, &dev_attr_output7); |
| 451 | device_create_file(&intf->dev, &dev_attr_output8); | 532 | device_create_file(&intf->dev, &dev_attr_output8); |
| 452 | } | 533 | } |
| 534 | if (ifkit->outputs == 16) { | ||
| 535 | device_create_file(&intf->dev, &dev_attr_output9); | ||
| 536 | device_create_file(&intf->dev, &dev_attr_output10); | ||
| 537 | device_create_file(&intf->dev, &dev_attr_output11); | ||
| 538 | device_create_file(&intf->dev, &dev_attr_output12); | ||
| 539 | device_create_file(&intf->dev, &dev_attr_output13); | ||
| 540 | device_create_file(&intf->dev, &dev_attr_output14); | ||
| 541 | device_create_file(&intf->dev, &dev_attr_output15); | ||
| 542 | device_create_file(&intf->dev, &dev_attr_output16); | ||
| 543 | } | ||
| 453 | 544 | ||
| 454 | if (ifkit->inputs >= 4) { | 545 | if (ifkit->inputs >= 4) { |
| 455 | device_create_file(&intf->dev, &dev_attr_input1); | 546 | device_create_file(&intf->dev, &dev_attr_input1); |
| @@ -457,12 +548,22 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 457 | device_create_file(&intf->dev, &dev_attr_input3); | 548 | device_create_file(&intf->dev, &dev_attr_input3); |
| 458 | device_create_file(&intf->dev, &dev_attr_input4); | 549 | device_create_file(&intf->dev, &dev_attr_input4); |
| 459 | } | 550 | } |
| 460 | if (ifkit->inputs == 8) { | 551 | if (ifkit->inputs >= 8) { |
| 461 | device_create_file(&intf->dev, &dev_attr_input5); | 552 | device_create_file(&intf->dev, &dev_attr_input5); |
| 462 | device_create_file(&intf->dev, &dev_attr_input6); | 553 | device_create_file(&intf->dev, &dev_attr_input6); |
| 463 | device_create_file(&intf->dev, &dev_attr_input7); | 554 | device_create_file(&intf->dev, &dev_attr_input7); |
| 464 | device_create_file(&intf->dev, &dev_attr_input8); | 555 | device_create_file(&intf->dev, &dev_attr_input8); |
| 465 | } | 556 | } |
| 557 | if (ifkit->inputs == 16) { | ||
| 558 | device_create_file(&intf->dev, &dev_attr_input9); | ||
| 559 | device_create_file(&intf->dev, &dev_attr_input10); | ||
| 560 | device_create_file(&intf->dev, &dev_attr_input11); | ||
| 561 | device_create_file(&intf->dev, &dev_attr_input12); | ||
| 562 | device_create_file(&intf->dev, &dev_attr_input13); | ||
| 563 | device_create_file(&intf->dev, &dev_attr_input14); | ||
| 564 | device_create_file(&intf->dev, &dev_attr_input15); | ||
| 565 | device_create_file(&intf->dev, &dev_attr_input16); | ||
| 566 | } | ||
| 466 | 567 | ||
| 467 | if (ifkit->sensors >= 4) { | 568 | if (ifkit->sensors >= 4) { |
| 468 | device_create_file(&intf->dev, &dev_attr_sensor1); | 569 | device_create_file(&intf->dev, &dev_attr_sensor1); |
| @@ -475,9 +576,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 475 | device_create_file(&intf->dev, &dev_attr_sensor6); | 576 | device_create_file(&intf->dev, &dev_attr_sensor6); |
| 476 | device_create_file(&intf->dev, &dev_attr_sensor7); | 577 | device_create_file(&intf->dev, &dev_attr_sensor7); |
| 477 | } | 578 | } |
| 478 | if (ifkit->sensors == 8) { | 579 | if (ifkit->sensors == 8) |
| 479 | device_create_file(&intf->dev, &dev_attr_sensor8); | 580 | device_create_file(&intf->dev, &dev_attr_sensor8); |
| 480 | } | ||
| 481 | 581 | ||
| 482 | if (ifkit->has_lcd) | 582 | if (ifkit->has_lcd) |
| 483 | device_create_file(&intf->dev, &dev_attr_lcd); | 583 | device_create_file(&intf->dev, &dev_attr_lcd); |
| @@ -486,29 +586,56 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
| 486 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 586 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
| 487 | 587 | ||
| 488 | return 0; | 588 | return 0; |
| 589 | |||
| 590 | out: | ||
| 591 | if (kit) { | ||
| 592 | if (kit->irq) | ||
| 593 | usb_free_urb(kit->irq); | ||
| 594 | if (kit->data) | ||
| 595 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); | ||
| 596 | kfree(kit); | ||
| 597 | } | ||
| 598 | |||
| 599 | return rc; | ||
| 489 | } | 600 | } |
| 490 | 601 | ||
| 491 | static void interfacekit_disconnect(struct usb_interface *interface) | 602 | static void interfacekit_disconnect(struct usb_interface *interface) |
| 492 | { | 603 | { |
| 493 | struct phidget_interfacekit *kit; | 604 | struct interfacekit *kit; |
| 494 | 605 | ||
| 495 | kit = usb_get_intfdata(interface); | 606 | kit = usb_get_intfdata(interface); |
| 496 | usb_set_intfdata(interface, NULL); | 607 | usb_set_intfdata(interface, NULL); |
| 497 | if (!kit) | 608 | if (!kit) |
| 498 | return; | 609 | return; |
| 499 | 610 | ||
| 611 | usb_kill_urb(kit->irq); | ||
| 612 | usb_free_urb(kit->irq); | ||
| 613 | usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); | ||
| 614 | |||
| 615 | cancel_delayed_work(&kit->do_notify); | ||
| 616 | |||
| 500 | if (kit->ifkit->outputs >= 4) { | 617 | if (kit->ifkit->outputs >= 4) { |
| 501 | device_remove_file(&interface->dev, &dev_attr_output1); | 618 | device_remove_file(&interface->dev, &dev_attr_output1); |
| 502 | device_remove_file(&interface->dev, &dev_attr_output2); | 619 | device_remove_file(&interface->dev, &dev_attr_output2); |
| 503 | device_remove_file(&interface->dev, &dev_attr_output3); | 620 | device_remove_file(&interface->dev, &dev_attr_output3); |
| 504 | device_remove_file(&interface->dev, &dev_attr_output4); | 621 | device_remove_file(&interface->dev, &dev_attr_output4); |
| 505 | } | 622 | } |
| 506 | if (kit->ifkit->outputs == 8) { | 623 | if (kit->ifkit->outputs >= 8) { |
| 507 | device_remove_file(&interface->dev, &dev_attr_output5); | 624 | device_remove_file(&interface->dev, &dev_attr_output5); |
| 508 | device_remove_file(&interface->dev, &dev_attr_output6); | 625 | device_remove_file(&interface->dev, &dev_attr_output6); |
| 509 | device_remove_file(&interface->dev, &dev_attr_output7); | 626 | device_remove_file(&interface->dev, &dev_attr_output7); |
| 510 | device_remove_file(&interface->dev, &dev_attr_output8); | 627 | device_remove_file(&interface->dev, &dev_attr_output8); |
| 511 | } | 628 | } |
| 629 | if (kit->ifkit->outputs == 16) { | ||
| 630 | device_remove_file(&interface->dev, &dev_attr_output9); | ||
| 631 | device_remove_file(&interface->dev, &dev_attr_output10); | ||
| 632 | device_remove_file(&interface->dev, &dev_attr_output11); | ||
| 633 | device_remove_file(&interface->dev, &dev_attr_output12); | ||
| 634 | device_remove_file(&interface->dev, &dev_attr_output13); | ||
| 635 | device_remove_file(&interface->dev, &dev_attr_output14); | ||
| 636 | device_remove_file(&interface->dev, &dev_attr_output15); | ||
| 637 | device_remove_file(&interface->dev, &dev_attr_output16); | ||
| 638 | } | ||
| 512 | 639 | ||
| 513 | if (kit->ifkit->inputs >= 4) { | 640 | if (kit->ifkit->inputs >= 4) { |
| 514 | device_remove_file(&interface->dev, &dev_attr_input1); | 641 | device_remove_file(&interface->dev, &dev_attr_input1); |
| @@ -516,12 +643,22 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
| 516 | device_remove_file(&interface->dev, &dev_attr_input3); | 643 | device_remove_file(&interface->dev, &dev_attr_input3); |
| 517 | device_remove_file(&interface->dev, &dev_attr_input4); | 644 | device_remove_file(&interface->dev, &dev_attr_input4); |
| 518 | } | 645 | } |
| 519 | if (kit->ifkit->inputs == 8) { | 646 | if (kit->ifkit->inputs >= 8) { |
| 520 | device_remove_file(&interface->dev, &dev_attr_input5); | 647 | device_remove_file(&interface->dev, &dev_attr_input5); |
| 521 | device_remove_file(&interface->dev, &dev_attr_input6); | 648 | device_remove_file(&interface->dev, &dev_attr_input6); |
| 522 | device_remove_file(&interface->dev, &dev_attr_input7); | 649 | device_remove_file(&interface->dev, &dev_attr_input7); |
| 523 | device_remove_file(&interface->dev, &dev_attr_input8); | 650 | device_remove_file(&interface->dev, &dev_attr_input8); |
| 524 | } | 651 | } |
| 652 | if (kit->ifkit->inputs == 16) { | ||
| 653 | device_remove_file(&interface->dev, &dev_attr_input9); | ||
| 654 | device_remove_file(&interface->dev, &dev_attr_input10); | ||
| 655 | device_remove_file(&interface->dev, &dev_attr_input11); | ||
| 656 | device_remove_file(&interface->dev, &dev_attr_input12); | ||
| 657 | device_remove_file(&interface->dev, &dev_attr_input13); | ||
| 658 | device_remove_file(&interface->dev, &dev_attr_input14); | ||
| 659 | device_remove_file(&interface->dev, &dev_attr_input15); | ||
| 660 | device_remove_file(&interface->dev, &dev_attr_input16); | ||
| 661 | } | ||
| 525 | 662 | ||
| 526 | if (kit->ifkit->sensors >= 4) { | 663 | if (kit->ifkit->sensors >= 4) { |
| 527 | device_remove_file(&interface->dev, &dev_attr_sensor1); | 664 | device_remove_file(&interface->dev, &dev_attr_sensor1); |
| @@ -534,19 +671,15 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
| 534 | device_remove_file(&interface->dev, &dev_attr_sensor6); | 671 | device_remove_file(&interface->dev, &dev_attr_sensor6); |
| 535 | device_remove_file(&interface->dev, &dev_attr_sensor7); | 672 | device_remove_file(&interface->dev, &dev_attr_sensor7); |
| 536 | } | 673 | } |
| 537 | if (kit->ifkit->sensors == 8) { | 674 | if (kit->ifkit->sensors == 8) |
| 538 | device_remove_file(&interface->dev, &dev_attr_sensor8); | 675 | device_remove_file(&interface->dev, &dev_attr_sensor8); |
| 539 | } | 676 | |
| 540 | if (kit->ifkit->has_lcd) | 677 | if (kit->ifkit->has_lcd) |
| 541 | device_remove_file(&interface->dev, &dev_attr_lcd); | 678 | device_remove_file(&interface->dev, &dev_attr_lcd); |
| 542 | 679 | ||
| 543 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", | 680 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
| 544 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); | 681 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
| 545 | 682 | ||
| 546 | usb_kill_urb(kit->irq); | ||
| 547 | usb_free_urb(kit->irq); | ||
| 548 | usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma); | ||
| 549 | |||
| 550 | usb_put_dev(kit->udev); | 683 | usb_put_dev(kit->udev); |
| 551 | kfree(kit); | 684 | kfree(kit); |
| 552 | } | 685 | } |
