HID: wiimote: add support for Guitar-Hero devices
authorNicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
Wed, 20 Jun 2018 10:55:15 +0000 (12:55 +0200)
committerJiri Kosina <jkosina@suse.cz>
Mon, 25 Jun 2018 13:26:06 +0000 (15:26 +0200)
This adds the drums and guitar extensions for Wiimote devices.

Devices are reported as "Nintendo Wii Remote Guitar/Drums". If I ever
get my hands on "RockBand" guitars, I will try to report them via the
same interface so user-space does not have to bother which device it
deals with.

This is a rebase of the original commits 8e22ecb603c8 and 73f8645db191.
They were reverted several years ago, since they were dependent on the
ABS_* rework of the input core. Sadly, this never worked out so these
commits were never pushed into a release. This rebase now uses the
ABS_HAT* event codes to report all pressure information.

Signed-off-by: Nicolas.Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
(Original commits by Nicolas, adapted to v4.18 by David)
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-wiimote-core.c
drivers/hid/hid-wiimote-modules.c
drivers/hid/hid-wiimote.h

index 579884e..7780da4 100644 (file)
@@ -455,6 +455,12 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
                return WIIMOTE_EXT_BALANCE_BOARD;
        if (rmem[4] == 0x01 && rmem[5] == 0x20)
                return WIIMOTE_EXT_PRO_CONTROLLER;
+       if (rmem[0] == 0x01 && rmem[1] == 0x00 &&
+           rmem[4] == 0x01 && rmem[5] == 0x03)
+               return WIIMOTE_EXT_DRUMS;
+       if (rmem[0] == 0x00 && rmem[1] == 0x00 &&
+           rmem[4] == 0x01 && rmem[5] == 0x03)
+               return WIIMOTE_EXT_GUITAR;
 
        return WIIMOTE_EXT_UNKNOWN;
 }
