diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/hid-wiimote-ext.c | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index ceec0cef326..f05f1549d94 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c | |||
@@ -36,6 +36,17 @@ enum wiiext_type { | |||
36 | WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ | 36 | WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | enum wiiext_keys { | ||
40 | WIIEXT_KEY_C, | ||
41 | WIIEXT_KEY_Z, | ||
42 | WIIEXT_KEY_COUNT | ||
43 | }; | ||
44 | |||
45 | static __u16 wiiext_keymap[] = { | ||
46 | BTN_C, /* WIIEXT_KEY_C */ | ||
47 | BTN_Z, /* WIIEXT_KEY_Z */ | ||
48 | }; | ||
49 | |||
39 | /* diable all extensions */ | 50 | /* diable all extensions */ |
40 | static void ext_disable(struct wiimote_ext *ext) | 51 | static void ext_disable(struct wiimote_ext *ext) |
41 | { | 52 | { |
@@ -272,6 +283,82 @@ static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) | |||
272 | 283 | ||
273 | static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) | 284 | static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) |
274 | { | 285 | { |
286 | __s16 x, y, z, bx, by; | ||
287 | |||
288 | /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 | | ||
289 | * -----+----------+---------+---------+----+-----+ | ||
290 | * 1 | Button X <7:0> | | ||
291 | * 2 | Button Y <7:0> | | ||
292 | * -----+----------+---------+---------+----+-----+ | ||
293 | * 3 | Speed X <9:2> | | ||
294 | * 4 | Speed Y <9:2> | | ||
295 | * 5 | Speed Z <9:2> | | ||
296 | * -----+----------+---------+---------+----+-----+ | ||
297 | * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ | | ||
298 | * -----+----------+---------+---------+----+-----+ | ||
299 | * Button X/Y is the analog stick. Speed X, Y and Z are the | ||
300 | * accelerometer data in the same format as the wiimote's accelerometer. | ||
301 | * The 6th byte contains the LSBs of the accelerometer data. | ||
302 | * BC and BZ are the C and Z buttons: 0 means pressed | ||
303 | * | ||
304 | * If reported interleaved with motionp, then the layout changes. The | ||
305 | * 5th and 6th byte changes to: | ||
306 | * -----+-----------------------------------+-----+ | ||
307 | * 5 | Speed Z <9:3> | EXT | | ||
308 | * -----+--------+-----+-----+----+----+----+-----+ | ||
309 | * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 | | ||
310 | * -----+--------+-----+-----+----+----+----+-----+ | ||
311 | * All three accelerometer values lose their LSB. The other data is | ||
312 | * still available but slightly moved. | ||
313 | * | ||
314 | * Center data for button values is 128. Center value for accelerometer | ||
315 | * values it 512 / 0x200 | ||
316 | */ | ||
317 | |||
318 | bx = payload[0]; | ||
319 | by = payload[1]; | ||
320 | bx -= 128; | ||
321 | by -= 128; | ||
322 | |||
323 | x = payload[2] << 2; | ||
324 | y = payload[3] << 2; | ||
325 | z = payload[4] << 2; | ||
326 | |||
327 | if (ext->motionp) { | ||
328 | x |= (payload[5] >> 3) & 0x02; | ||
329 | y |= (payload[5] >> 4) & 0x02; | ||
330 | z &= ~0x4; | ||
331 | z |= (payload[5] >> 5) & 0x06; | ||
332 | } else { | ||
333 | x |= (payload[5] >> 2) & 0x03; | ||
334 | y |= (payload[5] >> 4) & 0x03; | ||
335 | z |= (payload[5] >> 6) & 0x03; | ||
336 | } | ||
337 | |||
338 | x -= 0x200; | ||
339 | y -= 0x200; | ||
340 | z -= 0x200; | ||
341 | |||
342 | input_report_abs(ext->input, ABS_HAT0X, bx); | ||
343 | input_report_abs(ext->input, ABS_HAT0Y, by); | ||
344 | |||
345 | input_report_abs(ext->input, ABS_RX, x); | ||
346 | input_report_abs(ext->input, ABS_RY, y); | ||
347 | input_report_abs(ext->input, ABS_RZ, z); | ||
348 | |||
349 | if (ext->motionp) { | ||
350 | input_report_key(ext->input, | ||
351 | wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04)); | ||
352 | input_report_key(ext->input, | ||
353 | wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08)); | ||
354 | } else { | ||
355 | input_report_key(ext->input, | ||
356 | wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01)); | ||
357 | input_report_key(ext->input, | ||
358 | wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02)); | ||
359 | } | ||
360 | |||
361 | input_sync(ext->input); | ||
275 | } | 362 | } |
276 | 363 | ||
277 | static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) | 364 | static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) |
@@ -383,7 +470,7 @@ int wiiext_init(struct wiimote_data *wdata) | |||
383 | { | 470 | { |
384 | struct wiimote_ext *ext; | 471 | struct wiimote_ext *ext; |
385 | unsigned long flags; | 472 | unsigned long flags; |
386 | int ret; | 473 | int ret, i; |
387 | 474 | ||
388 | ext = kzalloc(sizeof(*ext), GFP_KERNEL); | 475 | ext = kzalloc(sizeof(*ext), GFP_KERNEL); |
389 | if (!ext) | 476 | if (!ext) |
@@ -408,6 +495,22 @@ int wiiext_init(struct wiimote_data *wdata) | |||
408 | ext->input->id.version = wdata->hdev->version; | 495 | ext->input->id.version = wdata->hdev->version; |
409 | ext->input->name = WIIMOTE_NAME " Extension"; | 496 | ext->input->name = WIIMOTE_NAME " Extension"; |
410 | 497 | ||
498 | set_bit(EV_KEY, ext->input->evbit); | ||
499 | for (i = 0; i < WIIEXT_KEY_COUNT; ++i) | ||
500 | set_bit(wiiext_keymap[i], ext->input->keybit); | ||
501 | |||
502 | set_bit(EV_ABS, ext->input->evbit); | ||
503 | set_bit(ABS_HAT0X, ext->input->absbit); | ||
504 | set_bit(ABS_HAT0Y, ext->input->absbit); | ||
505 | input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4); | ||
506 | input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4); | ||
507 | set_bit(ABS_RX, ext->input->absbit); | ||
508 | set_bit(ABS_RY, ext->input->absbit); | ||
509 | set_bit(ABS_RZ, ext->input->absbit); | ||
510 | input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4); | ||
511 | input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4); | ||
512 | input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4); | ||
513 | |||
411 | ret = input_register_device(ext->input); | 514 | ret = input_register_device(ext->input); |
412 | if (ret) { | 515 | if (ret) { |
413 | input_free_device(ext->input); | 516 | input_free_device(ext->input); |