diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-05-05 17:12:55 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-06-03 05:07:02 -0400 |
commit | 0ea1675723021bc412bc9ea5d601e2b5660b5f8c (patch) | |
tree | ac28f5e21ce9ba1bfa5c0723695f12a015e02b27 /drivers/hid/hid-wiimote-modules.c | |
parent | 6c5ae01805e2cc1810328b538ccb2376b5f8bd9f (diff) |
HID: wiimote: convert ACCEL to module
Accelerometer data is very similar to KEYS handling. Therefore, convert
all ACCEL related handling into a sub-device module similar to KEYS.
This doesn't change any semantics but only moves code over to
wiimote-modules.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-wiimote-modules.c')
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index f96de153971c..fbc09c8810b8 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c | |||
@@ -404,6 +404,128 @@ static const struct wiimod_ops wiimod_leds[4] = { | |||
404 | }, | 404 | }, |
405 | }; | 405 | }; |
406 | 406 | ||
407 | /* | ||
408 | * Accelerometer | ||
409 | * 3 axis accelerometer data is part of nearly all DRMs. If not supported by a | ||
410 | * device, it's mostly cleared to 0. This module parses this data and provides | ||
411 | * it via a separate input device. | ||
412 | */ | ||
413 | |||
414 | static void wiimod_accel_in_accel(struct wiimote_data *wdata, | ||
415 | const __u8 *accel) | ||
416 | { | ||
417 | __u16 x, y, z; | ||
418 | |||
419 | if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | ||
420 | return; | ||
421 | |||
422 | /* | ||
423 | * payload is: BB BB XX YY ZZ | ||
424 | * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ | ||
425 | * contain the upper 8 bits of each value. The lower 2 bits are | ||
426 | * contained in the buttons data BB BB. | ||
427 | * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the | ||
428 | * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y | ||
429 | * accel value and bit 6 is the second bit of the Z value. | ||
430 | * The first bit of Y and Z values is not available and always set to 0. | ||
431 | * 0x200 is returned on no movement. | ||
432 | */ | ||
433 | |||
434 | x = accel[2] << 2; | ||
435 | y = accel[3] << 2; | ||
436 | z = accel[4] << 2; | ||
437 | |||
438 | x |= (accel[0] >> 5) & 0x3; | ||
439 | y |= (accel[1] >> 4) & 0x2; | ||
440 | z |= (accel[1] >> 5) & 0x2; | ||
441 | |||
442 | input_report_abs(wdata->accel, ABS_RX, x - 0x200); | ||
443 | input_report_abs(wdata->accel, ABS_RY, y - 0x200); | ||
444 | input_report_abs(wdata->accel, ABS_RZ, z - 0x200); | ||
445 | input_sync(wdata->accel); | ||
446 | } | ||
447 | |||
448 | static int wiimod_accel_open(struct input_dev *dev) | ||
449 | { | ||
450 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
451 | unsigned long flags; | ||
452 | |||
453 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
454 | wiiproto_req_accel(wdata, true); | ||
455 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static void wiimod_accel_close(struct input_dev *dev) | ||
461 | { | ||
462 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
463 | unsigned long flags; | ||
464 | |||
465 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
466 | wiiproto_req_accel(wdata, false); | ||
467 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
468 | } | ||
469 | |||
470 | static int wiimod_accel_probe(const struct wiimod_ops *ops, | ||
471 | struct wiimote_data *wdata) | ||
472 | { | ||
473 | int ret; | ||
474 | |||
475 | wdata->accel = input_allocate_device(); | ||
476 | if (!wdata->accel) | ||
477 | return -ENOMEM; | ||
478 | |||
479 | input_set_drvdata(wdata->accel, wdata); | ||
480 | wdata->accel->open = wiimod_accel_open; | ||
481 | wdata->accel->close = wiimod_accel_close; | ||
482 | wdata->accel->dev.parent = &wdata->hdev->dev; | ||
483 | wdata->accel->id.bustype = wdata->hdev->bus; | ||
484 | wdata->accel->id.vendor = wdata->hdev->vendor; | ||
485 | wdata->accel->id.product = wdata->hdev->product; | ||
486 | wdata->accel->id.version = wdata->hdev->version; | ||
487 | wdata->accel->name = WIIMOTE_NAME " Accelerometer"; | ||
488 | |||
489 | set_bit(EV_ABS, wdata->accel->evbit); | ||
490 | set_bit(ABS_RX, wdata->accel->absbit); | ||
491 | set_bit(ABS_RY, wdata->accel->absbit); | ||
492 | set_bit(ABS_RZ, wdata->accel->absbit); | ||
493 | input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); | ||
494 | input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); | ||
495 | input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); | ||
496 | |||
497 | ret = input_register_device(wdata->accel); | ||
498 | if (ret) { | ||
499 | hid_err(wdata->hdev, "cannot register input device\n"); | ||
500 | goto err_free; | ||
501 | } | ||
502 | |||
503 | return 0; | ||
504 | |||
505 | err_free: | ||
506 | input_free_device(wdata->accel); | ||
507 | wdata->accel = NULL; | ||
508 | return ret; | ||
509 | } | ||
510 | |||
511 | static void wiimod_accel_remove(const struct wiimod_ops *ops, | ||
512 | struct wiimote_data *wdata) | ||
513 | { | ||
514 | if (!wdata->accel) | ||
515 | return; | ||
516 | |||
517 | input_unregister_device(wdata->accel); | ||
518 | wdata->accel = NULL; | ||
519 | } | ||
520 | |||
521 | static const struct wiimod_ops wiimod_accel = { | ||
522 | .flags = 0, | ||
523 | .arg = 0, | ||
524 | .probe = wiimod_accel_probe, | ||
525 | .remove = wiimod_accel_remove, | ||
526 | .in_accel = wiimod_accel_in_accel, | ||
527 | }; | ||
528 | |||
407 | /* module table */ | 529 | /* module table */ |
408 | 530 | ||
409 | const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { | 531 | const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { |
@@ -414,4 +536,5 @@ const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { | |||
414 | [WIIMOD_LED2] = &wiimod_leds[1], | 536 | [WIIMOD_LED2] = &wiimod_leds[1], |
415 | [WIIMOD_LED3] = &wiimod_leds[2], | 537 | [WIIMOD_LED3] = &wiimod_leds[2], |
416 | [WIIMOD_LED4] = &wiimod_leds[3], | 538 | [WIIMOD_LED4] = &wiimod_leds[3], |
539 | [WIIMOD_ACCEL] = &wiimod_accel, | ||
417 | }; | 540 | }; |