@@ -488,6 +494,8 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
        /* map MP with correct pass-through mode */
        switch (exttype) {
        case WIIMOTE_EXT_CLASSIC_CONTROLLER:
+       case WIIMOTE_EXT_DRUMS:
+       case WIIMOTE_EXT_GUITAR:
                wmem = 0x07;
                break;
        case WIIMOTE_EXT_NUNCHUK:
@@ -1075,6 +1083,8 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
        [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller",
        [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
        [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
+       [WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums",
+       [WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar",
 };
 
 /*
@@ -1660,6 +1670,10 @@ static ssize_t wiimote_ext_show(struct device *dev,
                return sprintf(buf, "balanceboard\n");
        case WIIMOTE_EXT_PRO_CONTROLLER:
                return sprintf(buf, "procontroller\n");
+       case WIIMOTE_EXT_DRUMS:
+               return sprintf(buf, "drums\n");
+       case WIIMOTE_EXT_GUITAR:
+               return sprintf(buf, "guitar\n");
        case WIIMOTE_EXT_UNKNOWN:
                /* fallthrough */
        default:
index c830ed3..aa72eb9 100644 (file)
@@ -1949,6 +1949,444 @@ static const struct wiimod_ops wiimod_pro = {
        .in_ext = wiimod_pro_in_ext,
 };
 
+/*
+ * Drums
+ * Guitar-Hero, Rock-Band and other games came bundled with drums which can
+ * be plugged as extension to a Wiimote. Drum-reports are still not entirely
+ * figured out, but the most important information is known.
+ * We create a separate device for drums and report all information via this
+ * input device.
+ */
+
+static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata,
+                                               __u8 none, __u8 which,
+                                               __u8 pressure, __u8 onoff,
+                                               __u8 *store, __u16 code,
+                                               __u8 which_code)
+{
+       static const __u8 default_pressure = 3;
+
+       if (!none && which == which_code) {
+               *store = pressure;
+               input_report_abs(wdata->extension.input, code, *store);
+       } else if (onoff != !!*store) {
+               *store = onoff ? default_pressure : 0;
+               input_report_abs(wdata->extension.input, code, *store);
+       }
+}
+
+static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+       __u8 pressure, which, none, hhp, sx, sy;
+       __u8 o, r, y, g, b, bass, bm, bp;
+
+       /*   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:0>             |
+        *    2   |  0  |  0  |              SY <5:0>             |
+        *   -----+-----+-----+-----------------------------+-----+
+        *    3   | HPP | NON |         WHICH <5:1>         |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    4   |   SOFT <7:5>    |  0  |  1  |  1  |  0  |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  ?  |  1  |  1  | B-  |  1  | B+  |  1  |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   |  O  |  R  |  Y  |  G  |  B  | BSS |  1  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        * All buttons are 0 if pressed
+        *
+        * With Motion+ enabled, the following bits will get invalid:
+        *   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:1>       |XXXXX|
+        *    2   |  0  |  0  |              SY <5:1>       |XXXXX|
+        *   -----+-----+-----+-----------------------------+-----+
+        *    3   | HPP | NON |         WHICH <5:1>         |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    4   |   SOFT <7:5>    |  0  |  1  |  1  |  0  |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  ?  |  1  |  1  | B-  |  1  | B+  |  1  |XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   |  O  |  R  |  Y  |  G  |  B  | BSS |XXXXX|XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        */
+
+       pressure = 7 - (ext[3] >> 5);
+       which = (ext[2] >> 1) & 0x1f;
+       none = !!(ext[2] & 0x40);
+       hhp = !(ext[2] & 0x80);
+       sx = ext[0] & 0x3f;
+       sy = ext[1] & 0x3f;
+       o = !(ext[5] & 0x80);
+       r = !(ext[5] & 0x40);
+       y = !(ext[5] & 0x20);
+       g = !(ext[5] & 0x10);
+       b = !(ext[5] & 0x08);
+       bass = !(ext[5] & 0x04);
+       bm = !(ext[4] & 0x10);
+       bp = !(ext[4] & 0x04);
+
+       if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+               sx &= 0x3e;
+               sy &= 0x3e;
+       }
+
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    o, &wdata->state.pressure_drums[0],
+                                    ABS_HAT2Y, 0x0e);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    r, &wdata->state.pressure_drums[1],
+                                    ABS_HAT0X, 0x19);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    y, &wdata->state.pressure_drums[2],
+                                    ABS_HAT2X, 0x11);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    g, &wdata->state.pressure_drums[3],
+                                    ABS_HAT1X, 0x12);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    b, &wdata->state.pressure_drums[4],
+                                    ABS_HAT0Y, 0x0f);
+
+       /* Bass shares pressure with hi-hat (set via hhp) */
+       wiimod_drums_report_pressure(wdata, none, hhp ? 0xff : which, pressure,
+                                    bass, &wdata->state.pressure_drums[5],
+                                    ABS_HAT3X, 0x1b);
+       /* Hi-hat has no on/off values, just pressure. Force to off/0. */
+       wiimod_drums_report_pressure(wdata, none, hhp ? which : 0xff, pressure,
+                                    0, &wdata->state.pressure_drums[6],
+                                    ABS_HAT3Y, 0x0e);
+
+       input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+       input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+
+       input_report_key(wdata->extension.input, BTN_START, bp);
+       input_report_key(wdata->extension.input, BTN_SELECT, bm);
+
+       input_sync(wdata->extension.input);
+}
+
+static int wiimod_drums_open(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+       return 0;
+}
+
+static void wiimod_drums_close(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_drums_probe(const struct wiimod_ops *ops,
+                             struct wiimote_data *wdata)
+{
+       int ret;
+
+       wdata->extension.input = input_allocate_device();
+       if (!wdata->extension.input)
+               return -ENOMEM;
+
+       input_set_drvdata(wdata->extension.input, wdata);
+       wdata->extension.input->open = wiimod_drums_open;
+       wdata->extension.input->close = wiimod_drums_close;
+       wdata->extension.input->dev.parent = &wdata->hdev->dev;
+       wdata->extension.input->id.bustype = wdata->hdev->bus;
+       wdata->extension.input->id.vendor = wdata->hdev->vendor;
+       wdata->extension.input->id.product = wdata->hdev->product;
+       wdata->extension.input->id.version = wdata->hdev->version;
+       wdata->extension.input->name = WIIMOTE_NAME " Drums";
+
+       set_bit(EV_KEY, wdata->extension.input->evbit);
+       set_bit(BTN_START, wdata->extension.input->keybit);
+       set_bit(BTN_SELECT, wdata->extension.input->keybit);
+
+       set_bit(EV_ABS, wdata->extension.input->evbit);
+       set_bit(ABS_X, wdata->extension.input->absbit);
+       set_bit(ABS_Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT2X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT3X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_X, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_Y, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT0X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT0Y, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT1X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT2X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT2Y, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT3X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT3Y, 0, 7, 0, 0);
+
+       ret = input_register_device(wdata->extension.input);
+       if (ret)
+               goto err_free;
+
+       return 0;
+
+err_free:
+       input_free_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+       return ret;
+}
+
+static void wiimod_drums_remove(const struct wiimod_ops *ops,
+                               struct wiimote_data *wdata)
+{
+       if (!wdata->extension.input)
+               return;
+
+       input_unregister_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_drums = {
+       .flags = 0,
+       .arg = 0,
+       .probe = wiimod_drums_probe,
+       .remove = wiimod_drums_remove,
+       .in_ext = wiimod_drums_in_ext,
+};
+
+/*
+ * Guitar
+ * Guitar-Hero, Rock-Band and other games came bundled with guitars which can
+ * be plugged as extension to a Wiimote.
+ * We create a separate device for guitars and report all information via this
+ * input device.
+ */
+
+enum wiimod_guitar_keys {
+       WIIMOD_GUITAR_KEY_G,
+       WIIMOD_GUITAR_KEY_R,
+       WIIMOD_GUITAR_KEY_Y,
+       WIIMOD_GUITAR_KEY_B,
+       WIIMOD_GUITAR_KEY_O,
+       WIIMOD_GUITAR_KEY_UP,
+       WIIMOD_GUITAR_KEY_DOWN,
+       WIIMOD_GUITAR_KEY_PLUS,
+       WIIMOD_GUITAR_KEY_MINUS,
+       WIIMOD_GUITAR_KEY_NUM,
+};
+
+static const __u16 wiimod_guitar_map[] = {
+       BTN_1,                  /* WIIMOD_GUITAR_KEY_G */
+       BTN_2,                  /* WIIMOD_GUITAR_KEY_R */
+       BTN_3,                  /* WIIMOD_GUITAR_KEY_Y */
+       BTN_4,                  /* WIIMOD_GUITAR_KEY_B */
+       BTN_5,                  /* WIIMOD_GUITAR_KEY_O */
+       BTN_DPAD_UP,            /* WIIMOD_GUITAR_KEY_UP */
+       BTN_DPAD_DOWN,          /* WIIMOD_GUITAR_KEY_DOWN */
+       BTN_START,              /* WIIMOD_GUITAR_KEY_PLUS */
+       BTN_SELECT,             /* WIIMOD_GUITAR_KEY_MINUS */
+};
+
+static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+       __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu;
+
+       /*   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:0>             |
+        *    2   |  0  |  0  |              SY <5:0>             |
+        *   -----+-----+-----+-----+-----------------------------+
+        *    3   |  0  |  0  |  0  |      TB <4:0>               |
+        *   -----+-----+-----+-----+-----------------------------+
+        *    4   |  0  |  0  |  0  |      WB <4:0>               |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  1  | BD  |  1  | B-  |  1  | B+  |  1  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   | BO  | BR  | BB  | BG  | BY  |  1  |  1  | BU  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        * All buttons are 0 if pressed
+        *
+        * With Motion+ enabled, it will look like this:
+        *   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:1>       | BU  |
+        *    2   |  0  |  0  |              SY <5:1>       |  1  |
+        *   -----+-----+-----+-----+-----------------------+-----+
+        *    3   |  0  |  0  |  0  |      TB <4:0>               |
+        *   -----+-----+-----+-----+-----------------------------+
+        *    4   |  0  |  0  |  0  |      WB <4:0>               |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  1  | BD  |  1  | B-  |  1  | B+  |  1  |XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   | BO  | BR  | BB  | BG  | BY  |  1  |XXXXX|XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        */
+
+       sx = ext[0] & 0x3f;
+       sy = ext[1] & 0x3f;
+       tb = ext[2] & 0x1f;
+       wb = ext[3] & 0x1f;
+       bd = !(ext[4] & 0x40);
+       bm = !(ext[4] & 0x10);
+       bp = !(ext[4] & 0x04);
+       bo = !(ext[5] & 0x80);
+       br = !(ext[5] & 0x40);
+       bb = !(ext[5] & 0x20);
+       bg = !(ext[5] & 0x10);
+       by = !(ext[5] & 0x08);
+       bu = !(ext[5] & 0x01);
+
+       if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+               bu = !(ext[0] & 0x01);
+               sx &= 0x3e;
+               sy &= 0x3e;
+       }
+
+       input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+       input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+       input_report_abs(wdata->extension.input, ABS_HAT0X, tb);
+       input_report_abs(wdata->extension.input, ABS_HAT1X, wb - 0x10);
+
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_G],
+                        bg);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_R],
+                        br);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_Y],
+                        by);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_B],
+                        bb);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_O],
+                        bo);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_UP],
+                        bu);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_DOWN],
+                        bd);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_PLUS],
+                        bp);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_MINUS],
+                        bm);
+
+       input_sync(wdata->extension.input);
+}
+
+static int wiimod_guitar_open(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+       return 0;
+}
+
+static void wiimod_guitar_close(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_guitar_probe(const struct wiimod_ops *ops,
+                              struct wiimote_data *wdata)
+{
+       int ret, i;
+
+       wdata->extension.input = input_allocate_device();
+       if (!wdata->extension.input)
+               return -ENOMEM;
+
+       input_set_drvdata(wdata->extension.input, wdata);
+       wdata->extension.input->open = wiimod_guitar_open;
+       wdata->extension.input->close = wiimod_guitar_close;
+       wdata->extension.input->dev.parent = &wdata->hdev->dev;
+       wdata->extension.input->id.bustype = wdata->hdev->bus;
+       wdata->extension.input->id.vendor = wdata->hdev->vendor;
+       wdata->extension.input->id.product = wdata->hdev->product;
+       wdata->extension.input->id.version = wdata->hdev->version;
+       wdata->extension.input->name = WIIMOTE_NAME " Guitar";
+
+       set_bit(EV_KEY, wdata->extension.input->evbit);
+       for (i = 0; i < WIIMOD_GUITAR_KEY_NUM; ++i)
+               set_bit(wiimod_guitar_map[i],
+                       wdata->extension.input->keybit);
+
+       set_bit(EV_ABS, wdata->extension.input->evbit);
+       set_bit(ABS_X, wdata->extension.input->absbit);
+       set_bit(ABS_Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_X, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_Y, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT0X, 0, 0x1f, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT1X, 0, 0x0f, 1, 1);
+
+       ret = input_register_device(wdata->extension.input);
+       if (ret)
+               goto err_free;
+
+       return 0;
+
+err_free:
+       input_free_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+       return ret;
+}
+
+static void wiimod_guitar_remove(const struct wiimod_ops *ops,
+                                struct wiimote_data *wdata)
+{
+       if (!wdata->extension.input)
+               return;
+
+       input_unregister_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_guitar = {
+       .flags = 0,
+       .arg = 0,
+       .probe = wiimod_guitar_probe,
+       .remove = wiimod_guitar_remove,
+       .in_ext = wiimod_guitar_in_ext,
+};
+
 /*
  * Builtin Motion Plus
  * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
@@ -2201,4 +2639,6 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
        [WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic,
        [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
        [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
+       [WIIMOTE_EXT_DRUMS] = &wiimod_drums,
+       [WIIMOTE_EXT_GUITAR] = &wiimod_guitar,
 };
index 510ca77..3bf3d3c 100644 (file)
@@ -89,6 +89,8 @@ enum wiimote_exttype {
        WIIMOTE_EXT_CLASSIC_CONTROLLER,
        WIIMOTE_EXT_BALANCE_BOARD,
        WIIMOTE_EXT_PRO_CONTROLLER,
+       WIIMOTE_EXT_DRUMS,
+       WIIMOTE_EXT_GUITAR,
        WIIMOTE_EXT_NUM,
 };
 
@@ -137,6 +139,7 @@ struct wiimote_state {
        /* calibration/cache data */
        __u16 calib_bboard[4][3];
        __s16 calib_pro_sticks[4];
+       __u8 pressure_drums[7];
        __u8 cache_rumble;
 };