aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-05-05 17:12:55 -0400
committerJiri Kosina <jkosina@suse.cz>2013-06-03 05:07:02 -0400
commit0ea1675723021bc412bc9ea5d601e2b5660b5f8c (patch)
treeac28f5e21ce9ba1bfa5c0723695f12a015e02b27 /drivers/hid
parent6c5ae01805e2cc1810328b538ccb2376b5f8bd9f (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')
-rw-r--r--drivers/hid/hid-wiimote-core.c101
-rw-r--r--drivers/hid/hid-wiimote-modules.c123
-rw-r--r--drivers/hid/hid-wiimote.h2
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
239static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) 239void 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
531static 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
543static 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
553static int wiimote_ir_open(struct input_dev *dev) 531static 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
819static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) 800static 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
1203err_ir:
1204 input_free_device(wdata->accel);
1205err: 1144err:
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
1289err_ir: 1221err_ir:
1290 input_unregister_device(wdata->accel);
1291 wdata->accel = NULL;
1292err_close:
1293 hid_hw_close(hdev); 1222 hid_hw_close(hdev);
1294err_stop: 1223err_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
414static 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
448static 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
460static 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
470static 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
505err_free:
506 input_free_device(wdata->accel);
507 wdata->accel = NULL;
508 return ret;
509}
510
511static 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
521static 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
409const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { 531const 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);
191extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); 192extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble);
192extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); 193extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds);
193extern void wiiproto_req_status(struct wiimote_data *wdata); 194extern void wiiproto_req_status(struct wiimote_data *wdata);
195extern void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel);
194extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, 196extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
195 const __u8 *wmem, __u8 size); 197 const __u8 *wmem, __u8 size);
196extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, 198extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,