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 | } |