aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-09-06 07:50:29 -0400
committerJiri Kosina <jkosina@suse.cz>2011-09-07 07:25:16 -0400
commitefcf91887419ec37ca564073a9fe30db49fe6c7c (patch)
treebb27e060cfb3ac8b9401eef9b828f7ed074b2c3b
parent98a558ae35930e02dfc2dd0a124c93ad39b0828d (diff)
HID: wiimote: Parse accelerometer data
Add parser functions for accelerometer data reported by the wiimote. The data is almost always reported in the same format, so we can use a single handler. However, an own handler function is created for each DRM-mode because when IR and extension support is added, each of them is parsed differently. Also set the appropriate DRM including accelerometer data on DRM requests to actually retrieve the accelerometer data. Data is reported to userspace as ABS_RX/Y/Z values. The values are between -500 and 500 and 0 means no acceleration. See also userspace xwiimote library for data parsing. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-wiimote.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index 9fb7bd63e7f7..de9aadf9218d 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -30,6 +30,7 @@ struct wiimote_buf {
30struct wiimote_state { 30struct wiimote_state {
31 spinlock_t lock; 31 spinlock_t lock;
32 __u8 flags; 32 __u8 flags;
33 __u8 accel_split[2];
33}; 34};
34 35
35struct wiimote_data { 36struct wiimote_data {
@@ -67,6 +68,12 @@ enum wiiproto_reqs {
67 WIIPROTO_REQ_STATUS = 0x20, 68 WIIPROTO_REQ_STATUS = 0x20,
68 WIIPROTO_REQ_RETURN = 0x22, 69 WIIPROTO_REQ_RETURN = 0x22,
69 WIIPROTO_REQ_DRM_K = 0x30, 70 WIIPROTO_REQ_DRM_K = 0x30,
71 WIIPROTO_REQ_DRM_KA = 0x31,
72 WIIPROTO_REQ_DRM_KAI = 0x33,
73 WIIPROTO_REQ_DRM_KAE = 0x35,
74 WIIPROTO_REQ_DRM_KAIE = 0x37,
75 WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
76 WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
70}; 77};
71 78
72enum wiiproto_keys { 79enum wiiproto_keys {
@@ -241,7 +248,10 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
241 */ 248 */
242static __u8 select_drm(struct wiimote_data *wdata) 249static __u8 select_drm(struct wiimote_data *wdata)
243{ 250{
244 return WIIPROTO_REQ_DRM_K; 251 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
252 return WIIPROTO_REQ_DRM_KA;
253 else
254 return WIIPROTO_REQ_DRM_K;
245} 255}
246 256
247static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) 257static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
@@ -416,6 +426,40 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
416 input_sync(wdata->input); 426 input_sync(wdata->input);
417} 427}
418 428
429static void handler_accel(struct wiimote_data *wdata, const __u8 *payload)
430{
431 __u16 x, y, z;
432
433 if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
434 return;
435
436 /*
437 * payload is: BB BB XX YY ZZ
438 * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ
439 * contain the upper 8 bits of each value. The lower 2 bits are
440 * contained in the buttons data BB BB.
441 * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the
442 * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y
443 * accel value and bit 6 is the second bit of the Z value.
444 * The first bit of Y and Z values is not available and always set to 0.
445 * 0x200 is returned on no movement.
446 */
447
448 x = payload[2] << 2;
449 y = payload[3] << 2;
450 z = payload[4] << 2;
451
452 x |= (payload[0] >> 5) & 0x3;
453 y |= (payload[1] >> 4) & 0x2;
454 z |= (payload[1] >> 5) & 0x2;
455
456 input_report_abs(wdata->accel, ABS_RX, x - 0x200);
457 input_report_abs(wdata->accel, ABS_RY, y - 0x200);
458 input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
459 input_sync(wdata->accel);
460}
461
462
419static void handler_status(struct wiimote_data *wdata, const __u8 *payload) 463static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
420{ 464{
421 handler_keys(wdata, payload); 465 handler_keys(wdata, payload);
@@ -436,6 +480,56 @@ static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
436 cmd); 480 cmd);
437} 481}
438 482
483static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload)
484{
485 handler_keys(wdata, payload);
486 handler_accel(wdata, payload);
487}
488
489static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
490{
491 handler_keys(wdata, payload);
492 handler_accel(wdata, payload);
493}
494
495static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
496{
497 handler_keys(wdata, payload);
498 handler_accel(wdata, payload);
499}
500
501static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
502{
503 handler_keys(wdata, payload);
504 handler_accel(wdata, payload);
505}
506
507static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
508{
509 handler_keys(wdata, payload);
510
511 wdata->state.accel_split[0] = payload[2];
512 wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20);
513 wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80);
514}
515
516static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
517{
518 __u8 buf[5];
519
520 handler_keys(wdata, payload);
521
522 wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02);
523 wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08);
524
525 buf[0] = 0;
526 buf[1] = 0;
527 buf[2] = wdata->state.accel_split[0];
528 buf[3] = payload[2];
529 buf[4] = wdata->state.accel_split[1];
530 handler_accel(wdata, buf);
531}
532
439struct wiiproto_handler { 533struct wiiproto_handler {
440 __u8 id; 534 __u8 id;
441 size_t size; 535 size_t size;
@@ -446,6 +540,12 @@ static struct wiiproto_handler handlers[] = {
446 { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, 540 { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
447 { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return }, 541 { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
448 { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, 542 { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
543 { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
544 { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
545 { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
546 { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
547 { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
548 { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
449 { .id = 0 } 549 { .id = 0 }
450}; 550};
451 551