Skip to content

Commit f722052

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.2/wiimote' into for-linus
- support for DJ Hero turntable (Joshua Jun)
2 parents ab6847b + 05086f3 commit f722052

File tree

3 files changed

+233
-0
lines changed

3 files changed

+233
-0
lines changed

drivers/hid/hid-wiimote-core.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
458458
if (rmem[0] == 0x00 && rmem[1] == 0x00 &&
459459
rmem[4] == 0x01 && rmem[5] == 0x03)
460460
return WIIMOTE_EXT_GUITAR;
461+
if (rmem[0] == 0x03 && rmem[1] == 0x00 &&
462+
rmem[4] == 0x01 && rmem[5] == 0x03)
463+
return WIIMOTE_EXT_TURNTABLE;
461464

462465
return WIIMOTE_EXT_UNKNOWN;
463466
}
@@ -495,6 +498,7 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
495498
case WIIMOTE_EXT_GUITAR:
496499
wmem = 0x07;
497500
break;
501+
case WIIMOTE_EXT_TURNTABLE:
498502
case WIIMOTE_EXT_NUNCHUK:
499503
wmem = 0x05;
500504
break;
@@ -1082,6 +1086,7 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
10821086
[WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
10831087
[WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums",
10841088
[WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar",
1089+
[WIIMOTE_EXT_TURNTABLE] = "Nintendo Wii Turntable"
10851090
};
10861091

10871092
/*
@@ -1669,6 +1674,8 @@ static ssize_t wiimote_ext_show(struct device *dev,
16691674
return sprintf(buf, "drums\n");
16701675
case WIIMOTE_EXT_GUITAR:
16711676
return sprintf(buf, "guitar\n");
1677+
case WIIMOTE_EXT_TURNTABLE:
1678+
return sprintf(buf, "turntable\n");
16721679
case WIIMOTE_EXT_UNKNOWN:
16731680
default:
16741681
return sprintf(buf, "unknown\n");

drivers/hid/hid-wiimote-modules.c

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,6 +2403,230 @@ static const struct wiimod_ops wiimod_guitar = {
24032403
.in_ext = wiimod_guitar_in_ext,
24042404
};
24052405

2406+
/*
2407+
* Turntable
2408+
* DJ Hero came with a Turntable Controller that was plugged in
2409+
* as an extension.
2410+
* We create a separate device for turntables and report all information via this
2411+
* input device.
2412+
*/
2413+
2414+
enum wiimod_turntable_keys {
2415+
WIIMOD_TURNTABLE_KEY_G_RIGHT,
2416+
WIIMOD_TURNTABLE_KEY_R_RIGHT,
2417+
WIIMOD_TURNTABLE_KEY_B_RIGHT,
2418+
WIIMOD_TURNTABLE_KEY_G_LEFT,
2419+
WIIMOD_TURNTABLE_KEY_R_LEFT,
2420+
WIIMOD_TURNTABLE_KEY_B_LEFT,
2421+
WIIMOD_TURNTABLE_KEY_EUPHORIA,
2422+
WIIMOD_TURNTABLE_KEY_PLUS,
2423+
WIIMOD_TURNTABLE_KEY_MINUS,
2424+
WIIMOD_TURNTABLE_KEY_NUM
2425+
};
2426+
2427+
static const __u16 wiimod_turntable_map[] = {
2428+
BTN_1, /* WIIMOD_TURNTABLE_KEY_G_RIGHT */
2429+
BTN_2, /* WIIMOD_TURNTABLE_KEY_R_RIGHT */
2430+
BTN_3, /* WIIMOD_TURNTABLE_KEY_B_RIGHT */
2431+
BTN_4, /* WIIMOD_TURNTABLE_KEY_G_LEFT */
2432+
BTN_5, /* WIIMOD_TURNTABLE_KEY_R_LEFT */
2433+
BTN_6, /* WIIMOD_TURNTABLE_KEY_B_LEFT */
2434+
BTN_7, /* WIIMOD_TURNTABLE_KEY_EUPHORIA */
2435+
BTN_START, /* WIIMOD_TURNTABLE_KEY_PLUS */
2436+
BTN_SELECT, /* WIIMOD_TURNTABLE_KEY_MINUS */
2437+
};
2438+
2439+
static void wiimod_turntable_in_ext(struct wiimote_data *wdata, const __u8 *ext)
2440+
{
2441+
__u8 be, cs, sx, sy, ed, rtt, rbg, rbr, rbb, ltt, lbg, lbr, lbb, bp, bm;
2442+
/*
2443+
* Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
2444+
*------+------+-----+-----+-----+-----+------+------+--------+
2445+
* 0 | RTT<4:3> | SX <5:0> |
2446+
* 1 | RTT<2:1> | SY <5:0> |
2447+
*------+------+-----+-----+-----+-----+------+------+--------+
2448+
* 2 |RTT<0>| ED<4:3> | CS<3:0> | RTT<5> |
2449+
*------+------+-----+-----+-----+-----+------+------+--------+
2450+
* 3 | ED<2:0> | LTT<4:0> |
2451+
*------+------+-----+-----+-----+-----+------+------+--------+
2452+
* 4 | 0 | 0 | LBR | B- | 0 | B+ | RBR | LTT<5> |
2453+
*------+------+-----+-----+-----+-----+------+------+--------+
2454+
* 5 | LBB | 0 | RBG | BE | LBG | RBB | 0 | 0 |
2455+
*------+------+-----+-----+-----+-----+------+------+--------+
2456+
* All pressed buttons are 0
2457+
*
2458+
* With Motion+ enabled, it will look like this:
2459+
* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
2460+
*------+------+-----+-----+-----+-----+------+------+--------+
2461+
* 1 | RTT<4:3> | SX <5:1> | 0 |
2462+
* 2 | RTT<2:1> | SY <5:1> | 0 |
2463+
*------+------+-----+-----+-----+-----+------+------+--------+
2464+
* 3 |RTT<0>| ED<4:3> | CS<3:0> | RTT<5> |
2465+
*------+------+-----+-----+-----+-----+------+------+--------+
2466+
* 4 | ED<2:0> | LTT<4:0> |
2467+
*------+------+-----+-----+-----+-----+------+------+--------+
2468+
* 5 | 0 | 0 | LBR | B- | 0 | B+ | RBR | XXXX |
2469+
*------+------+-----+-----+-----+-----+------+------+--------+
2470+
* 6 | LBB | 0 | RBG | BE | LBG | RBB | XXXX | XXXX |
2471+
*------+------+-----+-----+-----+-----+------+------+--------+
2472+
*/
2473+
2474+
be = !(ext[5] & 0x10);
2475+
cs = ((ext[2] & 0x1e));
2476+
sx = ext[0] & 0x3f;
2477+
sy = ext[1] & 0x3f;
2478+
ed = (ext[3] & 0xe0) >> 5;
2479+
rtt = ((ext[2] & 0x01) << 5 | (ext[0] & 0xc0) >> 3 | (ext[1] & 0xc0) >> 5 | ( ext[2] & 0x80 ) >> 7);
2480+
ltt = ((ext[4] & 0x01) << 5 | (ext[3] & 0x1f));
2481+
rbg = !(ext[5] & 0x20);
2482+
rbr = !(ext[4] & 0x02);
2483+
rbb = !(ext[5] & 0x04);
2484+
lbg = !(ext[5] & 0x08);
2485+
lbb = !(ext[5] & 0x80);
2486+
lbr = !(ext[4] & 0x20);
2487+
bm = !(ext[4] & 0x10);
2488+
bp = !(ext[4] & 0x04);
2489+
2490+
if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
2491+
ltt = (ext[4] & 0x01) << 5;
2492+
sx &= 0x3e;
2493+
sy &= 0x3e;
2494+
}
2495+
2496+
input_report_abs(wdata->extension.input, ABS_X, sx);
2497+
input_report_abs(wdata->extension.input, ABS_Y, sy);
2498+
input_report_abs(wdata->extension.input, ABS_HAT0X, rtt);
2499+
input_report_abs(wdata->extension.input, ABS_HAT1X, ltt);
2500+
input_report_abs(wdata->extension.input, ABS_HAT2X, cs);
2501+
input_report_abs(wdata->extension.input, ABS_HAT3X, ed);
2502+
input_report_key(wdata->extension.input,
2503+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_RIGHT],
2504+
rbg);
2505+
input_report_key(wdata->extension.input,
2506+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_RIGHT],
2507+
rbr);
2508+
input_report_key(wdata->extension.input,
2509+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_RIGHT],
2510+
rbb);
2511+
input_report_key(wdata->extension.input,
2512+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_LEFT],
2513+
lbg);
2514+
input_report_key(wdata->extension.input,
2515+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_LEFT],
2516+
lbr);
2517+
input_report_key(wdata->extension.input,
2518+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_LEFT],
2519+
lbb);
2520+
input_report_key(wdata->extension.input,
2521+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_EUPHORIA],
2522+
be);
2523+
input_report_key(wdata->extension.input,
2524+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_PLUS],
2525+
bp);
2526+
input_report_key(wdata->extension.input,
2527+
wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_MINUS],
2528+
bm);
2529+
2530+
input_sync(wdata->extension.input);
2531+
}
2532+
2533+
static int wiimod_turntable_open(struct input_dev *dev)
2534+
{
2535+
struct wiimote_data *wdata = input_get_drvdata(dev);
2536+
unsigned long flags;
2537+
2538+
spin_lock_irqsave(&wdata->state.lock, flags);
2539+
wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
2540+
wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2541+
spin_unlock_irqrestore(&wdata->state.lock, flags);
2542+
2543+
return 0;
2544+
}
2545+
2546+
static void wiimod_turntable_close(struct input_dev *dev)
2547+
{
2548+
struct wiimote_data *wdata = input_get_drvdata(dev);
2549+
unsigned long flags;
2550+
2551+
spin_lock_irqsave(&wdata->state.lock, flags);
2552+
wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
2553+
wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2554+
spin_unlock_irqrestore(&wdata->state.lock, flags);
2555+
}
2556+
2557+
static int wiimod_turntable_probe(const struct wiimod_ops *ops,
2558+
struct wiimote_data *wdata)
2559+
{
2560+
int ret, i;
2561+
2562+
wdata->extension.input = input_allocate_device();
2563+
if (!wdata->extension.input)
2564+
return -ENOMEM;
2565+
2566+
input_set_drvdata(wdata->extension.input, wdata);
2567+
wdata->extension.input->open = wiimod_turntable_open;
2568+
wdata->extension.input->close = wiimod_turntable_close;
2569+
wdata->extension.input->dev.parent = &wdata->hdev->dev;
2570+
wdata->extension.input->id.bustype = wdata->hdev->bus;
2571+
wdata->extension.input->id.vendor = wdata->hdev->vendor;
2572+
wdata->extension.input->id.product = wdata->hdev->product;
2573+
wdata->extension.input->id.version = wdata->hdev->version;
2574+
wdata->extension.input->name = WIIMOTE_NAME " Turntable";
2575+
2576+
set_bit(EV_KEY, wdata->extension.input->evbit);
2577+
for (i = 0; i < WIIMOD_TURNTABLE_KEY_NUM; ++i)
2578+
set_bit(wiimod_turntable_map[i],
2579+
wdata->extension.input->keybit);
2580+
2581+
set_bit(EV_ABS, wdata->extension.input->evbit);
2582+
set_bit(ABS_X, wdata->extension.input->absbit);
2583+
set_bit(ABS_Y, wdata->extension.input->absbit);
2584+
set_bit(ABS_HAT0X, wdata->extension.input->absbit);
2585+
set_bit(ABS_HAT1X, wdata->extension.input->absbit);
2586+
set_bit(ABS_HAT2X, wdata->extension.input->absbit);
2587+
set_bit(ABS_HAT3X, wdata->extension.input->absbit);
2588+
input_set_abs_params(wdata->extension.input,
2589+
ABS_X, 0, 63, 1, 0);
2590+
input_set_abs_params(wdata->extension.input,
2591+
ABS_Y, 63, 0, 1, 0);
2592+
input_set_abs_params(wdata->extension.input,
2593+
ABS_HAT0X, -8, 8, 0, 0);
2594+
input_set_abs_params(wdata->extension.input,
2595+
ABS_HAT1X, -8, 8, 0, 0);
2596+
input_set_abs_params(wdata->extension.input,
2597+
ABS_HAT2X, 0, 31, 1, 1);
2598+
input_set_abs_params(wdata->extension.input,
2599+
ABS_HAT3X, 0, 7, 0, 0);
2600+
ret = input_register_device(wdata->extension.input);
2601+
if (ret)
2602+
goto err_free;
2603+
2604+
return 0;
2605+
2606+
err_free:
2607+
input_free_device(wdata->extension.input);
2608+
wdata->extension.input = NULL;
2609+
return ret;
2610+
}
2611+
2612+
static void wiimod_turntable_remove(const struct wiimod_ops *ops,
2613+
struct wiimote_data *wdata)
2614+
{
2615+
if (!wdata->extension.input)
2616+
return;
2617+
2618+
input_unregister_device(wdata->extension.input);
2619+
wdata->extension.input = NULL;
2620+
}
2621+
2622+
static const struct wiimod_ops wiimod_turntable = {
2623+
.flags = 0,
2624+
.arg = 0,
2625+
.probe = wiimod_turntable_probe,
2626+
.remove = wiimod_turntable_remove,
2627+
.in_ext = wiimod_turntable_in_ext,
2628+
};
2629+
24062630
/*
24072631
* Builtin Motion Plus
24082632
* This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
@@ -2657,4 +2881,5 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
26572881
[WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
26582882
[WIIMOTE_EXT_DRUMS] = &wiimod_drums,
26592883
[WIIMOTE_EXT_GUITAR] = &wiimod_guitar,
2884+
[WIIMOTE_EXT_TURNTABLE] = &wiimod_turntable,
26602885
};

drivers/hid/hid-wiimote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ enum wiimote_exttype {
8888
WIIMOTE_EXT_PRO_CONTROLLER,
8989
WIIMOTE_EXT_DRUMS,
9090
WIIMOTE_EXT_GUITAR,
91+
WIIMOTE_EXT_TURNTABLE,
9192
WIIMOTE_EXT_NUM,
9293
};
9394

0 commit comments

Comments
 (0)