aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/input/powermate.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/input/powermate.c')
-rw-r--r--drivers/usb/input/powermate.c136
1 files changed, 70 insertions, 66 deletions
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index ad4afe7e5897..b7476233ef5d 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -68,7 +68,7 @@ struct powermate_device {
68 struct usb_ctrlrequest *configcr; 68 struct usb_ctrlrequest *configcr;
69 dma_addr_t configcr_dma; 69 dma_addr_t configcr_dma;
70 struct usb_device *udev; 70 struct usb_device *udev;
71 struct input_dev input; 71 struct input_dev *input;
72 spinlock_t lock; 72 spinlock_t lock;
73 int static_brightness; 73 int static_brightness;
74 int pulse_speed; 74 int pulse_speed;
@@ -106,10 +106,10 @@ static void powermate_irq(struct urb *urb, struct pt_regs *regs)
106 } 106 }
107 107
108 /* handle updates to device state */ 108 /* handle updates to device state */
109 input_regs(&pm->input, regs); 109 input_regs(pm->input, regs);
110 input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01); 110 input_report_key(pm->input, BTN_0, pm->data[0] & 0x01);
111 input_report_rel(&pm->input, REL_DIAL, pm->data[1]); 111 input_report_rel(pm->input, REL_DIAL, pm->data[1]);
112 input_sync(&pm->input); 112 input_sync(pm->input);
113 113
114exit: 114exit:
115 retval = usb_submit_urb (urb, GFP_ATOMIC); 115 retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -153,10 +153,10 @@ static void powermate_sync_state(struct powermate_device *pm)
153 153
154 Only values of 'arg' quite close to 255 are particularly useful/spectacular. 154 Only values of 'arg' quite close to 255 are particularly useful/spectacular.
155 */ 155 */
156 if (pm->pulse_speed < 255){ 156 if (pm->pulse_speed < 255) {
157 op = 0; // divide 157 op = 0; // divide
158 arg = 255 - pm->pulse_speed; 158 arg = 255 - pm->pulse_speed;
159 } else if (pm->pulse_speed > 255){ 159 } else if (pm->pulse_speed > 255) {
160 op = 2; // multiply 160 op = 2; // multiply
161 arg = pm->pulse_speed - 255; 161 arg = pm->pulse_speed - 255;
162 } else { 162 } else {
@@ -166,11 +166,11 @@ static void powermate_sync_state(struct powermate_device *pm)
166 pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); 166 pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE );
167 pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op ); 167 pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op );
168 pm->requires_update &= ~UPDATE_PULSE_MODE; 168 pm->requires_update &= ~UPDATE_PULSE_MODE;
169 }else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS){ 169 } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) {
170 pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); 170 pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS );
171 pm->configcr->wIndex = cpu_to_le16( pm->static_brightness ); 171 pm->configcr->wIndex = cpu_to_le16( pm->static_brightness );
172 pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; 172 pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS;
173 }else{ 173 } else {
174 printk(KERN_ERR "powermate: unknown update required"); 174 printk(KERN_ERR "powermate: unknown update required");
175 pm->requires_update = 0; /* fudge the bug */ 175 pm->requires_update = 0; /* fudge the bug */
176 return; 176 return;
@@ -228,19 +228,19 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne
228 spin_lock_irqsave(&pm->lock, flags); 228 spin_lock_irqsave(&pm->lock, flags);
229 229
230 /* mark state updates which are required */ 230 /* mark state updates which are required */
231 if (static_brightness != pm->static_brightness){ 231 if (static_brightness != pm->static_brightness) {
232 pm->static_brightness = static_brightness; 232 pm->static_brightness = static_brightness;
233 pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; 233 pm->requires_update |= UPDATE_STATIC_BRIGHTNESS;
234 } 234 }
235 if (pulse_asleep != pm->pulse_asleep){ 235 if (pulse_asleep != pm->pulse_asleep) {
236 pm->pulse_asleep = pulse_asleep; 236 pm->pulse_asleep = pulse_asleep;
237 pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); 237 pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS);
238 } 238 }
239 if (pulse_awake != pm->pulse_awake){ 239 if (pulse_awake != pm->pulse_awake) {
240 pm->pulse_awake = pulse_awake; 240 pm->pulse_awake = pulse_awake;
241 pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); 241 pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS);
242 } 242 }
243 if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){ 243 if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) {
244 pm->pulse_speed = pulse_speed; 244 pm->pulse_speed = pulse_speed;
245 pm->pulse_table = pulse_table; 245 pm->pulse_table = pulse_table;
246 pm->requires_update |= UPDATE_PULSE_MODE; 246 pm->requires_update |= UPDATE_PULSE_MODE;
@@ -283,6 +283,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
283 SLAB_ATOMIC, &pm->data_dma); 283 SLAB_ATOMIC, &pm->data_dma);
284 if (!pm->data) 284 if (!pm->data)
285 return -1; 285 return -1;
286
286 pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), 287 pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
287 SLAB_ATOMIC, &pm->configcr_dma); 288 SLAB_ATOMIC, &pm->configcr_dma);
288 if (!pm->configcr) 289 if (!pm->configcr)
@@ -308,8 +309,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
308 struct usb_host_interface *interface; 309 struct usb_host_interface *interface;
309 struct usb_endpoint_descriptor *endpoint; 310 struct usb_endpoint_descriptor *endpoint;
310 struct powermate_device *pm; 311 struct powermate_device *pm;
312 struct input_dev *input_dev;
311 int pipe, maxp; 313 int pipe, maxp;
312 char path[64]; 314 int err = -ENOMEM;
313 315
314 interface = intf->cur_altsetting; 316 interface = intf->cur_altsetting;
315 endpoint = &interface->endpoint[0].desc; 317 endpoint = &interface->endpoint[0].desc;
@@ -323,42 +325,61 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
323 0, interface->desc.bInterfaceNumber, NULL, 0, 325 0, interface->desc.bInterfaceNumber, NULL, 0,
324 USB_CTRL_SET_TIMEOUT); 326 USB_CTRL_SET_TIMEOUT);
325 327
326 if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL))) 328 pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL);
327 return -ENOMEM; 329 input_dev = input_allocate_device();
328 330 if (!pm || !input_dev)
329 memset(pm, 0, sizeof(struct powermate_device)); 331 goto fail1;
330 pm->udev = udev;
331 332
332 if (powermate_alloc_buffers(udev, pm)) { 333 if (powermate_alloc_buffers(udev, pm))
333 powermate_free_buffers(udev, pm); 334 goto fail2;
334 kfree(pm);
335 return -ENOMEM;
336 }
337 335
338 pm->irq = usb_alloc_urb(0, GFP_KERNEL); 336 pm->irq = usb_alloc_urb(0, GFP_KERNEL);
339 if (!pm->irq) { 337 if (!pm->irq)
340 powermate_free_buffers(udev, pm); 338 goto fail2;
341 kfree(pm);
342 return -ENOMEM;
343 }
344 339
345 pm->config = usb_alloc_urb(0, GFP_KERNEL); 340 pm->config = usb_alloc_urb(0, GFP_KERNEL);
346 if (!pm->config) { 341 if (!pm->config)
347 usb_free_urb(pm->irq); 342 goto fail3;
348 powermate_free_buffers(udev, pm); 343
349 kfree(pm); 344 pm->udev = udev;
350 return -ENOMEM; 345 pm->input = input_dev;
351 } 346
347 usb_make_path(udev, pm->phys, sizeof(pm->phys));
348 strlcpy(pm->phys, "/input0", sizeof(pm->phys));
352 349
353 spin_lock_init(&pm->lock); 350 spin_lock_init(&pm->lock);
354 init_input_dev(&pm->input); 351
352 switch (le16_to_cpu(udev->descriptor.idProduct)) {
353 case POWERMATE_PRODUCT_NEW:
354 input_dev->name = pm_name_powermate;
355 break;
356 case POWERMATE_PRODUCT_OLD:
357 input_dev->name = pm_name_soundknob;
358 break;
359 default:
360 input_dev->name = pm_name_soundknob;
361 printk(KERN_WARNING "powermate: unknown product id %04x\n",
362 le16_to_cpu(udev->descriptor.idProduct));
363 }
364
365 input_dev->phys = pm->phys;
366 usb_to_input_id(udev, &input_dev->id);
367 input_dev->cdev.dev = &intf->dev;
368 input_dev->private = pm;
369
370 input_dev->event = powermate_input_event;
371
372 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
373 input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
374 input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
375 input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
355 376
356 /* get a handle to the interrupt data pipe */ 377 /* get a handle to the interrupt data pipe */
357 pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); 378 pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
358 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 379 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
359 380
360 if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){ 381 if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) {
361 printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n", 382 printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
362 POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); 383 POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp);
363 maxp = POWERMATE_PAYLOAD_SIZE_MAX; 384 maxp = POWERMATE_PAYLOAD_SIZE_MAX;
364 } 385 }
@@ -371,35 +392,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
371 392
372 /* register our interrupt URB with the USB system */ 393 /* register our interrupt URB with the USB system */
373 if (usb_submit_urb(pm->irq, GFP_KERNEL)) { 394 if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
374 powermate_free_buffers(udev, pm); 395 err = -EIO;
375 kfree(pm); 396 goto fail4;
376 return -EIO; /* failure */
377 } 397 }
378 398
379 switch (le16_to_cpu(udev->descriptor.idProduct)) { 399 input_register_device(pm->input);
380 case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break;
381 case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break;
382 default:
383 pm->input.name = pm_name_soundknob;
384 printk(KERN_WARNING "powermate: unknown product id %04x\n",
385 le16_to_cpu(udev->descriptor.idProduct));
386 }
387
388 pm->input.private = pm;
389 pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
390 pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
391 pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
392 pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
393 usb_to_input_id(udev, &pm->input.id);
394 pm->input.event = powermate_input_event;
395 pm->input.dev = &intf->dev;
396 pm->input.phys = pm->phys;
397
398 input_register_device(&pm->input);
399
400 usb_make_path(udev, path, 64);
401 snprintf(pm->phys, 64, "%s/input0", path);
402 printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys);
403 400
404 /* force an update of everything */ 401 /* force an update of everything */
405 pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; 402 pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -407,6 +404,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
407 404
408 usb_set_intfdata(intf, pm); 405 usb_set_intfdata(intf, pm);
409 return 0; 406 return 0;
407
408fail4: usb_free_urb(pm->config);
409fail3: usb_free_urb(pm->irq);
410fail2: powermate_free_buffers(udev, pm);
411fail1: input_free_device(input_dev);
412 kfree(pm);
413 return err;
410} 414}
411 415
412/* Called when a USB device we've accepted ownership of is removed */ 416/* Called when a USB device we've accepted ownership of is removed */
@@ -418,7 +422,7 @@ static void powermate_disconnect(struct usb_interface *intf)
418 if (pm) { 422 if (pm) {
419 pm->requires_update = 0; 423 pm->requires_update = 0;
420 usb_kill_urb(pm->irq); 424 usb_kill_urb(pm->irq);
421 input_unregister_device(&pm->input); 425 input_unregister_device(pm->input);
422 usb_free_urb(pm->irq); 426 usb_free_urb(pm->irq);
423 usb_free_urb(pm->config); 427 usb_free_urb(pm->config);
424 powermate_free_buffers(interface_to_usbdev(intf), pm); 428 powermate_free_buffers(interface_to_usbdev(intf), pm);