diff options
Diffstat (limited to 'drivers/usb/input/powermate.c')
-rw-r--r-- | drivers/usb/input/powermate.c | 136 |
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 | ||
114 | exit: | 114 | exit: |
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 | |||
408 | fail4: usb_free_urb(pm->config); | ||
409 | fail3: usb_free_urb(pm->irq); | ||
410 | fail2: powermate_free_buffers(udev, pm); | ||
411 | fail1: 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); |