aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-09-06 07:50:28 -0400
committerJiri Kosina <jkosina@suse.cz>2011-09-07 07:25:15 -0400
commit98a558ae35930e02dfc2dd0a124c93ad39b0828d (patch)
tree9f57b5b2b1aec9ea5e189a17bac12d47fb665013 /drivers
parentd020be9246735ff1fc49b99bea0574a597592709 (diff)
HID: wiimote: Add accelerometer input device
Add new input device for every wiimote which is used to report accelerometer data to userspace. Only if the input device is currently open, we make the wiimote send accelerometer data. This saves a whole lot of energy on the wiimote if an application is only interested in button input reports. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/hid-wiimote.c99
1 files changed, 89 insertions, 10 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index 57faac527230..9fb7bd63e7f7 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -36,6 +36,7 @@ struct wiimote_data {
36 struct hid_device *hdev; 36 struct hid_device *hdev;
37 struct input_dev *input; 37 struct input_dev *input;
38 struct led_classdev *leds[4]; 38 struct led_classdev *leds[4];
39 struct input_dev *accel;
39 40
40 spinlock_t qlock; 41 spinlock_t qlock;
41 __u8 head; 42 __u8 head;
@@ -51,6 +52,7 @@ struct wiimote_data {
51#define WIIPROTO_FLAG_LED3 0x04 52#define WIIPROTO_FLAG_LED3 0x04
52#define WIIPROTO_FLAG_LED4 0x08 53#define WIIPROTO_FLAG_LED4 0x08
53#define WIIPROTO_FLAG_RUMBLE 0x10 54#define WIIPROTO_FLAG_RUMBLE 0x10
55#define WIIPROTO_FLAG_ACCEL 0x20
54#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ 56#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
55 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) 57 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
56 58
@@ -257,6 +259,20 @@ static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
257 wiimote_queue(wdata, cmd, sizeof(cmd)); 259 wiimote_queue(wdata, cmd, sizeof(cmd));
258} 260}
259 261
262static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel)
263{
264 accel = !!accel;
265 if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
266 return;
267
268 if (accel)
269 wdata->state.flags |= WIIPROTO_FLAG_ACCEL;
270 else
271 wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL;
272
273 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
274}
275
260static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) 276static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
261{ 277{
262 struct wiimote_data *wdata; 278 struct wiimote_data *wdata;
@@ -344,6 +360,35 @@ static void wiimote_input_close(struct input_dev *dev)
344 hid_hw_close(wdata->hdev); 360 hid_hw_close(wdata->hdev);
345} 361}
346 362
363static int wiimote_accel_open(struct input_dev *dev)
364{
365 struct wiimote_data *wdata = input_get_drvdata(dev);
366 int ret;
367 unsigned long flags;
368
369 ret = hid_hw_open(wdata->hdev);
370 if (ret)
371 return ret;
372
373 spin_lock_irqsave(&wdata->state.lock, flags);
374 wiiproto_req_accel(wdata, true);
375 spin_unlock_irqrestore(&wdata->state.lock, flags);
376
377 return 0;
378}
379
380static void wiimote_accel_close(struct input_dev *dev)
381{
382 struct wiimote_data *wdata = input_get_drvdata(dev);
383 unsigned long flags;
384
385 spin_lock_irqsave(&wdata->state.lock, flags);
386 wiiproto_req_accel(wdata, false);
387 spin_unlock_irqrestore(&wdata->state.lock, flags);
388
389 hid_hw_close(wdata->hdev);
390}
391
347static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) 392static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
348{ 393{
349 input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], 394 input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
@@ -490,10 +535,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
490 return NULL; 535 return NULL;
491 536
492 wdata->input = input_allocate_device(); 537 wdata->input = input_allocate_device();
493 if (!wdata->input) { 538 if (!wdata->input)
494 kfree(wdata); 539 goto err;
495 return NULL;
496 }
497 540
498 wdata->hdev = hdev; 541 wdata->hdev = hdev;
499 hid_set_drvdata(hdev, wdata); 542 hid_set_drvdata(hdev, wdata);
@@ -513,11 +556,30 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
513 set_bit(wiiproto_keymap[i], wdata->input->keybit); 556 set_bit(wiiproto_keymap[i], wdata->input->keybit);
514 557
515 set_bit(FF_RUMBLE, wdata->input->ffbit); 558 set_bit(FF_RUMBLE, wdata->input->ffbit);
516 if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play)) { 559 if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play))
517 input_free_device(wdata->input); 560 goto err_input;
518 kfree(wdata); 561
519 return NULL; 562 wdata->accel = input_allocate_device();
520 } 563 if (!wdata->accel)
564 goto err_input;
565
566 input_set_drvdata(wdata->accel, wdata);
567 wdata->accel->open = wiimote_accel_open;
568 wdata->accel->close = wiimote_accel_close;
569 wdata->accel->dev.parent = &wdata->hdev->dev;
570 wdata->accel->id.bustype = wdata->hdev->bus;
571 wdata->accel->id.vendor = wdata->hdev->vendor;
572 wdata->accel->id.product = wdata->hdev->product;
573 wdata->accel->id.version = wdata->hdev->version;
574 wdata->accel->name = WIIMOTE_NAME " Accelerometer";
575
576 set_bit(EV_ABS, wdata->accel->evbit);
577 set_bit(ABS_RX, wdata->accel->absbit);
578 set_bit(ABS_RY, wdata->accel->absbit);
579 set_bit(ABS_RZ, wdata->accel->absbit);
580 input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
581 input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
582 input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
521 583
522 spin_lock_init(&wdata->qlock); 584 spin_lock_init(&wdata->qlock);
523 INIT_WORK(&wdata->worker, wiimote_worker); 585 INIT_WORK(&wdata->worker, wiimote_worker);
@@ -525,12 +587,19 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
525 spin_lock_init(&wdata->state.lock); 587 spin_lock_init(&wdata->state.lock);
526 588
527 return wdata; 589 return wdata;
590
591err_input:
592 input_free_device(wdata->input);
593err:
594 kfree(wdata);
595 return NULL;
528} 596}
529 597
530static void wiimote_destroy(struct wiimote_data *wdata) 598static void wiimote_destroy(struct wiimote_data *wdata)
531{ 599{
532 wiimote_leds_destroy(wdata); 600 wiimote_leds_destroy(wdata);
533 601
602 input_unregister_device(wdata->accel);
534 input_unregister_device(wdata->input); 603 input_unregister_device(wdata->input);
535 cancel_work_sync(&wdata->worker); 604 cancel_work_sync(&wdata->worker);
536 hid_hw_stop(wdata->hdev); 605 hid_hw_stop(wdata->hdev);
@@ -562,12 +631,18 @@ static int wiimote_hid_probe(struct hid_device *hdev,
562 goto err; 631 goto err;
563 } 632 }
564 633
565 ret = input_register_device(wdata->input); 634 ret = input_register_device(wdata->accel);
566 if (ret) { 635 if (ret) {
567 hid_err(hdev, "Cannot register input device\n"); 636 hid_err(hdev, "Cannot register input device\n");
568 goto err_stop; 637 goto err_stop;
569 } 638 }
570 639
640 ret = input_register_device(wdata->input);
641 if (ret) {
642 hid_err(hdev, "Cannot register input device\n");
643 goto err_input;
644 }
645
571 ret = wiimote_leds_create(wdata); 646 ret = wiimote_leds_create(wdata);
572 if (ret) 647 if (ret)
573 goto err_free; 648 goto err_free;
@@ -585,9 +660,13 @@ err_free:
585 wiimote_destroy(wdata); 660 wiimote_destroy(wdata);
586 return ret; 661 return ret;
587 662
663err_input:
664 input_unregister_device(wdata->accel);
665 wdata->accel = NULL;
588err_stop: 666err_stop:
589 hid_hw_stop(hdev); 667 hid_hw_stop(hdev);
590err: 668err:
669 input_free_device(wdata->accel);
591 input_free_device(wdata->input); 670 input_free_device(wdata->input);
592 kfree(wdata); 671 kfree(wdata);
593 return ret; 672 return ret;