aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote.c136
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
371static 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
382static 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
443static 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
550unlock:
551 wiimote_cmd_release(wdata);
552 return ret;
553}
554
419static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) 555static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
420{ 556{
421 struct wiimote_data *wdata; 557 struct wiimote_data *wdata;