@@ -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};
0 commit comments