diff options
Diffstat (limited to 'drivers/hid/hid-wiimote-ext.c')
-rw-r--r-- | drivers/hid/hid-wiimote-ext.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index 0a1805c9b0e5..bc85bf29062e 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c | |||
@@ -28,12 +28,14 @@ struct wiimote_ext { | |||
28 | bool mp_plugged; | 28 | bool mp_plugged; |
29 | bool motionp; | 29 | bool motionp; |
30 | __u8 ext_type; | 30 | __u8 ext_type; |
31 | __u16 calib[4][3]; | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | enum wiiext_type { | 34 | enum wiiext_type { |
34 | WIIEXT_NONE, /* placeholder */ | 35 | WIIEXT_NONE, /* placeholder */ |
35 | WIIEXT_CLASSIC, /* Nintendo classic controller */ | 36 | WIIEXT_CLASSIC, /* Nintendo classic controller */ |
36 | WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ | 37 | WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ |
38 | WIIEXT_BALANCE_BOARD, /* Nintendo balance board controller */ | ||
37 | }; | 39 | }; |
38 | 40 | ||
39 | enum wiiext_keys { | 41 | enum wiiext_keys { |
@@ -126,6 +128,7 @@ error: | |||
126 | static __u8 ext_read(struct wiimote_ext *ext) | 128 | static __u8 ext_read(struct wiimote_ext *ext) |
127 | { | 129 | { |
128 | ssize_t ret; | 130 | ssize_t ret; |
131 | __u8 buf[24], i, j, offs = 0; | ||
129 | __u8 rmem[2], wmem; | 132 | __u8 rmem[2], wmem; |
130 | __u8 type = WIIEXT_NONE; | 133 | __u8 type = WIIEXT_NONE; |
131 | 134 | ||
@@ -151,6 +154,28 @@ static __u8 ext_read(struct wiimote_ext *ext) | |||
151 | type = WIIEXT_NUNCHUCK; | 154 | type = WIIEXT_NUNCHUCK; |
152 | else if (rmem[0] == 0x01 && rmem[1] == 0x01) | 155 | else if (rmem[0] == 0x01 && rmem[1] == 0x01) |
153 | type = WIIEXT_CLASSIC; | 156 | type = WIIEXT_CLASSIC; |
157 | else if (rmem[0] == 0x04 && rmem[1] == 0x02) | ||
158 | type = WIIEXT_BALANCE_BOARD; | ||
159 | } | ||
160 | |||
161 | /* get balance board calibration data */ | ||
162 | if (type == WIIEXT_BALANCE_BOARD) { | ||
163 | ret = wiimote_cmd_read(ext->wdata, 0xa40024, buf, 12); | ||
164 | ret += wiimote_cmd_read(ext->wdata, 0xa40024 + 12, | ||
165 | buf + 12, 12); | ||
166 | |||
167 | if (ret != 24) { | ||
168 | type = WIIEXT_NONE; | ||
169 | } else { | ||
170 | for (i = 0; i < 3; i++) { | ||
171 | for (j = 0; j < 4; j++) { | ||
172 | ext->calib[j][i] = buf[offs]; | ||
173 | ext->calib[j][i] <<= 8; | ||
174 | ext->calib[j][i] |= buf[offs + 1]; | ||
175 | offs += 2; | ||
176 | } | ||
177 | } | ||
178 | } | ||
154 | } | 179 | } |
155 | 180 | ||
156 | wiimote_cmd_release(ext->wdata); | 181 | wiimote_cmd_release(ext->wdata); |
@@ -509,6 +534,71 @@ static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) | |||
509 | input_sync(ext->input); | 534 | input_sync(ext->input); |
510 | } | 535 | } |
511 | 536 | ||
537 | static void handler_balance_board(struct wiimote_ext *ext, const __u8 *payload) | ||
538 | { | ||
539 | __s32 val[4], tmp; | ||
540 | unsigned int i; | ||
541 | |||
542 | /* Byte | 8 7 6 5 4 3 2 1 | | ||
543 | * -----+--------------------------+ | ||
544 | * 1 | Top Right <15:8> | | ||
545 | * 2 | Top Right <7:0> | | ||
546 | * -----+--------------------------+ | ||
547 | * 3 | Bottom Right <15:8> | | ||
548 | * 4 | Bottom Right <7:0> | | ||
549 | * -----+--------------------------+ | ||
550 | * 5 | Top Left <15:8> | | ||
551 | * 6 | Top Left <7:0> | | ||
552 | * -----+--------------------------+ | ||
553 | * 7 | Bottom Left <15:8> | | ||
554 | * 8 | Bottom Left <7:0> | | ||
555 | * -----+--------------------------+ | ||
556 | * | ||
557 | * These values represent the weight-measurements of the Wii-balance | ||
558 | * board with 16bit precision. | ||
559 | * | ||
560 | * The balance-board is never reported interleaved with motionp. | ||
561 | */ | ||
562 | |||
563 | val[0] = payload[0]; | ||
564 | val[0] <<= 8; | ||
565 | val[0] |= payload[1]; | ||
566 | |||
567 | val[1] = payload[2]; | ||
568 | val[1] <<= 8; | ||
569 | val[1] |= payload[3]; | ||
570 | |||
571 | val[2] = payload[4]; | ||
572 | val[2] <<= 8; | ||
573 | val[2] |= payload[5]; | ||
574 | |||
575 | val[3] = payload[6]; | ||
576 | val[3] <<= 8; | ||
577 | val[3] |= payload[7]; | ||
578 | |||
579 | /* apply calibration data */ | ||
580 | for (i = 0; i < 4; i++) { | ||
581 | if (val[i] < ext->calib[i][1]) { | ||
582 | tmp = val[i] - ext->calib[i][0]; | ||
583 | tmp *= 1700; | ||
584 | tmp /= ext->calib[i][1] - ext->calib[i][0]; | ||
585 | } else { | ||
586 | tmp = val[i] - ext->calib[i][1]; | ||
587 | tmp *= 1700; | ||
588 | tmp /= ext->calib[i][2] - ext->calib[i][1]; | ||
589 | tmp += 1700; | ||
590 | } | ||
591 | val[i] = tmp; | ||
592 | } | ||
593 | |||
594 | input_report_abs(ext->input, ABS_HAT0X, val[0]); | ||
595 | input_report_abs(ext->input, ABS_HAT0Y, val[1]); | ||
596 | input_report_abs(ext->input, ABS_HAT1X, val[2]); | ||
597 | input_report_abs(ext->input, ABS_HAT1Y, val[3]); | ||
598 | |||
599 | input_sync(ext->input); | ||
600 | } | ||
601 | |||
512 | /* call this with state.lock spinlock held */ | 602 | /* call this with state.lock spinlock held */ |
513 | void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) | 603 | void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) |
514 | { | 604 | { |
@@ -523,6 +613,8 @@ void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) | |||
523 | handler_nunchuck(ext, payload); | 613 | handler_nunchuck(ext, payload); |
524 | } else if (ext->ext_type == WIIEXT_CLASSIC) { | 614 | } else if (ext->ext_type == WIIEXT_CLASSIC) { |
525 | handler_classic(ext, payload); | 615 | handler_classic(ext, payload); |
616 | } else if (ext->ext_type == WIIEXT_BALANCE_BOARD) { | ||
617 | handler_balance_board(ext, payload); | ||
526 | } | 618 | } |
527 | } | 619 | } |
528 | 620 | ||
@@ -551,6 +643,11 @@ static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, | |||
551 | return sprintf(buf, "motionp+classic\n"); | 643 | return sprintf(buf, "motionp+classic\n"); |
552 | else | 644 | else |
553 | return sprintf(buf, "classic\n"); | 645 | return sprintf(buf, "classic\n"); |
646 | } else if (type == WIIEXT_BALANCE_BOARD) { | ||
647 | if (motionp) | ||
648 | return sprintf(buf, "motionp+balanceboard\n"); | ||
649 | else | ||
650 | return sprintf(buf, "balanceboard\n"); | ||
554 | } else { | 651 | } else { |
555 | if (motionp) | 652 | if (motionp) |
556 | return sprintf(buf, "motionp\n"); | 653 | return sprintf(buf, "motionp\n"); |