linux/drivers/hid/hid-wiimote-ext.c
<<
>>
Prefs
   1/*
   2 * HID driver for Nintendo Wiimote extension devices
   3 * Copyright (c) 2011 David Herrmann
   4 */
   5
   6/*
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License as published by the Free
   9 * Software Foundation; either version 2 of the License, or (at your option)
  10 * any later version.
  11 */
  12
  13#include <linux/atomic.h>
  14#include <linux/module.h>
  15#include <linux/spinlock.h>
  16#include <linux/workqueue.h>
  17#include "hid-wiimote.h"
  18
  19struct wiimote_ext {
  20        struct wiimote_data *wdata;
  21        struct work_struct worker;
  22        struct input_dev *input;
  23        struct input_dev *mp_input;
  24
  25        atomic_t opened;
  26        atomic_t mp_opened;
  27        bool plugged;
  28        bool mp_plugged;
  29        bool motionp;
  30        __u8 ext_type;
  31        __u16 calib[4][3];
  32};
  33
  34enum wiiext_type {
  35        WIIEXT_NONE,            /* placeholder */
  36        WIIEXT_CLASSIC,         /* Nintendo classic controller */
  37        WIIEXT_NUNCHUCK,        /* Nintendo nunchuck controller */
  38        WIIEXT_BALANCE_BOARD,   /* Nintendo balance board controller */
  39};
  40
  41enum wiiext_keys {
  42        WIIEXT_KEY_C,
  43        WIIEXT_KEY_Z,
  44        WIIEXT_KEY_A,
  45        WIIEXT_KEY_B,
  46        WIIEXT_KEY_X,
  47        WIIEXT_KEY_Y,
  48        WIIEXT_KEY_ZL,
  49        WIIEXT_KEY_ZR,
  50        WIIEXT_KEY_PLUS,
  51        WIIEXT_KEY_MINUS,
  52        WIIEXT_KEY_HOME,
  53        WIIEXT_KEY_LEFT,
  54        WIIEXT_KEY_RIGHT,
  55        WIIEXT_KEY_UP,
  56        WIIEXT_KEY_DOWN,
  57        WIIEXT_KEY_LT,
  58        WIIEXT_KEY_RT,
  59        WIIEXT_KEY_COUNT
  60};
  61
  62static __u16 wiiext_keymap[] = {
  63        BTN_C,          /* WIIEXT_KEY_C */
  64        BTN_Z,          /* WIIEXT_KEY_Z */
  65        BTN_A,          /* WIIEXT_KEY_A */
  66        BTN_B,          /* WIIEXT_KEY_B */
  67        BTN_X,          /* WIIEXT_KEY_X */
  68        BTN_Y,          /* WIIEXT_KEY_Y */
  69        BTN_TL2,        /* WIIEXT_KEY_ZL */
  70        BTN_TR2,        /* WIIEXT_KEY_ZR */
  71        KEY_NEXT,       /* WIIEXT_KEY_PLUS */
  72        KEY_PREVIOUS,   /* WIIEXT_KEY_MINUS */
  73        BTN_MODE,       /* WIIEXT_KEY_HOME */
  74        KEY_LEFT,       /* WIIEXT_KEY_LEFT */
  75        KEY_RIGHT,      /* WIIEXT_KEY_RIGHT */
  76        KEY_UP,         /* WIIEXT_KEY_UP */
  77        KEY_DOWN,       /* WIIEXT_KEY_DOWN */
  78        BTN_TL,         /* WIIEXT_KEY_LT */
  79        BTN_TR,         /* WIIEXT_KEY_RT */
  80};
  81
  82/* disable all extensions */
  83static void ext_disable(struct wiimote_ext *ext)
  84{
  85        unsigned long flags;
  86        __u8 wmem = 0x55;
  87
  88        if (!wiimote_cmd_acquire(ext->wdata)) {
  89                wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem));
  90                wiimote_cmd_release(ext->wdata);
  91        }
  92
  93        spin_lock_irqsave(&ext->wdata->state.lock, flags);
  94        ext->motionp = false;
  95        ext->ext_type = WIIEXT_NONE;
  96        wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL);
  97        spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
  98}
  99
 100static bool motionp_read(struct wiimote_ext *ext)
 101{
 102        __u8 rmem[2], wmem;
 103        ssize_t ret;
 104        bool avail = false;
 105
 106        if (!atomic_read(&ext->mp_opened))
 107                return false;
 108
 109        if (wiimote_cmd_acquire(ext->wdata))
 110                return false;
 111
 112        /* initialize motion plus */
 113        wmem = 0x55;
 114        ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem));
 115        if (ret)
 116                goto error;
 117
 118        /* read motion plus ID */
 119        ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2);
 120        if (ret == 2 || rmem[1] == 0x5)
 121                avail = true;
 122
 123error:
 124        wiimote_cmd_release(ext->wdata);
 125        return avail;
 126}
 127
 128static __u8 ext_read(struct wiimote_ext *ext)
 129{
 130        ssize_t ret;
 131        __u8 buf[24], i, j, offs = 0;
 132        __u8 rmem[2], wmem;
 133        __u8 type = WIIEXT_NONE;
 134
 135        if (!ext->plugged || !atomic_read(&ext->opened))
 136                return WIIEXT_NONE;
 137
 138        if (wiimote_cmd_acquire(ext->wdata))
 139                return WIIEXT_NONE;
 140
 141        /* initialize extension */
 142        wmem = 0x55;
 143        ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem));
 144        if (!ret) {
 145                /* disable encryption */
 146                wmem = 0x0;
 147                wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem));
 148        }
 149
 150        /* read extension ID */
 151        ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2);
 152        if (ret == 2) {
 153                if (rmem[0] == 0 && rmem[1] == 0)
 154                        type = WIIEXT_NUNCHUCK;
 155                else if (rmem[0] == 0x01 && rmem[1] == 0x01)
 156                        type = WIIEXT_CLASSIC;
 157                else if (rmem[0] == 0x04 && rmem[1] == 0x02)
 158                        type = WIIEXT_BALANCE_BOARD;
 159        }
 160
 161        /* get balance board calibration data */
 162        if (type == WIIEXT_BALANCE_BOARD) {
 163                ret = wiimote_cmd_read(ext->wdata, 0xa40024, buf, 12);
 164                ret += wiimote_cmd_read(ext->wdata, 0xa40024 + 12,
 165                                        buf + 12, 12);
 166
 167                if (ret != 24) {
 168                        type = WIIEXT_NONE;
 169                } else {
 170                        for (i = 0; i < 3; i++) {
 171                                for (j = 0; j < 4; j++) {
 172                                        ext->calib[j][i] = buf[offs];
 173                                        ext->calib[j][i] <<= 8;
 174                                        ext->calib[j][i] |= buf[offs + 1];
 175                                        offs += 2;
 176                                }
 177                        }
 178                }
 179        }
 180
 181        wiimote_cmd_release(ext->wdata);
 182
 183        return type;
 184}
 185
 186static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type)
 187{
 188        unsigned long flags;
 189        __u8 wmem;
 190        int ret;
 191
 192        if (motionp) {
 193                if (wiimote_cmd_acquire(ext->wdata))
 194                        return;
 195
 196                if (ext_type == WIIEXT_CLASSIC)
 197                        wmem = 0x07;
 198                else if (ext_type == WIIEXT_NUNCHUCK)
 199                        wmem = 0x05;
 200                else
 201                        wmem = 0x04;
 202
 203                ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem));
 204                wiimote_cmd_release(ext->wdata);
 205                if (ret)
 206                        return;
 207        }
 208
 209        spin_lock_irqsave(&ext->wdata->state.lock, flags);
 210        ext->motionp = motionp;
 211        ext->ext_type = ext_type;
 212        wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL);
 213        spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
 214}
 215
 216static void wiiext_worker(struct work_struct *work)
 217{
 218        struct wiimote_ext *ext = container_of(work, struct wiimote_ext,
 219                                                                        worker);
 220        bool motionp;
 221        __u8 ext_type;
 222
 223        ext_disable(ext);
 224        motionp = motionp_read(ext);
 225        ext_type = ext_read(ext);
 226        ext_enable(ext, motionp, ext_type);
 227}
 228
 229/* schedule work only once, otherwise mark for reschedule */
 230static void wiiext_schedule(struct wiimote_ext *ext)
 231{
 232        schedule_work(&ext->worker);
 233}
 234
 235/*
 236 * Reacts on extension port events
 237 * Whenever the driver gets an event from the wiimote that an extension has been
 238 * plugged or unplugged, this funtion shall be called. It checks what extensions
 239 * are connected and initializes and activates them.
 240 * This can be called in atomic context. The initialization is done in a
 241 * separate worker thread. The state.lock spinlock must be held by the caller.
 242 */
 243void wiiext_event(struct wiimote_data *wdata, bool plugged)
 244{
 245        if (!wdata->ext)
 246                return;
 247
 248        if (wdata->ext->plugged == plugged)
 249                return;
 250
 251        wdata->ext->plugged = plugged;
 252
 253        if (!plugged)
 254                wdata->ext->mp_plugged = false;
 255
 256        /*
 257         * We need to call wiiext_schedule(wdata->ext) here, however, the
 258         * extension initialization logic is not fully understood and so
 259         * automatic initialization is not supported, yet.
 260         */
 261}
 262
 263/*
 264 * Returns true if the current DRM mode should contain extension data and false
 265 * if there is no interest in extension data.
 266 * All supported extensions send 6 byte extension data so any DRM that contains
 267 * extension bytes is fine.
 268 * The caller must hold the state.lock spinlock.
 269 */
 270bool wiiext_active(struct wiimote_data *wdata)
 271{
 272        if (!wdata->ext)
 273                return false;
 274
 275        return wdata->ext->motionp || wdata->ext->ext_type;
 276}
 277
 278static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload)
 279{
 280        __s32 x, y, z;
 281        bool plugged;
 282
 283        /*        |   8    7    6    5    4    3 |  2  |  1  |
 284         *   -----+------------------------------+-----+-----+
 285         *    1   |               Yaw Speed <7:0>            |
 286         *    2   |              Roll Speed <7:0>            |
 287         *    3   |             Pitch Speed <7:0>            |
 288         *   -----+------------------------------+-----+-----+
 289         *    4   |       Yaw Speed <13:8>       | Yaw |Pitch|
 290         *   -----+------------------------------+-----+-----+
 291         *    5   |      Roll Speed <13:8>       |Roll | Ext |
 292         *   -----+------------------------------+-----+-----+
 293         *    6   |     Pitch Speed <13:8>       |  1  |  0  |
 294         *   -----+------------------------------+-----+-----+
 295         * The single bits Yaw, Roll, Pitch in the lower right corner specify
 296         * whether the wiimote is rotating fast (0) or slow (1). Speed for slow
 297         * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a
 298         * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast
 299         * and 9 for slow.
 300         * If the wiimote is not rotating the sensor reports 2^13 = 8192.
 301         * Ext specifies whether an extension is connected to the motionp.
 302         */
 303
 304        x = payload[0];
 305        y = payload[1];
 306        z = payload[2];
 307
 308        x |= (((__u16)payload[3]) << 6) & 0xff00;
 309        y |= (((__u16)payload[4]) << 6) & 0xff00;
 310        z |= (((__u16)payload[5]) << 6) & 0xff00;
 311
 312        x -= 8192;
 313        y -= 8192;
 314        z -= 8192;
 315
 316        if (!(payload[3] & 0x02))
 317                x *= 18;
 318        else
 319                x *= 9;
 320        if (!(payload[4] & 0x02))
 321                y *= 18;
 322        else
 323                y *= 9;
 324        if (!(payload[3] & 0x01))
 325                z *= 18;
 326        else
 327                z *= 9;
 328
 329        input_report_abs(ext->mp_input, ABS_RX, x);
 330        input_report_abs(ext->mp_input, ABS_RY, y);
 331        input_report_abs(ext->mp_input, ABS_RZ, z);
 332        input_sync(ext->mp_input);
 333
 334        plugged = payload[5] & 0x01;
 335        if (plugged != ext->mp_plugged)
 336                ext->mp_plugged = plugged;
 337}
 338
 339static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
 340{
 341        __s16 x, y, z, bx, by;
 342
 343        /*   Byte |   8    7 |  6    5 |  4    3 |  2 |  1  |
 344         *   -----+----------+---------+---------+----+-----+
 345         *    1   |              Button X <7:0>             |
 346         *    2   |              Button Y <7:0>             |
 347         *   -----+----------+---------+---------+----+-----+
 348         *    3   |               Speed X <9:2>             |
 349         *    4   |               Speed Y <9:2>             |
 350         *    5   |               Speed Z <9:2>             |
 351         *   -----+----------+---------+---------+----+-----+
 352         *    6   | Z <1:0>  | Y <1:0> | X <1:0> | BC | BZ  |
 353         *   -----+----------+---------+---------+----+-----+
 354         * Button X/Y is the analog stick. Speed X, Y and Z are the
 355         * accelerometer data in the same format as the wiimote's accelerometer.
 356         * The 6th byte contains the LSBs of the accelerometer data.
 357         * BC and BZ are the C and Z buttons: 0 means pressed
 358         *
 359         * If reported interleaved with motionp, then the layout changes. The
 360         * 5th and 6th byte changes to:
 361         *   -----+-----------------------------------+-----+
 362         *    5   |            Speed Z <9:3>          | EXT |
 363         *   -----+--------+-----+-----+----+----+----+-----+
 364         *    6   |Z <2:1> |Y <1>|X <1>| BC | BZ | 0  |  0  |
 365         *   -----+--------+-----+-----+----+----+----+-----+
 366         * All three accelerometer values lose their LSB. The other data is
 367         * still available but slightly moved.
 368         *
 369         * Center data for button values is 128. Center value for accelerometer
 370         * values it 512 / 0x200
 371         */
 372
 373        bx = payload[0];
 374        by = payload[1];
 375        bx -= 128;
 376        by -= 128;
 377
 378        x = payload[2] << 2;
 379        y = payload[3] << 2;
 380        z = payload[4] << 2;
 381
 382        if (ext->motionp) {
 383                x |= (payload[5] >> 3) & 0x02;
 384                y |= (payload[5] >> 4) & 0x02;
 385                z &= ~0x4;
 386                z |= (payload[5] >> 5) & 0x06;
 387        } else {
 388                x |= (payload[5] >> 2) & 0x03;
 389                y |= (payload[5] >> 4) & 0x03;
 390                z |= (payload[5] >> 6) & 0x03;
 391        }
 392
 393        x -= 0x200;
 394        y -= 0x200;
 395        z -= 0x200;
 396
 397        input_report_abs(ext->input, ABS_HAT0X, bx);
 398        input_report_abs(ext->input, ABS_HAT0Y, by);
 399
 400        input_report_abs(ext->input, ABS_RX, x);
 401        input_report_abs(ext->input, ABS_RY, y);
 402        input_report_abs(ext->input, ABS_RZ, z);
 403
 404        if (ext->motionp) {
 405                input_report_key(ext->input,
 406                        wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x04));
 407                input_report_key(ext->input,
 408                        wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x08));
 409        } else {
 410                input_report_key(ext->input,
 411                        wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x01));
 412                input_report_key(ext->input,
 413                        wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x02));
 414        }
 415
 416        input_sync(ext->input);
 417}
 418
 419static void handler_classic(struct wiimote_ext *ext, const __u8 *payload)
 420{
 421        __s8 rx, ry, lx, ly, lt, rt;
 422
 423        /*   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
 424         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 425         *    1   | RX <5:4>  |              LX <5:0>             |
 426         *    2   | RX <3:2>  |              LY <5:0>             |
 427         *   -----+-----+-----+-----+-----------------------------+
 428         *    3   |RX<1>| LT <5:4>  |         RY <5:1>            |
 429         *   -----+-----+-----------+-----------------------------+
 430         *    4   |     LT <3:1>    |         RT <5:1>            |
 431         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 432         *    5   | BDR | BDD | BLT | B-  | BH  | B+  | BRT |  1  |
 433         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 434         *    6   | BZL | BB  | BY  | BA  | BX  | BZR | BDL | BDU |
 435         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 436         * All buttons are 0 if pressed
 437         * RX and RY are right analog stick
 438         * LX and LY are left analog stick
 439         * LT is left trigger, RT is right trigger
 440         * BLT is 0 if left trigger is fully pressed
 441         * BRT is 0 if right trigger is fully pressed
 442         * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons
 443         * BZL is left Z button and BZR is right Z button
 444         * B-, BH, B+ are +, HOME and - buttons
 445         * BB, BY, BA, BX are A, B, X, Y buttons
 446         * LSB of RX, RY, LT, and RT are not transmitted and always 0.
 447         *
 448         * With motionp enabled it changes slightly to this:
 449         *   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
 450         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 451         *    1   | RX <4:3>  |          LX <5:1>           | BDU |
 452         *    2   | RX <2:1>  |          LY <5:1>           | BDL |
 453         *   -----+-----+-----+-----+-----------------------+-----+
 454         *    3   |RX<0>| LT <4:3>  |         RY <4:0>            |
 455         *   -----+-----+-----------+-----------------------------+
 456         *    4   |     LT <2:0>    |         RT <4:0>            |
 457         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 458         *    5   | BDR | BDD | BLT | B-  | BH  | B+  | BRT | EXT |
 459         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 460         *    6   | BZL | BB  | BY  | BA  | BX  | BZR |  0  |  0  |
 461         *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
 462         * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest
 463         * is the same as before.
 464         */
 465
 466        if (ext->motionp) {
 467                lx = payload[0] & 0x3e;
 468                ly = payload[0] & 0x3e;
 469        } else {
 470                lx = payload[0] & 0x3f;
 471                ly = payload[0] & 0x3f;
 472        }
 473
 474        rx = (payload[0] >> 3) & 0x14;
 475        rx |= (payload[1] >> 5) & 0x06;
 476        rx |= (payload[2] >> 7) & 0x01;
 477        ry = payload[2] & 0x1f;
 478
 479        rt = payload[3] & 0x1f;
 480        lt = (payload[2] >> 2) & 0x18;
 481        lt |= (payload[3] >> 5) & 0x07;
 482
 483        rx <<= 1;
 484        ry <<= 1;
 485        rt <<= 1;
 486        lt <<= 1;
 487
 488        input_report_abs(ext->input, ABS_HAT1X, lx - 0x20);
 489        input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20);
 490        input_report_abs(ext->input, ABS_HAT2X, rx - 0x20);
 491        input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20);
 492        input_report_abs(ext->input, ABS_HAT3X, rt - 0x20);
 493        input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20);
 494
 495        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT],
 496                                                        !!(payload[4] & 0x80));
 497        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN],
 498                                                        !!(payload[4] & 0x40));
 499        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT],
 500                                                        !!(payload[4] & 0x20));
 501        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS],
 502                                                        !!(payload[4] & 0x10));
 503        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME],
 504                                                        !!(payload[4] & 0x08));
 505        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS],
 506                                                        !!(payload[4] & 0x04));
 507        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT],
 508                                                        !!(payload[4] & 0x02));
 509        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL],
 510                                                        !!(payload[5] & 0x80));
 511        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B],
 512                                                        !!(payload[5] & 0x40));
 513        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y],
 514                                                        !!(payload[5] & 0x20));
 515        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A],
 516                                                        !!(payload[5] & 0x10));
 517        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X],
 518                                                        !!(payload[5] & 0x08));
 519        input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR],
 520                                                        !!(payload[5] & 0x04));
 521
 522        if (ext->motionp) {
 523                input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP],
 524                                                        !!(payload[0] & 0x01));
 525                input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT],
 526                                                        !!(payload[1] & 0x01));
 527        } else {
 528                input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP],
 529                                                        !!(payload[5] & 0x01));
 530                input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT],
 531                                                        !!(payload[5] & 0x02));
 532        }
 533
 534        input_sync(ext->input);
 535}
 536
 537static void handler_balance_board(struct wiimote_ext *ext, const __u8 *payload)
 538{
 539        __s32 val[4], tmp;
 540        unsigned int i;
 541
 542        /*   Byte |  8  7  6  5  4  3  2  1  |
 543         *   -----+--------------------------+
 544         *    1   |    Top Right <15:8>      |
 545         *    2   |    Top Right  <7:0>      |
 546         *   -----+--------------------------+
 547         *    3   | Bottom Right <15:8>      |
 548         *    4   | Bottom Right  <7:0>      |
 549         *   -----+--------------------------+
 550         *    5   |     Top Left <15:8>      |
 551         *    6   |     Top Left  <7:0>      |
 552         *   -----+--------------------------+
 553         *    7   |  Bottom Left <15:8>      |
 554         *    8   |  Bottom Left  <7:0>      |
 555         *   -----+--------------------------+
 556         *
 557         * These values represent the weight-measurements of the Wii-balance
 558         * board with 16bit precision.
 559         *
 560         * The balance-board is never reported interleaved with motionp.
 561         */
 562
 563        val[0] = payload[0];
 564        val[0] <<= 8;
 565        val[0] |= payload[1];
 566
 567        val[1] = payload[2];
 568        val[1] <<= 8;
 569        val[1] |= payload[3];
 570
 571        val[2] = payload[4];
 572        val[2] <<= 8;
 573        val[2] |= payload[5];
 574
 575        val[3] = payload[6];
 576        val[3] <<= 8;
 577        val[3] |= payload[7];
 578
 579        /* apply calibration data */
 580        for (i = 0; i < 4; i++) {
 581                if (val[i] < ext->calib[i][1]) {
 582                        tmp = val[i] - ext->calib[i][0];
 583                        tmp *= 1700;
 584                        tmp /= ext->calib[i][1] - ext->calib[i][0];
 585                } else {
 586                        tmp = val[i] - ext->calib[i][1];
 587                        tmp *= 1700;
 588                        tmp /= ext->calib[i][2] - ext->calib[i][1];
 589                        tmp += 1700;
 590                }
 591                val[i] = tmp;
 592        }
 593
 594        input_report_abs(ext->input, ABS_HAT0X, val[0]);
 595        input_report_abs(ext->input, ABS_HAT0Y, val[1]);
 596        input_report_abs(ext->input, ABS_HAT1X, val[2]);
 597        input_report_abs(ext->input, ABS_HAT1Y, val[3]);
 598
 599        input_sync(ext->input);
 600}
 601
 602/* call this with state.lock spinlock held */
 603void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload)
 604{
 605        struct wiimote_ext *ext = wdata->ext;
 606
 607        if (!ext)
 608                return;
 609
 610        if (ext->motionp && (payload[5] & 0x02)) {
 611                handler_motionp(ext, payload);
 612        } else if (ext->ext_type == WIIEXT_NUNCHUCK) {
 613                handler_nunchuck(ext, payload);
 614        } else if (ext->ext_type == WIIEXT_CLASSIC) {
 615                handler_classic(ext, payload);
 616        } else if (ext->ext_type == WIIEXT_BALANCE_BOARD) {
 617                handler_balance_board(ext, payload);
 618        }
 619}
 620
 621static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
 622                                                                char *buf)
 623{
 624        struct wiimote_data *wdata = dev_to_wii(dev);
 625        __u8 type = WIIEXT_NONE;
 626        bool motionp = false;
 627        unsigned long flags;
 628
 629        spin_lock_irqsave(&wdata->state.lock, flags);
 630        if (wdata->ext) {
 631                motionp = wdata->ext->motionp;
 632                type = wdata->ext->ext_type;
 633        }
 634        spin_unlock_irqrestore(&wdata->state.lock, flags);
 635
 636        if (type == WIIEXT_NUNCHUCK) {
 637                if (motionp)
 638                        return sprintf(buf, "motionp+nunchuck\n");
 639                else
 640                        return sprintf(buf, "nunchuck\n");
 641        } else if (type == WIIEXT_CLASSIC) {
 642                if (motionp)
 643                        return sprintf(buf, "motionp+classic\n");
 644                else
 645                        return sprintf(buf, "classic\n");
 646        } else if (type == WIIEXT_BALANCE_BOARD) {
 647                if (motionp)
 648                        return sprintf(buf, "motionp+balanceboard\n");
 649                else
 650                        return sprintf(buf, "balanceboard\n");
 651        } else {
 652                if (motionp)
 653                        return sprintf(buf, "motionp\n");
 654                else
 655                        return sprintf(buf, "none\n");
 656        }
 657}
 658
 659static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL);
 660
 661static int wiiext_input_open(struct input_dev *dev)
 662{
 663        struct wiimote_ext *ext = input_get_drvdata(dev);
 664        int ret;
 665
 666        ret = hid_hw_open(ext->wdata->hdev);
 667        if (ret)
 668                return ret;
 669
 670        atomic_inc(&ext->opened);
 671        wiiext_schedule(ext);
 672
 673        return 0;
 674}
 675
 676static void wiiext_input_close(struct input_dev *dev)
 677{
 678        struct wiimote_ext *ext = input_get_drvdata(dev);
 679
 680        atomic_dec(&ext->opened);
 681        wiiext_schedule(ext);
 682        hid_hw_close(ext->wdata->hdev);
 683}
 684
 685static int wiiext_mp_open(struct input_dev *dev)
 686{
 687        struct wiimote_ext *ext = input_get_drvdata(dev);
 688        int ret;
 689
 690        ret = hid_hw_open(ext->wdata->hdev);
 691        if (ret)
 692                return ret;
 693
 694        atomic_inc(&ext->mp_opened);
 695        wiiext_schedule(ext);
 696
 697        return 0;
 698}
 699
 700static void wiiext_mp_close(struct input_dev *dev)
 701{
 702        struct wiimote_ext *ext = input_get_drvdata(dev);
 703
 704        atomic_dec(&ext->mp_opened);
 705        wiiext_schedule(ext);
 706        hid_hw_close(ext->wdata->hdev);
 707}
 708
 709/* Initializes the extension driver of a wiimote */
 710int wiiext_init(struct wiimote_data *wdata)
 711{
 712        struct wiimote_ext *ext;
 713        unsigned long flags;
 714        int ret, i;
 715
 716        ext = kzalloc(sizeof(*ext), GFP_KERNEL);
 717        if (!ext)
 718                return -ENOMEM;
 719
 720        ext->wdata = wdata;
 721        INIT_WORK(&ext->worker, wiiext_worker);
 722
 723        ext->input = input_allocate_device();
 724        if (!ext->input) {
 725                ret = -ENOMEM;
 726                goto err_input;
 727        }
 728
 729        input_set_drvdata(ext->input, ext);
 730        ext->input->open = wiiext_input_open;
 731        ext->input->close = wiiext_input_close;
 732        ext->input->dev.parent = &wdata->hdev->dev;
 733        ext->input->id.bustype = wdata->hdev->bus;
 734        ext->input->id.vendor = wdata->hdev->vendor;
 735        ext->input->id.product = wdata->hdev->product;
 736        ext->input->id.version = wdata->hdev->version;
 737        ext->input->name = WIIMOTE_NAME " Extension";
 738
 739        set_bit(EV_KEY, ext->input->evbit);
 740        for (i = 0; i < WIIEXT_KEY_COUNT; ++i)
 741                set_bit(wiiext_keymap[i], ext->input->keybit);
 742
 743        set_bit(EV_ABS, ext->input->evbit);
 744        set_bit(ABS_HAT0X, ext->input->absbit);
 745        set_bit(ABS_HAT0Y, ext->input->absbit);
 746        set_bit(ABS_HAT1X, ext->input->absbit);
 747        set_bit(ABS_HAT1Y, ext->input->absbit);
 748        set_bit(ABS_HAT2X, ext->input->absbit);
 749        set_bit(ABS_HAT2Y, ext->input->absbit);
 750        set_bit(ABS_HAT3X, ext->input->absbit);
 751        set_bit(ABS_HAT3Y, ext->input->absbit);
 752        input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4);
 753        input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4);
 754        input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1);
 755        input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1);
 756        input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1);
 757        input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1);
 758        input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1);
 759        input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1);
 760        set_bit(ABS_RX, ext->input->absbit);
 761        set_bit(ABS_RY, ext->input->absbit);
 762        set_bit(ABS_RZ, ext->input->absbit);
 763        input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4);
 764        input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4);
 765        input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4);
 766
 767        ret = input_register_device(ext->input);
 768        if (ret) {
 769                input_free_device(ext->input);
 770                goto err_input;
 771        }
 772
 773        ext->mp_input = input_allocate_device();
 774        if (!ext->mp_input) {
 775                ret = -ENOMEM;
 776                goto err_mp;
 777        }
 778
 779        input_set_drvdata(ext->mp_input, ext);
 780        ext->mp_input->open = wiiext_mp_open;
 781        ext->mp_input->close = wiiext_mp_close;
 782        ext->mp_input->dev.parent = &wdata->hdev->dev;
 783        ext->mp_input->id.bustype = wdata->hdev->bus;
 784        ext->mp_input->id.vendor = wdata->hdev->vendor;
 785        ext->mp_input->id.product = wdata->hdev->product;
 786        ext->mp_input->id.version = wdata->hdev->version;
 787        ext->mp_input->name = WIIMOTE_NAME " Motion+";
 788
 789        set_bit(EV_ABS, ext->mp_input->evbit);
 790        set_bit(ABS_RX, ext->mp_input->absbit);
 791        set_bit(ABS_RY, ext->mp_input->absbit);
 792        set_bit(ABS_RZ, ext->mp_input->absbit);
 793        input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8);
 794        input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8);
 795        input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8);
 796
 797        ret = input_register_device(ext->mp_input);
 798        if (ret) {
 799                input_free_device(ext->mp_input);
 800                goto err_mp;
 801        }
 802
 803        ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension);
 804        if (ret)
 805                goto err_dev;
 806
 807        spin_lock_irqsave(&wdata->state.lock, flags);
 808        wdata->ext = ext;
 809        spin_unlock_irqrestore(&wdata->state.lock, flags);
 810
 811        return 0;
 812
 813err_dev:
 814        input_unregister_device(ext->mp_input);
 815err_mp:
 816        input_unregister_device(ext->input);
 817err_input:
 818        kfree(ext);
 819        return ret;
 820}
 821
 822/* Deinitializes the extension driver of a wiimote */
 823void wiiext_deinit(struct wiimote_data *wdata)
 824{
 825        struct wiimote_ext *ext = wdata->ext;
 826        unsigned long flags;
 827
 828        if (!ext)
 829                return;
 830
 831        /*
 832         * We first unset wdata->ext to avoid further input from the wiimote
 833         * core. The worker thread does not access this pointer so it is not
 834         * affected by this.
 835         * We kill the worker after this so it does not get respawned during
 836         * deinitialization.
 837         */
 838
 839        spin_lock_irqsave(&wdata->state.lock, flags);
 840        wdata->ext = NULL;
 841        spin_unlock_irqrestore(&wdata->state.lock, flags);
 842
 843        device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
 844        input_unregister_device(ext->mp_input);
 845        input_unregister_device(ext->input);
 846
 847        cancel_work_sync(&ext->worker);
 848        kfree(ext);
 849}
 850
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.