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 | |
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>
-rw-r--r-- | drivers/hid/hid-wiimote-core.c | 101 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 123 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.h | 2 |
3 files changed, 140 insertions, 86 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 4f58c7827395..7c703e1f90d8 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c | |||
@@ -236,7 +236,7 @@ void wiiproto_req_status(struct wiimote_data *wdata) | |||
236 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 236 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
237 | } | 237 | } |
238 | 238 | ||
239 | static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) | 239 | void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) |
240 | { | 240 | { |
241 | accel = !!accel; | 241 | accel = !!accel; |
242 | if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | 242 | if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) |
@@ -528,28 +528,6 @@ unlock: | |||
528 | return ret; | 528 | return ret; |
529 | } | 529 | } |
530 | 530 | ||
531 | static int wiimote_accel_open(struct input_dev *dev) | ||
532 | { | ||
533 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
534 | unsigned long flags; | ||
535 | |||
536 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
537 | wiiproto_req_accel(wdata, true); | ||
538 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static void wiimote_accel_close(struct input_dev *dev) | ||
544 | { | ||
545 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
546 | unsigned long flags; | ||
547 | |||
548 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
549 | wiiproto_req_accel(wdata, false); | ||
550 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
551 | } | ||
552 | |||
553 | static int wiimote_ir_open(struct input_dev *dev) | 531 | static int wiimote_ir_open(struct input_dev *dev) |
554 | { | 532 | { |
555 | struct wiimote_data *wdata = input_get_drvdata(dev); | 533 | struct wiimote_data *wdata = input_get_drvdata(dev); |
@@ -581,6 +559,7 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { | |||
581 | WIIMOD_LED2, | 559 | WIIMOD_LED2, |
582 | WIIMOD_LED3, | 560 | WIIMOD_LED3, |
583 | WIIMOD_LED4, | 561 | WIIMOD_LED4, |
562 | WIIMOD_ACCEL, | ||
584 | WIIMOD_NULL, | 563 | WIIMOD_NULL, |
585 | }, | 564 | }, |
586 | [WIIMOTE_DEV_GEN10] = (const __u8[]){ | 565 | [WIIMOTE_DEV_GEN10] = (const __u8[]){ |
@@ -591,6 +570,7 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { | |||
591 | WIIMOD_LED2, | 570 | WIIMOD_LED2, |
592 | WIIMOD_LED3, | 571 | WIIMOD_LED3, |
593 | WIIMOD_LED4, | 572 | WIIMOD_LED4, |
573 | WIIMOD_ACCEL, | ||
594 | WIIMOD_NULL, | 574 | WIIMOD_NULL, |
595 | }, | 575 | }, |
596 | [WIIMOTE_DEV_GEN20] = (const __u8[]){ | 576 | [WIIMOTE_DEV_GEN20] = (const __u8[]){ |
@@ -601,6 +581,7 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { | |||
601 | WIIMOD_LED2, | 581 | WIIMOD_LED2, |
602 | WIIMOD_LED3, | 582 | WIIMOD_LED3, |
603 | WIIMOD_LED4, | 583 | WIIMOD_LED4, |
584 | WIIMOD_ACCEL, | ||
604 | WIIMOD_NULL, | 585 | WIIMOD_NULL, |
605 | }, | 586 | }, |
606 | }; | 587 | }; |
@@ -818,35 +799,17 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | |||
818 | 799 | ||
819 | static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) | 800 | static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) |
820 | { | 801 | { |
821 | __u16 x, y, z; | 802 | const __u8 *iter, *mods; |
822 | 803 | const struct wiimod_ops *ops; | |
823 | if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | ||
824 | return; | ||
825 | |||
826 | /* | ||
827 | * payload is: BB BB XX YY ZZ | ||
828 | * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ | ||
829 | * contain the upper 8 bits of each value. The lower 2 bits are | ||
830 | * contained in the buttons data BB BB. | ||
831 | * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the | ||
832 | * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y | ||
833 | * accel value and bit 6 is the second bit of the Z value. | ||
834 | * The first bit of Y and Z values is not available and always set to 0. | ||
835 | * 0x200 is returned on no movement. | ||
836 | */ | ||
837 | |||
838 | x = payload[2] << 2; | ||
839 | y = payload[3] << 2; | ||
840 | z = payload[4] << 2; | ||
841 | |||
842 | x |= (payload[0] >> 5) & 0x3; | ||
843 | y |= (payload[1] >> 4) & 0x2; | ||
844 | z |= (payload[1] >> 5) & 0x2; | ||
845 | 804 | ||
846 | input_report_abs(wdata->accel, ABS_RX, x - 0x200); | 805 | mods = wiimote_devtype_mods[wdata->state.devtype]; |
847 | input_report_abs(wdata->accel, ABS_RY, y - 0x200); | 806 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { |
848 | input_report_abs(wdata->accel, ABS_RZ, z - 0x200); | 807 | ops = wiimod_table[*iter]; |
849 | input_sync(wdata->accel); | 808 | if (ops->in_accel) { |
809 | ops->in_accel(wdata, payload); | ||
810 | break; | ||
811 | } | ||
812 | } | ||
850 | } | 813 | } |
851 | 814 | ||
852 | #define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | 815 | #define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ |
@@ -1133,31 +1096,9 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
1133 | wdata->hdev = hdev; | 1096 | wdata->hdev = hdev; |
1134 | hid_set_drvdata(hdev, wdata); | 1097 | hid_set_drvdata(hdev, wdata); |
1135 | 1098 | ||
1136 | wdata->accel = input_allocate_device(); | ||
1137 | if (!wdata->accel) | ||
1138 | goto err; | ||
1139 | |||
1140 | input_set_drvdata(wdata->accel, wdata); | ||
1141 | wdata->accel->open = wiimote_accel_open; | ||
1142 | wdata->accel->close = wiimote_accel_close; | ||
1143 | wdata->accel->dev.parent = &wdata->hdev->dev; | ||
1144 | wdata->accel->id.bustype = wdata->hdev->bus; | ||
1145 | wdata->accel->id.vendor = wdata->hdev->vendor; | ||
1146 | wdata->accel->id.product = wdata->hdev->product; | ||
1147 | wdata->accel->id.version = wdata->hdev->version; | ||
1148 | wdata->accel->name = WIIMOTE_NAME " Accelerometer"; | ||
1149 | |||
1150 | set_bit(EV_ABS, wdata->accel->evbit); | ||
1151 | set_bit(ABS_RX, wdata->accel->absbit); | ||
1152 | set_bit(ABS_RY, wdata->accel->absbit); | ||
1153 | set_bit(ABS_RZ, wdata->accel->absbit); | ||
1154 | input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); | ||
1155 | input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); | ||
1156 | input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); | ||
1157 | |||
1158 | wdata->ir = input_allocate_device(); | 1099 | wdata->ir = input_allocate_device(); |
1159 | if (!wdata->ir) | 1100 | if (!wdata->ir) |
1160 | goto err_ir; | 1101 | goto err; |
1161 | 1102 | ||
1162 | input_set_drvdata(wdata->ir, wdata); | 1103 | input_set_drvdata(wdata->ir, wdata); |
1163 | wdata->ir->open = wiimote_ir_open; | 1104 | wdata->ir->open = wiimote_ir_open; |
@@ -1200,8 +1141,6 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
1200 | 1141 | ||
1201 | return wdata; | 1142 | return wdata; |
1202 | 1143 | ||
1203 | err_ir: | ||
1204 | input_free_device(wdata->accel); | ||
1205 | err: | 1144 | err: |
1206 | kfree(wdata); | 1145 | kfree(wdata); |
1207 | return NULL; | 1146 | return NULL; |
@@ -1214,7 +1153,6 @@ static void wiimote_destroy(struct wiimote_data *wdata) | |||
1214 | 1153 | ||
1215 | cancel_work_sync(&wdata->init_worker); | 1154 | cancel_work_sync(&wdata->init_worker); |
1216 | wiimote_modules_unload(wdata); | 1155 | wiimote_modules_unload(wdata); |
1217 | input_unregister_device(wdata->accel); | ||
1218 | input_unregister_device(wdata->ir); | 1156 | input_unregister_device(wdata->ir); |
1219 | cancel_work_sync(&wdata->queue.worker); | 1157 | cancel_work_sync(&wdata->queue.worker); |
1220 | hid_hw_close(wdata->hdev); | 1158 | hid_hw_close(wdata->hdev); |
@@ -1255,12 +1193,6 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1255 | goto err_stop; | 1193 | goto err_stop; |
1256 | } | 1194 | } |
1257 | 1195 | ||
1258 | ret = input_register_device(wdata->accel); | ||
1259 | if (ret) { | ||
1260 | hid_err(hdev, "Cannot register input device\n"); | ||
1261 | goto err_close; | ||
1262 | } | ||
1263 | |||
1264 | ret = input_register_device(wdata->ir); | 1196 | ret = input_register_device(wdata->ir); |
1265 | if (ret) { | 1197 | if (ret) { |
1266 | hid_err(hdev, "Cannot register input device\n"); | 1198 | hid_err(hdev, "Cannot register input device\n"); |
@@ -1287,9 +1219,6 @@ err_free: | |||
1287 | return ret; | 1219 | return ret; |
1288 | 1220 | ||
1289 | err_ir: | 1221 | err_ir: |
1290 | input_unregister_device(wdata->accel); | ||
1291 | wdata->accel = NULL; | ||
1292 | err_close: | ||
1293 | hid_hw_close(hdev); | 1222 | hid_hw_close(hdev); |
1294 | err_stop: | 1223 | err_stop: |
1295 | hid_hw_stop(hdev); | 1224 | hid_hw_stop(hdev); |
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 | }; |
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 66150a693324..8c242e615ab2 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
@@ -133,6 +133,7 @@ enum wiimod_module { | |||
133 | WIIMOD_LED2, | 133 | WIIMOD_LED2, |
134 | WIIMOD_LED3, | 134 | WIIMOD_LED3, |
135 | WIIMOD_LED4, | 135 | WIIMOD_LED4, |
136 | WIIMOD_ACCEL, | ||
136 | WIIMOD_NUM, | 137 | WIIMOD_NUM, |
137 | WIIMOD_NULL = WIIMOD_NUM, | 138 | WIIMOD_NULL = WIIMOD_NUM, |
138 | }; | 139 | }; |
@@ -191,6 +192,7 @@ extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); | |||
191 | extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); | 192 | extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); |
192 | extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); | 193 | extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); |
193 | extern void wiiproto_req_status(struct wiimote_data *wdata); | 194 | extern void wiiproto_req_status(struct wiimote_data *wdata); |
195 | extern void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel); | ||
194 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | 196 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
195 | const __u8 *wmem, __u8 size); | 197 | const __u8 *wmem, __u8 size); |
196 | extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, | 198 | extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, |