aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/phidgetmotorcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc/phidgetmotorcontrol.c')
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c126
1 files changed, 79 insertions, 47 deletions
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 2972dc2eb27f..d9ac7f97f8c8 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -15,6 +15,8 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/usb.h> 16#include <linux/usb.h>
17 17
18#include "phidget.h"
19
18#define DRIVER_AUTHOR "Sean Young <sean@mess.org>" 20#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
19#define DRIVER_DESC "USB PhidgetMotorControl Driver" 21#define DRIVER_DESC "USB PhidgetMotorControl Driver"
20 22
@@ -23,9 +25,13 @@
23 25
24#define URB_INT_SIZE 8 26#define URB_INT_SIZE 8
25 27
28static unsigned long device_no;
29
26struct motorcontrol { 30struct motorcontrol {
27 struct usb_device *udev; 31 struct usb_device *udev;
28 struct usb_interface *intf; 32 struct usb_interface *intf;
33 struct device *dev;
34 int dev_no;
29 u8 inputs[4]; 35 u8 inputs[4];
30 s8 desired_speed[2]; 36 s8 desired_speed[2];
31 s8 speed[2]; 37 s8 speed[2];
@@ -162,14 +168,14 @@ static void do_notify(void *data)
162 for (i=0; i<4; i++) { 168 for (i=0; i<4; i++) {
163 if (test_and_clear_bit(i, &mc->input_events)) { 169 if (test_and_clear_bit(i, &mc->input_events)) {
164 sprintf(sysfs_file, "input%d", i); 170 sprintf(sysfs_file, "input%d", i);
165 sysfs_notify(&mc->intf->dev.kobj, NULL, sysfs_file); 171 sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
166 } 172 }
167 } 173 }
168 174
169 for (i=0; i<2; i++) { 175 for (i=0; i<2; i++) {
170 if (test_and_clear_bit(i, &mc->speed_events)) { 176 if (test_and_clear_bit(i, &mc->speed_events)) {
171 sprintf(sysfs_file, "speed%d", i); 177 sprintf(sysfs_file, "speed%d", i);
172 sysfs_notify(&mc->intf->dev.kobj, NULL, sysfs_file); 178 sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
173 } 179 }
174 } 180 }
175 181
@@ -181,11 +187,11 @@ static void do_notify(void *data)
181} 187}
182 188
183#define show_set_speed(value) \ 189#define show_set_speed(value) \
184static ssize_t set_speed##value(struct device *dev, \ 190static ssize_t set_speed##value(struct device *dev, \
185 struct device_attribute *attr, const char *buf, size_t count) \ 191 struct device_attribute *attr, \
192 const char *buf, size_t count) \
186{ \ 193{ \
187 struct usb_interface *intf = to_usb_interface(dev); \ 194 struct motorcontrol *mc = dev_get_drvdata(dev); \
188 struct motorcontrol *mc = usb_get_intfdata(intf); \
189 int speed; \ 195 int speed; \
190 int retval; \ 196 int retval; \
191 \ 197 \
@@ -202,11 +208,11 @@ static ssize_t set_speed##value(struct device *dev, \
202 return retval ? retval : count; \ 208 return retval ? retval : count; \
203} \ 209} \
204 \ 210 \
205static ssize_t show_speed##value(struct device *dev, \ 211static ssize_t show_speed##value(struct device *dev, \
206 struct device_attribute *attr, char *buf) \ 212 struct device_attribute *attr, \
213 char *buf) \
207{ \ 214{ \
208 struct usb_interface *intf = to_usb_interface(dev); \ 215 struct motorcontrol *mc = dev_get_drvdata(dev); \
209 struct motorcontrol *mc = usb_get_intfdata(intf); \
210 \ 216 \
211 return sprintf(buf, "%d\n", mc->speed[value]); \ 217 return sprintf(buf, "%d\n", mc->speed[value]); \
212} \ 218} \
@@ -217,10 +223,10 @@ show_set_speed(1);
217 223
218#define show_set_acceleration(value) \ 224#define show_set_acceleration(value) \
219static ssize_t set_acceleration##value(struct device *dev, \ 225static ssize_t set_acceleration##value(struct device *dev, \
220 struct device_attribute *attr, const char *buf, size_t count) \ 226 struct device_attribute *attr, \
227 const char *buf, size_t count) \
221{ \ 228{ \
222 struct usb_interface *intf = to_usb_interface(dev); \ 229 struct motorcontrol *mc = dev_get_drvdata(dev); \
223 struct motorcontrol *mc = usb_get_intfdata(intf); \
224 int acceleration; \ 230 int acceleration; \
225 int retval; \ 231 int retval; \
226 \ 232 \
@@ -237,11 +243,11 @@ static ssize_t set_acceleration##value(struct device *dev, \
237 return retval ? retval : count; \ 243 return retval ? retval : count; \
238} \ 244} \
239 \ 245 \
240static ssize_t show_acceleration##value(struct device *dev, \ 246static ssize_t show_acceleration##value(struct device *dev, \
241 struct device_attribute *attr, char *buf) \ 247 struct device_attribute *attr, \
248 char *buf) \
242{ \ 249{ \
243 struct usb_interface *intf = to_usb_interface(dev); \ 250 struct motorcontrol *mc = dev_get_drvdata(dev); \
244 struct motorcontrol *mc = usb_get_intfdata(intf); \
245 \ 251 \
246 return sprintf(buf, "%d\n", mc->acceleration[value]); \ 252 return sprintf(buf, "%d\n", mc->acceleration[value]); \
247} \ 253} \
@@ -251,11 +257,11 @@ show_set_acceleration(0);
251show_set_acceleration(1); 257show_set_acceleration(1);
252 258
253#define show_current(value) \ 259#define show_current(value) \
254static ssize_t show_current##value(struct device *dev, \ 260static ssize_t show_current##value(struct device *dev, \
255 struct device_attribute *attr, char *buf) \ 261 struct device_attribute *attr, \
262 char *buf) \
256{ \ 263{ \
257 struct usb_interface *intf = to_usb_interface(dev); \ 264 struct motorcontrol *mc = dev_get_drvdata(dev); \
258 struct motorcontrol *mc = usb_get_intfdata(intf); \
259 \ 265 \
260 return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ 266 return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \
261} \ 267} \
@@ -265,11 +271,11 @@ show_current(0);
265show_current(1); 271show_current(1);
266 272
267#define show_input(value) \ 273#define show_input(value) \
268static ssize_t show_input##value(struct device *dev, \ 274static ssize_t show_input##value(struct device *dev, \
269 struct device_attribute *attr, char *buf) \ 275 struct device_attribute *attr, \
276 char *buf) \
270{ \ 277{ \
271 struct usb_interface *intf = to_usb_interface(dev); \ 278 struct motorcontrol *mc = dev_get_drvdata(dev); \
272 struct motorcontrol *mc = usb_get_intfdata(intf); \
273 \ 279 \
274 return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ 280 return sprintf(buf, "%d\n", (int)mc->inputs[value]); \
275} \ 281} \
@@ -287,6 +293,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
287 struct usb_endpoint_descriptor *endpoint; 293 struct usb_endpoint_descriptor *endpoint;
288 struct motorcontrol *mc; 294 struct motorcontrol *mc;
289 int pipe, maxp, rc = -ENOMEM; 295 int pipe, maxp, rc = -ENOMEM;
296 int bit, value;
290 297
291 interface = intf->cur_altsetting; 298 interface = intf->cur_altsetting;
292 if (interface->desc.bNumEndpoints != 1) 299 if (interface->desc.bNumEndpoints != 1)
@@ -306,6 +313,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
306 if (!mc) 313 if (!mc)
307 goto out; 314 goto out;
308 315
316 mc->dev_no = -1;
309 mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma); 317 mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);
310 if (!mc->data) 318 if (!mc->data)
311 goto out; 319 goto out;
@@ -326,26 +334,42 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
326 334
327 usb_set_intfdata(intf, mc); 335 usb_set_intfdata(intf, mc);
328 336
337 do {
338 bit = find_first_zero_bit(&device_no, sizeof(device_no));
339 value = test_and_set_bit(bit, &device_no);
340 } while(value);
341 mc->dev_no = bit;
342
343 mc->dev = device_create(phidget_class, &mc->udev->dev, 0,
344 "motorcontrol%d", mc->dev_no);
345 if (IS_ERR(mc->dev)) {
346 rc = PTR_ERR(mc->dev);
347 mc->dev = NULL;
348 goto out;
349 }
350
351 dev_set_drvdata(mc->dev, mc);
352
329 if (usb_submit_urb(mc->irq, GFP_KERNEL)) { 353 if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
330 rc = -EIO; 354 rc = -EIO;
331 goto out; 355 goto out;
332 } 356 }
333 357
334 device_create_file(&intf->dev, &dev_attr_input0); 358 device_create_file(mc->dev, &dev_attr_input0);
335 device_create_file(&intf->dev, &dev_attr_input1); 359 device_create_file(mc->dev, &dev_attr_input1);
336 device_create_file(&intf->dev, &dev_attr_input2); 360 device_create_file(mc->dev, &dev_attr_input2);
337 device_create_file(&intf->dev, &dev_attr_input3); 361 device_create_file(mc->dev, &dev_attr_input3);
338 362
339 device_create_file(&intf->dev, &dev_attr_speed0); 363 device_create_file(mc->dev, &dev_attr_speed0);
340 device_create_file(&intf->dev, &dev_attr_speed1); 364 device_create_file(mc->dev, &dev_attr_speed1);
341 365
342 device_create_file(&intf->dev, &dev_attr_acceleration0); 366 device_create_file(mc->dev, &dev_attr_acceleration0);
343 device_create_file(&intf->dev, &dev_attr_acceleration1); 367 device_create_file(mc->dev, &dev_attr_acceleration1);
344 368
345 device_create_file(&intf->dev, &dev_attr_current0); 369 device_create_file(mc->dev, &dev_attr_current0);
346 device_create_file(&intf->dev, &dev_attr_current1); 370 device_create_file(mc->dev, &dev_attr_current1);
347 371
348 dev_info(&intf->dev, "USB Phidget MotorControl attached\n"); 372 dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
349 373
350 return 0; 374 return 0;
351 375
@@ -355,6 +379,11 @@ out:
355 usb_free_urb(mc->irq); 379 usb_free_urb(mc->irq);
356 if (mc->data) 380 if (mc->data)
357 usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); 381 usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
382 if (mc->dev)
383 device_unregister(mc->dev);
384 if (mc->dev_no >= 0)
385 clear_bit(mc->dev_no, &device_no);
386
358 kfree(mc); 387 kfree(mc);
359 } 388 }
360 389
@@ -376,24 +405,27 @@ static void motorcontrol_disconnect(struct usb_interface *interface)
376 405
377 cancel_delayed_work(&mc->do_notify); 406 cancel_delayed_work(&mc->do_notify);
378 407
379 device_remove_file(&interface->dev, &dev_attr_input0); 408 device_remove_file(mc->dev, &dev_attr_input0);
380 device_remove_file(&interface->dev, &dev_attr_input1); 409 device_remove_file(mc->dev, &dev_attr_input1);
381 device_remove_file(&interface->dev, &dev_attr_input2); 410 device_remove_file(mc->dev, &dev_attr_input2);
382 device_remove_file(&interface->dev, &dev_attr_input3); 411 device_remove_file(mc->dev, &dev_attr_input3);
383 412
384 device_remove_file(&interface->dev, &dev_attr_speed0); 413 device_remove_file(mc->dev, &dev_attr_speed0);
385 device_remove_file(&interface->dev, &dev_attr_speed1); 414 device_remove_file(mc->dev, &dev_attr_speed1);
386 415
387 device_remove_file(&interface->dev, &dev_attr_acceleration0); 416 device_remove_file(mc->dev, &dev_attr_acceleration0);
388 device_remove_file(&interface->dev, &dev_attr_acceleration1); 417 device_remove_file(mc->dev, &dev_attr_acceleration1);
389 418
390 device_remove_file(&interface->dev, &dev_attr_current0); 419 device_remove_file(mc->dev, &dev_attr_current0);
391 device_remove_file(&interface->dev, &dev_attr_current1); 420 device_remove_file(mc->dev, &dev_attr_current1);
392 421
393 dev_info(&interface->dev, "USB Phidget MotorControl disconnected\n"); 422 device_unregister(mc->dev);
394 423
395 usb_put_dev(mc->udev); 424 usb_put_dev(mc->udev);
425 clear_bit(mc->dev_no, &device_no);
396 kfree(mc); 426 kfree(mc);
427
428 dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
397} 429}
398 430
399static struct usb_driver motorcontrol_driver = { 431static struct usb_driver motorcontrol_driver = {