diff options
| -rw-r--r-- | drivers/hid/hid-wiimote.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 59a08933c73c..35dc293db40e 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
| @@ -82,8 +82,10 @@ enum wiiproto_reqs { | |||
| 82 | WIIPROTO_REQ_RUMBLE = 0x10, | 82 | WIIPROTO_REQ_RUMBLE = 0x10, |
| 83 | WIIPROTO_REQ_LED = 0x11, | 83 | WIIPROTO_REQ_LED = 0x11, |
| 84 | WIIPROTO_REQ_DRM = 0x12, | 84 | WIIPROTO_REQ_DRM = 0x12, |
| 85 | WIIPROTO_REQ_IR1 = 0x13, | ||
| 85 | WIIPROTO_REQ_WMEM = 0x16, | 86 | WIIPROTO_REQ_WMEM = 0x16, |
| 86 | WIIPROTO_REQ_RMEM = 0x17, | 87 | WIIPROTO_REQ_RMEM = 0x17, |
| 88 | WIIPROTO_REQ_IR2 = 0x1a, | ||
| 87 | WIIPROTO_REQ_STATUS = 0x20, | 89 | WIIPROTO_REQ_STATUS = 0x20, |
| 88 | WIIPROTO_REQ_DATA = 0x21, | 90 | WIIPROTO_REQ_DATA = 0x21, |
| 89 | WIIPROTO_REQ_RETURN = 0x22, | 91 | WIIPROTO_REQ_RETURN = 0x22, |
| @@ -366,6 +368,28 @@ static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) | |||
| 366 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | 368 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); |
| 367 | } | 369 | } |
| 368 | 370 | ||
| 371 | static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) | ||
| 372 | { | ||
| 373 | __u8 cmd[2]; | ||
| 374 | |||
| 375 | cmd[0] = WIIPROTO_REQ_IR1; | ||
| 376 | cmd[1] = flags; | ||
| 377 | |||
| 378 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
| 379 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
| 380 | } | ||
| 381 | |||
| 382 | static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) | ||
| 383 | { | ||
| 384 | __u8 cmd[2]; | ||
| 385 | |||
| 386 | cmd[0] = WIIPROTO_REQ_IR2; | ||
| 387 | cmd[1] = flags; | ||
| 388 | |||
| 389 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
| 390 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
| 391 | } | ||
| 392 | |||
| 369 | #define wiiproto_req_wreg(wdata, os, buf, sz) \ | 393 | #define wiiproto_req_wreg(wdata, os, buf, sz) \ |
| 370 | wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) | 394 | wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) |
| 371 | 395 | ||
| @@ -416,6 +440,118 @@ static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | |||
| 416 | return ret; | 440 | return ret; |
| 417 | } | 441 | } |
| 418 | 442 | ||
| 443 | static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) | ||
| 444 | { | ||
| 445 | int ret; | ||
| 446 | unsigned long flags; | ||
| 447 | __u8 format = 0; | ||
| 448 | static const __u8 data_enable[] = { 0x01 }; | ||
| 449 | static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, | ||
| 450 | 0x00, 0xaa, 0x00, 0x64 }; | ||
| 451 | static const __u8 data_sens2[] = { 0x63, 0x03 }; | ||
| 452 | static const __u8 data_fin[] = { 0x08 }; | ||
| 453 | |||
| 454 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 455 | |||
| 456 | if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { | ||
| 457 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | |||
| 461 | if (mode == 0) { | ||
| 462 | wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | ||
| 463 | wiiproto_req_ir1(wdata, 0); | ||
| 464 | wiiproto_req_ir2(wdata, 0); | ||
| 465 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
| 466 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 471 | |||
| 472 | ret = wiimote_cmd_acquire(wdata); | ||
| 473 | if (ret) | ||
| 474 | return ret; | ||
| 475 | |||
| 476 | /* send PIXEL CLOCK ENABLE cmd first */ | ||
| 477 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 478 | wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); | ||
| 479 | wiiproto_req_ir1(wdata, 0x06); | ||
| 480 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 481 | |||
| 482 | ret = wiimote_cmd_wait(wdata); | ||
| 483 | if (ret) | ||
| 484 | goto unlock; | ||
| 485 | if (wdata->state.cmd_err) { | ||
| 486 | ret = -EIO; | ||
| 487 | goto unlock; | ||
| 488 | } | ||
| 489 | |||
| 490 | /* enable IR LOGIC */ | ||
| 491 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 492 | wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); | ||
| 493 | wiiproto_req_ir2(wdata, 0x06); | ||
| 494 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 495 | |||
| 496 | ret = wiimote_cmd_wait(wdata); | ||
| 497 | if (ret) | ||
| 498 | goto unlock; | ||
| 499 | if (wdata->state.cmd_err) { | ||
| 500 | ret = -EIO; | ||
| 501 | goto unlock; | ||
| 502 | } | ||
| 503 | |||
| 504 | /* enable IR cam but do not make it send data, yet */ | ||
| 505 | ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, | ||
| 506 | sizeof(data_enable)); | ||
| 507 | if (ret) | ||
| 508 | goto unlock; | ||
| 509 | |||
| 510 | /* write first sensitivity block */ | ||
| 511 | ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, | ||
| 512 | sizeof(data_sens1)); | ||
| 513 | if (ret) | ||
| 514 | goto unlock; | ||
| 515 | |||
| 516 | /* write second sensitivity block */ | ||
| 517 | ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, | ||
| 518 | sizeof(data_sens2)); | ||
| 519 | if (ret) | ||
| 520 | goto unlock; | ||
| 521 | |||
| 522 | /* put IR cam into desired state */ | ||
| 523 | switch (mode) { | ||
| 524 | case WIIPROTO_FLAG_IR_FULL: | ||
| 525 | format = 5; | ||
| 526 | break; | ||
| 527 | case WIIPROTO_FLAG_IR_EXT: | ||
| 528 | format = 3; | ||
| 529 | break; | ||
| 530 | case WIIPROTO_FLAG_IR_BASIC: | ||
| 531 | format = 1; | ||
| 532 | break; | ||
| 533 | } | ||
| 534 | ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); | ||
| 535 | if (ret) | ||
| 536 | goto unlock; | ||
| 537 | |||
| 538 | /* make IR cam send data */ | ||
| 539 | ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); | ||
| 540 | if (ret) | ||
| 541 | goto unlock; | ||
| 542 | |||
| 543 | /* request new DRM mode compatible to IR mode */ | ||
| 544 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 545 | wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | ||
| 546 | wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; | ||
| 547 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
| 548 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 549 | |||
| 550 | unlock: | ||
| 551 | wiimote_cmd_release(wdata); | ||
| 552 | return ret; | ||
| 553 | } | ||
| 554 | |||
| 419 | static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) | 555 | static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) |
| 420 | { | 556 | { |
| 421 | struct wiimote_data *wdata; | 557 | struct wiimote_data *wdata; |
