* [PATCH 00/16] Wiimote: Extension and Debug Support
@ 2011-11-13 13:27 David Herrmann
2011-11-13 13:27 ` [PATCH 01/16] HID: wiimote: Rename driver to allow multiple source files David Herrmann
` (15 more replies)
0 siblings, 16 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Hi
This is the revised patchset for extension support. I didn't change much
compared to the previously sent patchset apart from some cleanups and
simplifications.
I added 4 more patches which add debugfs support. They should be trivial,
though.
The first three patches split the driver into multiple files and add simple
helper functions.
The following patches add the basic extension-support layout and add protocol
parsers. I'd appreciate any feedback on that.
Regards
David
David Herrmann (16):
HID: wiimote: Rename driver to allow multiple source files
HID: wiimote: Move common symbols into header
HID: wiimote: Add read-mem helpers
HID: wiimote: Add extension support stub
HID: wiimote: Add extension initializer stubs
HID: wiimote: Add extension initializers
HID: wiimote: Add extension sysfs attribute
HID: wiimote: Register input devices for extensions
HID: wiimote: Add extension handler stubs
HID: wiimote: Parse motion+ data
HID: wiimote: Parse nunchuck data
HID: wiimote: Parse classic controller data
HID: wiimote: Add debugfs support stubs
HID: wiimote: Allow direct eeprom access
HID: wiimote: Allow direct DRM debug access
HID: wiimote: Enable NO_INIT_REPORTS quirk
Documentation/ABI/testing/sysfs-driver-hid-wiimote | 12 +
drivers/hid/Kconfig | 9 +
drivers/hid/Makefile | 8 +
drivers/hid/{hid-wiimote.c => hid-wiimote-core.c} | 245 +++----
drivers/hid/hid-wiimote-debug.c | 227 ++++++
drivers/hid/hid-wiimote-ext.c | 744 ++++++++++++++++++++
drivers/hid/hid-wiimote.h | 208 ++++++
7 files changed, 1317 insertions(+), 136 deletions(-)
rename drivers/hid/{hid-wiimote.c => hid-wiimote-core.c} (90%)
create mode 100644 drivers/hid/hid-wiimote-debug.c
create mode 100644 drivers/hid/hid-wiimote-ext.c
create mode 100644 drivers/hid/hid-wiimote.h
--
1.7.7.3
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 01/16] HID: wiimote: Rename driver to allow multiple source files
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 02/16] HID: wiimote: Move common symbols into header David Herrmann
` (14 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Extension and sound support for the wiimote are quite complex and will be
implemented in separate source files. Hence rename the current driver to "-core"
suffix so multiple files can be linked into this module.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/Makefile | 2 ++
drivers/hid/{hid-wiimote.c => hid-wiimote-core.c} | 0
2 files changed, 2 insertions(+), 0 deletions(-)
rename drivers/hid/{hid-wiimote.c => hid-wiimote-core.c} (100%)
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 0a0a38e..07e750a 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -25,6 +25,8 @@ ifdef CONFIG_LOGIWII_FF
hid-logitech-y += hid-lg4ff.o
endif
+hid-wiimote-y := hid-wiimote-core.o
+
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote-core.c
similarity index 100%
rename from drivers/hid/hid-wiimote.c
rename to drivers/hid/hid-wiimote-core.c
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 02/16] HID: wiimote: Move common symbols into header
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
2011-11-13 13:27 ` [PATCH 01/16] HID: wiimote: Rename driver to allow multiple source files David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 03/16] HID: wiimote: Add read-mem helpers David Herrmann
` (13 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Wiimote extension and sound support need access to several symbols so move them
into a new header.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-core.c | 134 +--------------------------------
drivers/hid/hid-wiimote.h | 163 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 166 insertions(+), 131 deletions(-)
create mode 100644 drivers/hid/hid-wiimote.h
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 76739c0..c955d50 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -20,91 +20,9 @@
#include <linux/power_supply.h>
#include <linux/spinlock.h>
#include "hid-ids.h"
+#include "hid-wiimote.h"
#define WIIMOTE_VERSION "0.2"
-#define WIIMOTE_NAME "Nintendo Wii Remote"
-#define WIIMOTE_BUFSIZE 32
-
-struct wiimote_buf {
- __u8 data[HID_MAX_BUFFER_SIZE];
- size_t size;
-};
-
-struct wiimote_state {
- spinlock_t lock;
- __u8 flags;
- __u8 accel_split[2];
-
- /* synchronous cmd requests */
- struct mutex sync;
- struct completion ready;
- int cmd;
- __u32 opt;
-
- /* results of synchronous requests */
- __u8 cmd_battery;
- __u8 cmd_err;
-};
-
-struct wiimote_data {
- struct hid_device *hdev;
- struct input_dev *input;
- struct led_classdev *leds[4];
- struct input_dev *accel;
- struct input_dev *ir;
- struct power_supply battery;
-
- spinlock_t qlock;
- __u8 head;
- __u8 tail;
- struct wiimote_buf outq[WIIMOTE_BUFSIZE];
- struct work_struct worker;
-
- struct wiimote_state state;
-};
-
-#define WIIPROTO_FLAG_LED1 0x01
-#define WIIPROTO_FLAG_LED2 0x02
-#define WIIPROTO_FLAG_LED3 0x04
-#define WIIPROTO_FLAG_LED4 0x08
-#define WIIPROTO_FLAG_RUMBLE 0x10
-#define WIIPROTO_FLAG_ACCEL 0x20
-#define WIIPROTO_FLAG_IR_BASIC 0x40
-#define WIIPROTO_FLAG_IR_EXT 0x80
-#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */
-#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
- WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
-#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
- WIIPROTO_FLAG_IR_FULL)
-
-/* return flag for led \num */
-#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
-
-enum wiiproto_reqs {
- WIIPROTO_REQ_NULL = 0x0,
- WIIPROTO_REQ_RUMBLE = 0x10,
- WIIPROTO_REQ_LED = 0x11,
- WIIPROTO_REQ_DRM = 0x12,
- WIIPROTO_REQ_IR1 = 0x13,
- WIIPROTO_REQ_SREQ = 0x15,
- WIIPROTO_REQ_WMEM = 0x16,
- WIIPROTO_REQ_RMEM = 0x17,
- WIIPROTO_REQ_IR2 = 0x1a,
- WIIPROTO_REQ_STATUS = 0x20,
- WIIPROTO_REQ_DATA = 0x21,
- WIIPROTO_REQ_RETURN = 0x22,
- WIIPROTO_REQ_DRM_K = 0x30,
- WIIPROTO_REQ_DRM_KA = 0x31,
- WIIPROTO_REQ_DRM_KE = 0x32,
- WIIPROTO_REQ_DRM_KAI = 0x33,
- WIIPROTO_REQ_DRM_KEE = 0x34,
- WIIPROTO_REQ_DRM_KAE = 0x35,
- WIIPROTO_REQ_DRM_KIE = 0x36,
- WIIPROTO_REQ_DRM_KAIE = 0x37,
- WIIPROTO_REQ_DRM_E = 0x3d,
- WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
- WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
-};
enum wiiproto_keys {
WIIPROTO_KEY_LEFT,
@@ -139,52 +57,6 @@ static enum power_supply_property wiimote_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY
};
-/* requires the state.lock spinlock to be held */
-static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
- __u32 opt)
-{
- return wdata->state.cmd == cmd && wdata->state.opt == opt;
-}
-
-/* requires the state.lock spinlock to be held */
-static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
-{
- wdata->state.cmd = WIIPROTO_REQ_NULL;
- complete(&wdata->state.ready);
-}
-
-static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
-{
- return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
-}
-
-/* requires the state.lock spinlock to be held */
-static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd,
- __u32 opt)
-{
- INIT_COMPLETION(wdata->state.ready);
- wdata->state.cmd = cmd;
- wdata->state.opt = opt;
-}
-
-static inline void wiimote_cmd_release(struct wiimote_data *wdata)
-{
- mutex_unlock(&wdata->state.sync);
-}
-
-static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
-{
- int ret;
-
- ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ);
- if (ret < 0)
- return -ERESTARTSYS;
- else if (ret == 0)
- return -EIO;
- else
- return 0;
-}
-
static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
size_t count)
{
@@ -347,7 +219,7 @@ static __u8 select_drm(struct wiimote_data *wdata)
}
}
-static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
+void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
{
__u8 cmd[3];
@@ -441,7 +313,7 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
}
/* requries the cmd-mutex to be held */
-static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
+int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
const __u8 *wmem, __u8 size)
{
unsigned long flags;
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
new file mode 100644
index 0000000..d78f79c
--- /dev/null
+++ b/drivers/hid/hid-wiimote.h
@@ -0,0 +1,163 @@
+#ifndef __HID_WIIMOTE_H
+#define __HID_WIIMOTE_H
+
+/*
+ * HID driver for Nintendo Wiimote devices
+ * Copyright (c) 2011 David Herrmann
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
+#include <linux/spinlock.h>
+
+#define WIIMOTE_NAME "Nintendo Wii Remote"
+#define WIIMOTE_BUFSIZE 32
+
+#define WIIPROTO_FLAG_LED1 0x01
+#define WIIPROTO_FLAG_LED2 0x02
+#define WIIPROTO_FLAG_LED3 0x04
+#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAG_RUMBLE 0x10
+#define WIIPROTO_FLAG_ACCEL 0x20
+#define WIIPROTO_FLAG_IR_BASIC 0x40
+#define WIIPROTO_FLAG_IR_EXT 0x80
+#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */
+#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
+ WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
+ WIIPROTO_FLAG_IR_FULL)
+
+/* return flag for led \num */
+#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
+
+struct wiimote_buf {
+ __u8 data[HID_MAX_BUFFER_SIZE];
+ size_t size;
+};
+
+struct wiimote_state {
+ spinlock_t lock;
+ __u8 flags;
+ __u8 accel_split[2];
+
+ /* synchronous cmd requests */
+ struct mutex sync;
+ struct completion ready;
+ int cmd;
+ __u32 opt;
+
+ /* results of synchronous requests */
+ __u8 cmd_battery;
+ __u8 cmd_err;
+};
+
+struct wiimote_data {
+ struct hid_device *hdev;
+ struct input_dev *input;
+ struct led_classdev *leds[4];
+ struct input_dev *accel;
+ struct input_dev *ir;
+ struct power_supply battery;
+
+ spinlock_t qlock;
+ __u8 head;
+ __u8 tail;
+ struct wiimote_buf outq[WIIMOTE_BUFSIZE];
+ struct work_struct worker;
+
+ struct wiimote_state state;
+};
+
+enum wiiproto_reqs {
+ WIIPROTO_REQ_NULL = 0x0,
+ WIIPROTO_REQ_RUMBLE = 0x10,
+ WIIPROTO_REQ_LED = 0x11,
+ WIIPROTO_REQ_DRM = 0x12,
+ WIIPROTO_REQ_IR1 = 0x13,
+ WIIPROTO_REQ_SREQ = 0x15,
+ WIIPROTO_REQ_WMEM = 0x16,
+ WIIPROTO_REQ_RMEM = 0x17,
+ WIIPROTO_REQ_IR2 = 0x1a,
+ WIIPROTO_REQ_STATUS = 0x20,
+ WIIPROTO_REQ_DATA = 0x21,
+ WIIPROTO_REQ_RETURN = 0x22,
+ WIIPROTO_REQ_DRM_K = 0x30,
+ WIIPROTO_REQ_DRM_KA = 0x31,
+ WIIPROTO_REQ_DRM_KE = 0x32,
+ WIIPROTO_REQ_DRM_KAI = 0x33,
+ WIIPROTO_REQ_DRM_KEE = 0x34,
+ WIIPROTO_REQ_DRM_KAE = 0x35,
+ WIIPROTO_REQ_DRM_KIE = 0x36,
+ WIIPROTO_REQ_DRM_KAIE = 0x37,
+ WIIPROTO_REQ_DRM_E = 0x3d,
+ WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
+ WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
+};
+
+#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
+ dev))
+
+extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm);
+extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
+ const __u8 *wmem, __u8 size);
+
+/* requires the state.lock spinlock to be held */
+static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
+ __u32 opt)
+{
+ return wdata->state.cmd == cmd && wdata->state.opt == opt;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
+{
+ wdata->state.cmd = WIIPROTO_REQ_NULL;
+ complete(&wdata->state.ready);
+}
+
+static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
+{
+ return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd,
+ __u32 opt)
+{
+ INIT_COMPLETION(wdata->state.ready);
+ wdata->state.cmd = cmd;
+ wdata->state.opt = opt;
+}
+
+static inline void wiimote_cmd_release(struct wiimote_data *wdata)
+{
+ mutex_unlock(&wdata->state.sync);
+}
+
+static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
+{
+ int ret;
+
+ ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ);
+ if (ret < 0)
+ return -ERESTARTSYS;
+ else if (ret == 0)
+ return -EIO;
+ else
+ return 0;
+}
+
+#endif
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 03/16] HID: wiimote: Add read-mem helpers
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
2011-11-13 13:27 ` [PATCH 01/16] HID: wiimote: Rename driver to allow multiple source files David Herrmann
2011-11-13 13:27 ` [PATCH 02/16] HID: wiimote: Move common symbols into header David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 04/16] HID: wiimote: Add extension support stub David Herrmann
` (12 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Add helper functions similar to the write-mem helpers but for reading wiimote
memory and eeprom.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-core.c | 77 ++++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 4 ++
2 files changed, 81 insertions(+), 0 deletions(-)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index c955d50..f7f8b7f 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -312,6 +312,37 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
wiimote_queue(wdata, cmd, sizeof(cmd));
}
+#define wiiproto_req_rreg(wdata, os, sz) \
+ wiiproto_req_rmem((wdata), false, (os), (sz))
+
+#define wiiproto_req_reeprom(wdata, os, sz) \
+ wiiproto_req_rmem((wdata), true, (os), (sz))
+
+static void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom,
+ __u32 offset, __u16 size)
+{
+ __u8 cmd[7];
+
+ if (size == 0) {
+ hid_warn(wdata->hdev, "Invalid length %d rmem request\n", size);
+ return;
+ }
+
+ cmd[0] = WIIPROTO_REQ_RMEM;
+ cmd[1] = 0;
+ cmd[2] = (offset >> 16) & 0xff;
+ cmd[3] = (offset >> 8) & 0xff;
+ cmd[4] = offset & 0xff;
+ cmd[5] = (size >> 8) & 0xff;
+ cmd[6] = size & 0xff;
+
+ if (!eeprom)
+ cmd[1] |= 0x04;
+
+ wiiproto_keep_rumble(wdata, &cmd[1]);
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
/* requries the cmd-mutex to be held */
int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
const __u8 *wmem, __u8 size)
@@ -331,6 +362,36 @@ int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
return ret;
}
+/* requries the cmd-mutex to be held */
+ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem,
+ __u8 size)
+{
+ unsigned long flags;
+ ssize_t ret;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.cmd_read_size = size;
+ wdata->state.cmd_read_buf = rmem;
+ wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, offset & 0xffff);
+ wiiproto_req_rreg(wdata, offset, size);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_wait(wdata);
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.cmd_read_buf = NULL;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ if (!ret) {
+ if (wdata->state.cmd_read_size == 0)
+ ret = -EIO;
+ else
+ ret = wdata->state.cmd_read_size;
+ }
+
+ return ret;
+}
+
static int wiimote_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -742,7 +803,23 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
static void handler_data(struct wiimote_data *wdata, const __u8 *payload)
{
+ __u16 offset = payload[3] << 8 | payload[4];
+ __u8 size = (payload[2] >> 4) + 1;
+ __u8 err = payload[2] & 0x0f;
+
handler_keys(wdata, payload);
+
+ if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_RMEM, offset)) {
+ if (err)
+ size = 0;
+ else if (size > wdata->state.cmd_read_size)
+ size = wdata->state.cmd_read_size;
+
+ wdata->state.cmd_read_size = size;
+ if (wdata->state.cmd_read_buf)
+ memcpy(wdata->state.cmd_read_buf, &payload[5], size);
+ wiimote_cmd_complete(wdata);
+ }
}
static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index d78f79c..865740d 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -62,6 +62,8 @@ struct wiimote_state {
/* results of synchronous requests */
__u8 cmd_battery;
__u8 cmd_err;
+ __u8 *cmd_read_buf;
+ __u8 cmd_read_size;
};
struct wiimote_data {
@@ -113,6 +115,8 @@ enum wiiproto_reqs {
extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm);
extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
const __u8 *wmem, __u8 size);
+extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,
+ __u8 *rmem, __u8 size);
/* requires the state.lock spinlock to be held */
static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 04/16] HID: wiimote: Add extension support stub
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (2 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 03/16] HID: wiimote: Add read-mem helpers David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-14 7:54 ` Oliver Neukum
2011-11-13 13:27 ` [PATCH 05/16] HID: wiimote: Add extension initializer stubs David Herrmann
` (11 subsequent siblings)
15 siblings, 1 reply; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
The wiimote supports several extensions. This adds a separate source file which
handles all extensions and can be disabled at compile-time.
The driver reacts on "plug"-events on the extension port and starts a worker
which initializes or deinitializes the extensions.
Currently, the initialization logic is not fully understood and we can only
detect and enable all extensions when all extensions are deactivated. Therefore,
we need to disable all extensions, then detect and activate them again to react
on "plug"-events.
However, deactivating extensions will generate a new "plug"-event and we will
never leave that loop. Hence, we only support extensions if they are plugged
before the wiimote is connected (or before the ext-input device is opened). In
the future we may support full extension hotplug support, but
reverse-engineering this may take a while.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/Kconfig | 9 +++
drivers/hid/Makefile | 3 +
drivers/hid/hid-wiimote-core.c | 23 ++++++-
drivers/hid/hid-wiimote-ext.c | 122 ++++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 17 ++++++
5 files changed, 170 insertions(+), 4 deletions(-)
create mode 100644 drivers/hid/hid-wiimote-ext.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 9907dc9..edf2b2b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -594,6 +594,15 @@ config HID_WIIMOTE
---help---
Support for the Nintendo Wii Remote bluetooth device.
+config HID_WIIMOTE_EXT
+ bool "Nintendo Wii Remote Extension support"
+ depends on HID_WIIMOTE
+ default HID_WIIMOTE
+ ---help---
+ Support for extension controllers of the Nintendo Wii Remote. Say yes
+ here if you want to use the Nintendo Motion+, Nunchuck or Classic
+ extension controllers with your Wii Remote.
+
config HID_ZEROPLUS
tristate "Zeroplus based game controller support"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 07e750a..57d46e6 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -26,6 +26,9 @@ ifdef CONFIG_LOGIWII_FF
endif
hid-wiimote-y := hid-wiimote-core.o
+ifdef CONFIG_HID_WIIMOTE_EXT
+ hid-wiimote-y += hid-wiimote-ext.o
+endif
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index f7f8b7f..2ca8bfd 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -201,6 +201,7 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
static __u8 select_drm(struct wiimote_data *wdata)
{
__u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR;
+ bool ext = wiiext_active(wdata);
if (ir == WIIPROTO_FLAG_IR_BASIC) {
if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
@@ -212,10 +213,17 @@ static __u8 select_drm(struct wiimote_data *wdata)
} else if (ir == WIIPROTO_FLAG_IR_FULL) {
return WIIPROTO_REQ_DRM_SKAI1;
} else {
- if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
- return WIIPROTO_REQ_DRM_KA;
- else
- return WIIPROTO_REQ_DRM_K;
+ if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) {
+ if (ext)
+ return WIIPROTO_REQ_DRM_KAE;
+ else
+ return WIIPROTO_REQ_DRM_KA;
+ } else {
+ if (ext)
+ return WIIPROTO_REQ_DRM_KE;
+ else
+ return WIIPROTO_REQ_DRM_K;
+ }
}
}
@@ -795,6 +803,8 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
/* on status reports the drm is reset so we need to resend the drm */
wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ wiiext_event(wdata, payload[2] & 0x02);
+
if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) {
wdata->state.cmd_battery = payload[5];
wiimote_cmd_complete(wdata);
@@ -1145,6 +1155,7 @@ err:
static void wiimote_destroy(struct wiimote_data *wdata)
{
+ wiiext_deinit(wdata);
wiimote_leds_destroy(wdata);
power_supply_unregister(&wdata->battery);
@@ -1216,6 +1227,10 @@ static int wiimote_hid_probe(struct hid_device *hdev,
if (ret)
goto err_free;
+ ret = wiiext_init(wdata);
+ if (ret)
+ goto err_free;
+
hid_info(hdev, "New device registered\n");
/* by default set led1 after device initialization */
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
new file mode 100644
index 0000000..631566d
--- /dev/null
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -0,0 +1,122 @@
+/*
+ * HID driver for Nintendo Wiimote extension devices
+ * Copyright (c) 2011 David Herrmann
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include "hid-wiimote.h"
+
+struct wiimote_ext {
+ struct wiimote_data *wdata;
+ struct work_struct worker;
+
+ atomic_t opened;
+ atomic_t mp_opened;
+ bool plugged;
+ bool motionp;
+ __u8 ext_type;
+};
+
+enum wiiext_type {
+ WIIEXT_NONE, /* placeholder */
+ WIIEXT_CLASSIC, /* Nintendo classic controller */
+ WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */
+};
+
+static void wiiext_worker(struct work_struct *work)
+{
+ struct wiimote_ext *ext = container_of(work, struct wiimote_ext,
+ worker);
+}
+
+/* schedule work only once, otherwise mark for reschedule */
+static void wiiext_schedule(struct wiimote_ext *ext)
+{
+ queue_work(system_nrt_wq, &ext->worker);
+}
+
+/*
+ * Reacts on extension port events
+ * Whenever the driver gets an event from the wiimote that an extension has been
+ * plugged or unplugged, this funtion shall be called. It checks what extensions
+ * are connected and initializes and activates them.
+ * This can be called in atomic context. The initialization is done in a
+ * separate worker thread. The state.lock spinlock must be held by the caller.
+ */
+void wiiext_event(struct wiimote_data *wdata, bool plugged)
+{
+ if (!wdata->ext)
+ return;
+
+ if (wdata->ext->plugged == plugged)
+ return;
+
+ wdata->ext->plugged = plugged;
+ /*
+ * We need to call wiiext_schedule(wdata->ext) here, however, the
+ * extension initialization logic is not fully understood and so
+ * automatic initialization is not supported, yet.
+ */
+}
+
+/*
+ * Returns true if the current DRM mode should contain extension data and false
+ * if there is no interest in extension data.
+ * All supported extensions send 6 byte extension data so any DRM that contains
+ * extension bytes is fine.
+ * The caller must hold the state.lock spinlock.
+ */
+bool wiiext_active(struct wiimote_data *wdata)
+{
+ if (!wdata->ext)
+ return false;
+
+ return wdata->ext->motionp || wdata->ext->ext_type;
+}
+
+/* Initializes the extension driver of a wiimote */
+int wiiext_init(struct wiimote_data *wdata)
+{
+ struct wiimote_ext *ext;
+ unsigned long flags;
+
+ ext = kzalloc(sizeof(*ext), GFP_KERNEL);
+ if (!ext)
+ return -ENOMEM;
+
+ ext->wdata = wdata;
+ INIT_WORK(&ext->worker, wiiext_worker);
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->ext = ext;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+/* Deinitializes the extension driver of a wiimote */
+void wiiext_deinit(struct wiimote_data *wdata)
+{
+ struct wiimote_ext *ext = wdata->ext;
+ unsigned long flags;
+
+ if (!ext)
+ return;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->ext = NULL;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ cancel_work_sync(&ext->worker);
+ kfree(ext);
+}
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 865740d..abbfab8 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -73,6 +73,7 @@ struct wiimote_data {
struct input_dev *accel;
struct input_dev *ir;
struct power_supply battery;
+ struct wiimote_ext *ext;
spinlock_t qlock;
__u8 head;
@@ -118,6 +119,22 @@ extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,
__u8 *rmem, __u8 size);
+#ifdef CONFIG_HID_WIIMOTE_EXT
+
+extern int wiiext_init(struct wiimote_data *wdata);
+extern void wiiext_deinit(struct wiimote_data *wdata);
+extern void wiiext_event(struct wiimote_data *wdata, bool plugged);
+extern bool wiiext_active(struct wiimote_data *wdata);
+
+#else
+
+static inline int wiiext_init(void *u) { return 0; }
+static inline void wiiext_deinit(void *u) { }
+static inline void wiiext_event(void *u, bool p) { }
+static inline bool wiiext_active(void *u) { return false; }
+
+#endif
+
/* requires the state.lock spinlock to be held */
static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
__u32 opt)
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 05/16] HID: wiimote: Add extension initializer stubs
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (3 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 04/16] HID: wiimote: Add extension support stub David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 06/16] HID: wiimote: Add extension initializers David Herrmann
` (10 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Add stub functions to read and identify extensions and then initialize all
connected extensions.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-ext.c | 38 ++++++++++++++++++++++++++++++++++++++
1 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index 631566d..540feb0 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -33,10 +33,48 @@ enum wiiext_type {
WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */
};
+/* diable all extensions */
+static void ext_disable(struct wiimote_ext *ext)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ext->wdata->state.lock, flags);
+ ext->motionp = false;
+ ext->ext_type = WIIEXT_NONE;
+ spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
+}
+
+static bool motionp_read(struct wiimote_ext *ext)
+{
+ return false;
+}
+
+static __u8 ext_read(struct wiimote_ext *ext)
+{
+ return WIIEXT_NONE;
+}
+
+static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ext->wdata->state.lock, flags);
+ ext->motionp = motionp;
+ ext->ext_type = ext_type;
+ spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
+}
+
static void wiiext_worker(struct work_struct *work)
{
struct wiimote_ext *ext = container_of(work, struct wiimote_ext,
worker);
+ bool motionp;
+ __u8 ext_type;
+
+ ext_disable(ext);
+ motionp = motionp_read(ext);
+ ext_type = ext_read(ext);
+ ext_enable(ext, motionp, ext_type);
}
/* schedule work only once, otherwise mark for reschedule */
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 06/16] HID: wiimote: Add extension initializers
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (4 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 05/16] HID: wiimote: Add extension initializer stubs David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 07/16] HID: wiimote: Add extension sysfs attribute David Herrmann
` (9 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
The wiimote extension registers are not fully understood, so we always disable
all extensions on extension-port events. Then we reinitialize and reidentify
them and activate all requested extensions.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-ext.c | 81 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index 540feb0..d522dd3 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -37,30 +37,107 @@ enum wiiext_type {
static void ext_disable(struct wiimote_ext *ext)
{
unsigned long flags;
+ __u8 wmem = 0x55;
+
+ if (!wiimote_cmd_acquire(ext->wdata)) {
+ wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem));
+ wiimote_cmd_release(ext->wdata);
+ }
spin_lock_irqsave(&ext->wdata->state.lock, flags);
ext->motionp = false;
ext->ext_type = WIIEXT_NONE;
+ wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL);
spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
}
static bool motionp_read(struct wiimote_ext *ext)
{
- return false;
+ __u8 rmem[2], wmem;
+ ssize_t ret;
+ bool avail = false;
+
+ if (wiimote_cmd_acquire(ext->wdata))
+ return false;
+
+ /* initialize motion plus */
+ wmem = 0x55;
+ ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem));
+ if (ret)
+ goto error;
+
+ /* read motion plus ID */
+ ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2);
+ if (ret == 2 || rmem[1] == 0x5)
+ avail = true;
+
+error:
+ wiimote_cmd_release(ext->wdata);
+ return avail;
}
static __u8 ext_read(struct wiimote_ext *ext)
{
- return WIIEXT_NONE;
+ ssize_t ret;
+ __u8 rmem[2], wmem;
+ __u8 type = WIIEXT_NONE;
+
+ if (!ext->plugged)
+ return WIIEXT_NONE;
+
+ if (wiimote_cmd_acquire(ext->wdata))
+ return WIIEXT_NONE;
+
+ /* initialize extension */
+ wmem = 0x55;
+ ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem));
+ if (!ret) {
+ /* disable encryption */
+ wmem = 0x0;
+ wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem));
+ }
+
+ /* read extension ID */
+ ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2);
+ if (ret == 2) {
+ if (rmem[0] == 0 && rmem[1] == 0)
+ type = WIIEXT_NUNCHUCK;
+ else if (rmem[0] == 0x01 && rmem[1] == 0x01)
+ type = WIIEXT_CLASSIC;
+ }
+
+ wiimote_cmd_release(ext->wdata);
+
+ return type;
}
static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type)
{
unsigned long flags;
+ __u8 wmem;
+ int ret;
+
+ if (motionp) {
+ if (wiimote_cmd_acquire(ext->wdata))
+ return;
+
+ if (ext_type == WIIEXT_CLASSIC)
+ wmem = 0x07;
+ else if (ext_type == WIIEXT_NUNCHUCK)
+ wmem = 0x05;
+ else
+ wmem = 0x04;
+
+ ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem));
+ wiimote_cmd_release(ext->wdata);
+ if (ret)
+ return;
+ }
spin_lock_irqsave(&ext->wdata->state.lock, flags);
ext->motionp = motionp;
ext->ext_type = ext_type;
+ wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL);
spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 07/16] HID: wiimote: Add extension sysfs attribute
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (5 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 06/16] HID: wiimote: Add extension initializers David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 08/16] HID: wiimote: Register input devices for extensions David Herrmann
` (8 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Add new sysfs attribute "extension" which returns the currently connected and
initialized extensions.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
Documentation/ABI/testing/sysfs-driver-hid-wiimote | 12 +++++
drivers/hid/hid-wiimote-ext.c | 46 ++++++++++++++++++++
2 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-wiimote b/Documentation/ABI/testing/sysfs-driver-hid-wiimote
index 5d5a16e..3d98009 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-wiimote
+++ b/Documentation/ABI/testing/sysfs-driver-hid-wiimote
@@ -8,3 +8,15 @@ Contact: David Herrmann <dh.herrmann@googlemail.com>
Description: Make it possible to set/get current led state. Reading from it
returns 0 if led is off and 1 if it is on. Writing 0 to it
disables the led, writing 1 enables it.
+
+What: /sys/bus/hid/drivers/wiimote/<dev>/extension
+Date: August 2011
+KernelVersion: 3.2
+Contact: David Herrmann <dh.herrmann@googlemail.com>
+Description: This file contains the currently connected and initialized
+ extensions. It can be one of: none, motionp, nunchuck, classic,
+ motionp+nunchuck, motionp+classic
+ motionp is the official Nintendo Motion+ extension, nunchuck is
+ the official Nintendo Nunchuck extension and classic is the
+ Nintendo Classic Controller extension. The motionp extension can
+ be combined with the other two.
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index d522dd3..a290ef2 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -199,11 +199,47 @@ bool wiiext_active(struct wiimote_data *wdata)
return wdata->ext->motionp || wdata->ext->ext_type;
}
+static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct wiimote_data *wdata = dev_to_wii(dev);
+ __u8 type = WIIEXT_NONE;
+ bool motionp = false;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ if (wdata->ext) {
+ motionp = wdata->ext->motionp;
+ type = wdata->ext->ext_type;
+ }
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ if (type == WIIEXT_NUNCHUCK) {
+ if (motionp)
+ return sprintf(buf, "motionp+nunchuck\n");
+ else
+ return sprintf(buf, "nunchuck\n");
+ } else if (type == WIIEXT_CLASSIC) {
+ if (motionp)
+ return sprintf(buf, "motionp+classic\n");
+ else
+ return sprintf(buf, "classic\n");
+ } else {
+ if (motionp)
+ return sprintf(buf, "motionp\n");
+ else
+ return sprintf(buf, "none\n");
+ }
+}
+
+static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL);
+
/* Initializes the extension driver of a wiimote */
int wiiext_init(struct wiimote_data *wdata)
{
struct wiimote_ext *ext;
unsigned long flags;
+ int ret;
ext = kzalloc(sizeof(*ext), GFP_KERNEL);
if (!ext)
@@ -212,11 +248,19 @@ int wiiext_init(struct wiimote_data *wdata)
ext->wdata = wdata;
INIT_WORK(&ext->worker, wiiext_worker);
+ ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension);
+ if (ret)
+ goto err;
+
spin_lock_irqsave(&wdata->state.lock, flags);
wdata->ext = ext;
spin_unlock_irqrestore(&wdata->state.lock, flags);
return 0;
+
+err:
+ kfree(ext);
+ return ret;
}
/* Deinitializes the extension driver of a wiimote */
@@ -232,6 +276,8 @@ void wiiext_deinit(struct wiimote_data *wdata)
wdata->ext = NULL;
spin_unlock_irqrestore(&wdata->state.lock, flags);
+ device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
+
cancel_work_sync(&ext->worker);
kfree(ext);
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 08/16] HID: wiimote: Register input devices for extensions
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (6 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 07/16] HID: wiimote: Add extension sysfs attribute David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 09/16] HID: wiimote: Add extension handler stubs David Herrmann
` (7 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Motion+ and regular extensions are physical adapters for the wiimote so create
one input device for each of them. This also allows to enable only opened
extensions and turn unused extenions off to save battery power.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-ext.c | 109 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 106 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index a290ef2..cbfb655 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -19,6 +19,8 @@
struct wiimote_ext {
struct wiimote_data *wdata;
struct work_struct worker;
+ struct input_dev *input;
+ struct input_dev *mp_input;
atomic_t opened;
atomic_t mp_opened;
@@ -57,6 +59,9 @@ static bool motionp_read(struct wiimote_ext *ext)
ssize_t ret;
bool avail = false;
+ if (!atomic_read(&ext->mp_opened))
+ return false;
+
if (wiimote_cmd_acquire(ext->wdata))
return false;
@@ -82,7 +87,7 @@ static __u8 ext_read(struct wiimote_ext *ext)
__u8 rmem[2], wmem;
__u8 type = WIIEXT_NONE;
- if (!ext->plugged)
+ if (!ext->plugged || !atomic_read(&ext->opened))
return WIIEXT_NONE;
if (wiimote_cmd_acquire(ext->wdata))
@@ -234,6 +239,54 @@ static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL);
+static int wiiext_input_open(struct input_dev *dev)
+{
+ struct wiimote_ext *ext = input_get_drvdata(dev);
+ int ret;
+
+ ret = hid_hw_open(ext->wdata->hdev);
+ if (ret)
+ return ret;
+
+ atomic_inc(&ext->opened);
+ wiiext_schedule(ext);
+
+ return 0;
+}
+
+static void wiiext_input_close(struct input_dev *dev)
+{
+ struct wiimote_ext *ext = input_get_drvdata(dev);
+
+ atomic_dec(&ext->opened);
+ wiiext_schedule(ext);
+ hid_hw_close(ext->wdata->hdev);
+}
+
+static int wiiext_mp_open(struct input_dev *dev)
+{
+ struct wiimote_ext *ext = input_get_drvdata(dev);
+ int ret;
+
+ ret = hid_hw_open(ext->wdata->hdev);
+ if (ret)
+ return ret;
+
+ atomic_inc(&ext->mp_opened);
+ wiiext_schedule(ext);
+
+ return 0;
+}
+
+static void wiiext_mp_close(struct input_dev *dev)
+{
+ struct wiimote_ext *ext = input_get_drvdata(dev);
+
+ atomic_dec(&ext->mp_opened);
+ wiiext_schedule(ext);
+ hid_hw_close(ext->wdata->hdev);
+}
+
/* Initializes the extension driver of a wiimote */
int wiiext_init(struct wiimote_data *wdata)
{
@@ -248,9 +301,53 @@ int wiiext_init(struct wiimote_data *wdata)
ext->wdata = wdata;
INIT_WORK(&ext->worker, wiiext_worker);
+ ext->input = input_allocate_device();
+ if (!ext->input) {
+ ret = -ENOMEM;
+ goto err_input;
+ }
+
+ input_set_drvdata(ext->input, ext);
+ ext->input->open = wiiext_input_open;
+ ext->input->close = wiiext_input_close;
+ ext->input->dev.parent = &wdata->hdev->dev;
+ ext->input->id.bustype = wdata->hdev->bus;
+ ext->input->id.vendor = wdata->hdev->vendor;
+ ext->input->id.product = wdata->hdev->product;
+ ext->input->id.version = wdata->hdev->version;
+ ext->input->name = WIIMOTE_NAME " Extension";
+
+ ret = input_register_device(ext->input);
+ if (ret) {
+ input_free_device(ext->input);
+ goto err_input;
+ }
+
+ ext->mp_input = input_allocate_device();
+ if (!ext->mp_input) {
+ ret = -ENOMEM;
+ goto err_mp;
+ }
+
+ input_set_drvdata(ext->mp_input, ext);
+ ext->mp_input->open = wiiext_mp_open;
+ ext->mp_input->close = wiiext_mp_close;
+ ext->mp_input->dev.parent = &wdata->hdev->dev;
+ ext->mp_input->id.bustype = wdata->hdev->bus;
+ ext->mp_input->id.vendor = wdata->hdev->vendor;
+ ext->mp_input->id.product = wdata->hdev->product;
+ ext->mp_input->id.version = wdata->hdev->version;
+ ext->mp_input->name = WIIMOTE_NAME " Motion+";
+
+ ret = input_register_device(ext->mp_input);
+ if (ret) {
+ input_free_device(ext->mp_input);
+ goto err_mp;
+ }
+
ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension);
if (ret)
- goto err;
+ goto err_dev;
spin_lock_irqsave(&wdata->state.lock, flags);
wdata->ext = ext;
@@ -258,7 +355,11 @@ int wiiext_init(struct wiimote_data *wdata)
return 0;
-err:
+err_dev:
+ input_unregister_device(ext->mp_input);
+err_mp:
+ input_unregister_device(ext->input);
+err_input:
kfree(ext);
return ret;
}
@@ -277,6 +378,8 @@ void wiiext_deinit(struct wiimote_data *wdata)
spin_unlock_irqrestore(&wdata->state.lock, flags);
device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
+ input_unregister_device(ext->mp_input);
+ input_unregister_device(ext->input);
cancel_work_sync(&ext->worker);
kfree(ext);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 09/16] HID: wiimote: Add extension handler stubs
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (7 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 08/16] HID: wiimote: Register input devices for extensions David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 10/16] HID: wiimote: Parse motion+ data David Herrmann
` (6 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
All supported extensions report data as 6 byte block. All DRMs with extension
data provide at least 6 extension bytes. Hence a generic handler for all
extension bytes is sufficient and can be called on all DRMs.
The handler distinguishes the input and passes it to the right handler. Motion+
passes data interleaved so we can have Motion+ and a regular extension enabled
simultaneously.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-core.c | 6 ++++++
drivers/hid/hid-wiimote-ext.c | 29 +++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 2 ++
3 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 2ca8bfd..d8ed1ec 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -857,6 +857,7 @@ static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload)
static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload)
{
handler_keys(wdata, payload);
+ wiiext_handle(wdata, &payload[2]);
}
static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
@@ -873,6 +874,7 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload)
{
handler_keys(wdata, payload);
+ wiiext_handle(wdata, &payload[2]);
}
static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
@@ -883,12 +885,14 @@ static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
ir_to_input2(wdata, &payload[7], false);
ir_to_input3(wdata, &payload[9], true);
input_sync(wdata->ir);
+ wiiext_handle(wdata, &payload[12]);
}
static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
{
handler_keys(wdata, payload);
handler_accel(wdata, payload);
+ wiiext_handle(wdata, &payload[5]);
}
static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
@@ -900,10 +904,12 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
ir_to_input2(wdata, &payload[10], false);
ir_to_input3(wdata, &payload[12], true);
input_sync(wdata->ir);
+ wiiext_handle(wdata, &payload[15]);
}
static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload)
{
+ wiiext_handle(wdata, payload);
}
static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index cbfb655..e108f0c 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -204,6 +204,35 @@ bool wiiext_active(struct wiimote_data *wdata)
return wdata->ext->motionp || wdata->ext->ext_type;
}
+static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload)
+{
+}
+
+static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
+{
+}
+
+static void handler_classic(struct wiimote_ext *ext, const __u8 *payload)
+{
+}
+
+/* call this with state.lock spinlock held */
+void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload)
+{
+ struct wiimote_ext *ext = wdata->ext;
+
+ if (!ext)
+ return;
+
+ if (ext->motionp && (payload[5] & 0x02)) {
+ handler_motionp(ext, payload);
+ } else if (ext->ext_type == WIIEXT_NUNCHUCK) {
+ handler_nunchuck(ext, payload);
+ } else if (ext->ext_type == WIIEXT_CLASSIC) {
+ handler_classic(ext, payload);
+ }
+}
+
static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index abbfab8..1f3e53a 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -125,6 +125,7 @@ extern int wiiext_init(struct wiimote_data *wdata);
extern void wiiext_deinit(struct wiimote_data *wdata);
extern void wiiext_event(struct wiimote_data *wdata, bool plugged);
extern bool wiiext_active(struct wiimote_data *wdata);
+extern void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload);
#else
@@ -132,6 +133,7 @@ static inline int wiiext_init(void *u) { return 0; }
static inline void wiiext_deinit(void *u) { }
static inline void wiiext_event(void *u, bool p) { }
static inline bool wiiext_active(void *u) { return false; }
+static inline void wiiext_handle(void *u, const __u8 *p) { }
#endif
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 10/16] HID: wiimote: Parse motion+ data
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (8 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 09/16] HID: wiimote: Add extension handler stubs David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 11/16] HID: wiimote: Parse nunchuck data David Herrmann
` (5 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Motion+ reports rotation gyro data which we report to userspace as ABS_RX/Y/Z
values. The device reports them either in fast or slow mode. We adjust the
values to get a linear scale so userspace does not need to know about slow and
fast mode.
The motion+ also reports whether an extension is connected to it. We keep track
of this value and reinitialize the extensions if an extension is plugged or
unplugged.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-ext.c | 70 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index e108f0c..5953862 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -25,6 +25,7 @@ struct wiimote_ext {
atomic_t opened;
atomic_t mp_opened;
bool plugged;
+ bool mp_plugged;
bool motionp;
__u8 ext_type;
};
@@ -182,6 +183,10 @@ void wiiext_event(struct wiimote_data *wdata, bool plugged)
return;
wdata->ext->plugged = plugged;
+
+ if (!plugged)
+ wdata->ext->mp_plugged = false;
+
/*
* We need to call wiiext_schedule(wdata->ext) here, however, the
* extension initialization logic is not fully understood and so
@@ -206,6 +211,63 @@ bool wiiext_active(struct wiimote_data *wdata)
static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload)
{
+ __s32 x, y, z;
+ bool plugged;
+
+ /* | 8 7 6 5 4 3 | 2 | 1 |
+ * -----+------------------------------+-----+-----+
+ * 1 | Yaw Speed <7:0> |
+ * 2 | Roll Speed <7:0> |
+ * 3 | Pitch Speed <7:0> |
+ * -----+------------------------------+-----+-----+
+ * 4 | Yaw Speed <13:8> | Yaw |Pitch|
+ * -----+------------------------------+-----+-----+
+ * 5 | Roll Speed <13:8> |Roll | Ext |
+ * -----+------------------------------+-----+-----+
+ * 6 | Pitch Speed <13:8> | 1 | 0 |
+ * -----+------------------------------+-----+-----+
+ * The single bits Yaw, Roll, Pitch in the lower right corner specify
+ * whether the wiimote is rotating fast (0) or slow (1). Speed for slow
+ * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a
+ * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast
+ * and 9 for slow.
+ * If the wiimote is not rotating the sensor reports 2^13 = 8192.
+ * Ext specifies whether an extension is connected to the motionp.
+ */
+
+ x = payload[0];
+ y = payload[1];
+ z = payload[2];
+
+ x |= (((__u16)payload[3]) << 6) & 0xff00;
+ y |= (((__u16)payload[4]) << 6) & 0xff00;
+ z |= (((__u16)payload[5]) << 6) & 0xff00;
+
+ x -= 8192;
+ y -= 8192;
+ z -= 8192;
+
+ if (!(payload[3] & 0x02))
+ x *= 18;
+ else
+ x *= 9;
+ if (!(payload[4] & 0x02))
+ y *= 18;
+ else
+ y *= 9;
+ if (!(payload[3] & 0x01))
+ z *= 18;
+ else
+ z *= 9;
+
+ input_report_abs(ext->mp_input, ABS_RX, x);
+ input_report_abs(ext->mp_input, ABS_RY, y);
+ input_report_abs(ext->mp_input, ABS_RZ, z);
+ input_sync(ext->mp_input);
+
+ plugged = payload[5] & 0x01;
+ if (plugged != ext->mp_plugged)
+ ext->mp_plugged = plugged;
}
static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
@@ -368,6 +430,14 @@ int wiiext_init(struct wiimote_data *wdata)
ext->mp_input->id.version = wdata->hdev->version;
ext->mp_input->name = WIIMOTE_NAME " Motion+";
+ set_bit(EV_ABS, ext->mp_input->evbit);
+ set_bit(ABS_RX, ext->mp_input->absbit);
+ set_bit(ABS_RY, ext->mp_input->absbit);
+ set_bit(ABS_RZ, ext->mp_input->absbit);
+ input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8);
+ input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8);
+ input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8);
+
ret = input_register_device(ext->mp_input);
if (ret) {
input_free_device(ext->mp_input);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 11/16] HID: wiimote: Parse nunchuck data
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (9 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 10/16] HID: wiimote: Parse motion+ data David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 12/16] HID: wiimote: Parse classic controller data David Herrmann
` (4 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
The Nintendo Nunchuck extension reports accelerometer values, one analog stick
and two buttons. See inline comments for data layout.
We report all data to userspace through extension input device.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-ext.c | 105 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 104 insertions(+), 1 deletions(-)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index 5953862..bac2e45 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -36,6 +36,17 @@ enum wiiext_type {
WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */
};
+enum wiiext_keys {
+ WIIEXT_KEY_C,
+ WIIEXT_KEY_Z,
+ WIIEXT_KEY_COUNT
+};
+
+static __u16 wiiext_keymap[] = {
+ BTN_C, /* WIIEXT_KEY_C */
+ BTN_Z, /* WIIEXT_KEY_Z */
+};
+
/* diable all extensions */
static void ext_disable(struct wiimote_ext *ext)
{
@@ -272,6 +283,82 @@ static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload)
static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
{
+ __s16 x, y, z, bx, by;
+
+ /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 |
+ * -----+----------+---------+---------+----+-----+
+ * 1 | Button X <7:0> |
+ * 2 | Button Y <7:0> |
+ * -----+----------+---------+---------+----+-----+
+ * 3 | Speed X <9:2> |
+ * 4 | Speed Y <9:2> |
+ * 5 | Speed Z <9:2> |
+ * -----+----------+---------+---------+----+-----+
+ * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ |
+ * -----+----------+---------+---------+----+-----+
+ * Button X/Y is the analog stick. Speed X, Y and Z are the
+ * accelerometer data in the same format as the wiimote's accelerometer.
+ * The 6th byte contains the LSBs of the accelerometer data.
+ * BC and BZ are the C and Z buttons: 0 means pressed
+ *
+ * If reported interleaved with motionp, then the layout changes. The
+ * 5th and 6th byte changes to:
+ * -----+-----------------------------------+-----+
+ * 5 | Speed Z <9:3> | EXT |
+ * -----+--------+-----+-----+----+----+----+-----+
+ * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 |
+ * -----+--------+-----+-----+----+----+----+-----+
+ * All three accelerometer values lose their LSB. The other data is
+ * still available but slightly moved.
+ *
+ * Center data for button values is 128. Center value for accelerometer
+ * values it 512 / 0x200
+ */
+
+ bx = payload[0];
+ by = payload[1];
+ bx -= 128;
+ by -= 128;
+
+ x = payload[2] << 2;
+ y = payload[3] << 2;
+ z = payload[4] << 2;
+
+ if (ext->motionp) {
+ x |= (payload[5] >> 3) & 0x02;
+ y |= (payload[5] >> 4) & 0x02;
+ z &= ~0x4;
+ z |= (payload[5] >> 5) & 0x06;
+ } else {
+ x |= (payload[5] >> 2) & 0x03;
+ y |= (payload[5] >> 4) & 0x03;
+ z |= (payload[5] >> 6) & 0x03;
+ }
+
+ x -= 0x200;
+ y -= 0x200;
+ z -= 0x200;
+
+ input_report_abs(ext->input, ABS_HAT0X, bx);
+ input_report_abs(ext->input, ABS_HAT0Y, by);
+
+ input_report_abs(ext->input, ABS_RX, x);
+ input_report_abs(ext->input, ABS_RY, y);
+ input_report_abs(ext->input, ABS_RZ, z);
+
+ if (ext->motionp) {
+ input_report_key(ext->input,
+ wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04));
+ input_report_key(ext->input,
+ wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08));
+ } else {
+ input_report_key(ext->input,
+ wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01));
+ input_report_key(ext->input,
+ wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02));
+ }
+
+ input_sync(ext->input);
}
static void handler_classic(struct wiimote_ext *ext, const __u8 *payload)
@@ -383,7 +470,7 @@ int wiiext_init(struct wiimote_data *wdata)
{
struct wiimote_ext *ext;
unsigned long flags;
- int ret;
+ int ret, i;
ext = kzalloc(sizeof(*ext), GFP_KERNEL);
if (!ext)
@@ -408,6 +495,22 @@ int wiiext_init(struct wiimote_data *wdata)
ext->input->id.version = wdata->hdev->version;
ext->input->name = WIIMOTE_NAME " Extension";
+ set_bit(EV_KEY, ext->input->evbit);
+ for (i = 0; i < WIIEXT_KEY_COUNT; ++i)
+ set_bit(wiiext_keymap[i], ext->input->keybit);
+
+ set_bit(EV_ABS, ext->input->evbit);
+ set_bit(ABS_HAT0X, ext->input->absbit);
+ set_bit(ABS_HAT0Y, ext->input->absbit);
+ input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4);
+ input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4);
+ set_bit(ABS_RX, ext->input->absbit);
+ set_bit(ABS_RY, ext->input->absbit);
+ set_bit(ABS_RZ, ext->input->absbit);
+ input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4);
+ input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4);
+ input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4);
+
ret = input_register_device(ext->input);
if (ret) {
input_free_device(ext->input);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 12/16] HID: wiimote: Parse classic controller data
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (10 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 11/16] HID: wiimote: Parse nunchuck data David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 13/16] HID: wiimote: Add debugfs support stubs David Herrmann
` (3 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Nintendo Classic Controller extension reports lots of keys, two analog sticks
and two analog buttons. We report all data through extension input device to
userspace.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-ext.c | 156 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 156 insertions(+), 0 deletions(-)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index bac2e45..2160c3a 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -39,12 +39,42 @@ enum wiiext_type {
enum wiiext_keys {
WIIEXT_KEY_C,
WIIEXT_KEY_Z,
+ WIIEXT_KEY_A,
+ WIIEXT_KEY_B,
+ WIIEXT_KEY_X,
+ WIIEXT_KEY_Y,
+ WIIEXT_KEY_ZL,
+ WIIEXT_KEY_ZR,
+ WIIEXT_KEY_PLUS,
+ WIIEXT_KEY_MINUS,
+ WIIEXT_KEY_HOME,
+ WIIEXT_KEY_LEFT,
+ WIIEXT_KEY_RIGHT,
+ WIIEXT_KEY_UP,
+ WIIEXT_KEY_DOWN,
+ WIIEXT_KEY_LT,
+ WIIEXT_KEY_RT,
WIIEXT_KEY_COUNT
};
static __u16 wiiext_keymap[] = {
BTN_C, /* WIIEXT_KEY_C */
BTN_Z, /* WIIEXT_KEY_Z */
+ BTN_A, /* WIIEXT_KEY_A */
+ BTN_B, /* WIIEXT_KEY_B */
+ BTN_X, /* WIIEXT_KEY_X */
+ BTN_Y, /* WIIEXT_KEY_Y */
+ BTN_TL2, /* WIIEXT_KEY_ZL */
+ BTN_TR2, /* WIIEXT_KEY_ZR */
+ KEY_NEXT, /* WIIEXT_KEY_PLUS */
+ KEY_PREVIOUS, /* WIIEXT_KEY_MINUS */
+ BTN_MODE, /* WIIEXT_KEY_HOME */
+ KEY_LEFT, /* WIIEXT_KEY_LEFT */
+ KEY_RIGHT, /* WIIEXT_KEY_RIGHT */
+ KEY_UP, /* WIIEXT_KEY_UP */
+ KEY_DOWN, /* WIIEXT_KEY_DOWN */
+ BTN_TL, /* WIIEXT_KEY_LT */
+ BTN_TR, /* WIIEXT_KEY_RT */
};
/* diable all extensions */
@@ -363,6 +393,120 @@ static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
static void handler_classic(struct wiimote_ext *ext, const __u8 *payload)
{
+ __s8 rx, ry, lx, ly, lt, rt;
+
+ /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | RX <5:4> | LX <5:0> |
+ * 2 | RX <3:2> | LY <5:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 3 |RX<1>| LT <5:4> | RY <5:1> |
+ * -----+-----+-----------+-----------------------------+
+ * 4 | LT <3:1> | RT <5:1> |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * All buttons are 0 if pressed
+ * RX and RY are right analog stick
+ * LX and LY are left analog stick
+ * LT is left trigger, RT is right trigger
+ * BLT is 0 if left trigger is fully pressed
+ * BRT is 0 if right trigger is fully pressed
+ * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons
+ * BZL is left Z button and BZR is right Z button
+ * B-, BH, B+ are +, HOME and - buttons
+ * BB, BY, BA, BX are A, B, X, Y buttons
+ * LSB of RX, RY, LT, and RT are not transmitted and always 0.
+ *
+ * With motionp enabled it changes slightly to this:
+ * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | RX <4:3> | LX <5:1> | BDU |
+ * 2 | RX <2:1> | LY <5:1> | BDL |
+ * -----+-----+-----+-----+-----------------------+-----+
+ * 3 |RX<0>| LT <4:3> | RY <4:0> |
+ * -----+-----+-----------+-----------------------------+
+ * 4 | LT <2:0> | RT <4:0> |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest
+ * is the same as before.
+ */
+
+ if (ext->motionp) {
+ lx = payload[0] & 0x3e;
+ ly = payload[0] & 0x3e;
+ } else {
+ lx = payload[0] & 0x3f;
+ ly = payload[0] & 0x3f;
+ }
+
+ rx = (payload[0] >> 3) & 0x14;
+ rx |= (payload[1] >> 5) & 0x06;
+ rx |= (payload[2] >> 7) & 0x01;
+ ry = payload[2] & 0x1f;
+
+ rt = payload[3] & 0x1f;
+ lt = (payload[2] >> 2) & 0x18;
+ lt |= (payload[3] >> 5) & 0x07;
+
+ rx <<= 1;
+ ry <<= 1;
+ rt <<= 1;
+ lt <<= 1;
+
+ input_report_abs(ext->input, ABS_HAT1X, lx - 0x20);
+ input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20);
+ input_report_abs(ext->input, ABS_HAT2X, rx - 0x20);
+ input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20);
+ input_report_abs(ext->input, ABS_HAT3X, rt - 0x20);
+ input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20);
+
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT],
+ !!(payload[4] & 0x80));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN],
+ !!(payload[4] & 0x40));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT],
+ !!(payload[4] & 0x20));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS],
+ !!(payload[4] & 0x10));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME],
+ !!(payload[4] & 0x08));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS],
+ !!(payload[4] & 0x04));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT],
+ !!(payload[4] & 0x02));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL],
+ !!(payload[5] & 0x80));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B],
+ !!(payload[5] & 0x40));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y],
+ !!(payload[5] & 0x20));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A],
+ !!(payload[5] & 0x10));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X],
+ !!(payload[5] & 0x08));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR],
+ !!(payload[5] & 0x04));
+
+ if (ext->motionp) {
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP],
+ !!(payload[0] & 0x01));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT],
+ !!(payload[1] & 0x01));
+ } else {
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP],
+ !!(payload[5] & 0x01));
+ input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT],
+ !!(payload[5] & 0x02));
+ }
+
+ input_sync(ext->input);
}
/* call this with state.lock spinlock held */
@@ -502,8 +646,20 @@ int wiiext_init(struct wiimote_data *wdata)
set_bit(EV_ABS, ext->input->evbit);
set_bit(ABS_HAT0X, ext->input->absbit);
set_bit(ABS_HAT0Y, ext->input->absbit);
+ set_bit(ABS_HAT1X, ext->input->absbit);
+ set_bit(ABS_HAT1Y, ext->input->absbit);
+ set_bit(ABS_HAT2X, ext->input->absbit);
+ set_bit(ABS_HAT2Y, ext->input->absbit);
+ set_bit(ABS_HAT3X, ext->input->absbit);
+ set_bit(ABS_HAT3Y, ext->input->absbit);
input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4);
input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4);
+ input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1);
+ input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1);
+ input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1);
+ input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1);
+ input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1);
+ input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1);
set_bit(ABS_RX, ext->input->absbit);
set_bit(ABS_RY, ext->input->absbit);
set_bit(ABS_RZ, ext->input->absbit);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 13/16] HID: wiimote: Add debugfs support stubs
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (11 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 12/16] HID: wiimote: Parse classic controller data David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 14/16] HID: wiimote: Allow direct eeprom access David Herrmann
` (2 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Add initializer and deinitializer for debugfs support. This will later allow raw
eeprom access and direct DRM modifications to debug wiimote behaviour and
further protocol reverse-engineerings.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/Makefile | 3 ++
drivers/hid/hid-wiimote-core.c | 5 +++
drivers/hid/hid-wiimote-debug.c | 52 +++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 13 +++++++++
4 files changed, 73 insertions(+), 0 deletions(-)
create mode 100644 drivers/hid/hid-wiimote-debug.c
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 57d46e6..adbc933 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -29,6 +29,9 @@ hid-wiimote-y := hid-wiimote-core.o
ifdef CONFIG_HID_WIIMOTE_EXT
hid-wiimote-y += hid-wiimote-ext.o
endif
+ifdef CONFIG_DEBUG_FS
+ hid-wiimote-y += hid-wiimote-debug.o
+endif
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index d8ed1ec..919abba 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -1161,6 +1161,7 @@ err:
static void wiimote_destroy(struct wiimote_data *wdata)
{
+ wiidebug_deinit(wdata);
wiiext_deinit(wdata);
wiimote_leds_destroy(wdata);
@@ -1237,6 +1238,10 @@ static int wiimote_hid_probe(struct hid_device *hdev,
if (ret)
goto err_free;
+ ret = wiidebug_init(wdata);
+ if (ret)
+ goto err_free;
+
hid_info(hdev, "New device registered\n");
/* by default set led1 after device initialization */
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c
new file mode 100644
index 0000000..6282e3c
--- /dev/null
+++ b/drivers/hid/hid-wiimote-debug.c
@@ -0,0 +1,52 @@
+/*
+ * Debug support for HID Nintendo Wiimote devices
+ * Copyright (c) 2011 David Herrmann
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "hid-wiimote.h"
+
+struct wiimote_debug {
+ struct wiimote_data *wdata;
+};
+
+int wiidebug_init(struct wiimote_data *wdata)
+{
+ struct wiimote_debug *dbg;
+ unsigned long flags;
+
+ dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
+ if (!dbg)
+ return -ENOMEM;
+
+ dbg->wdata = wdata;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->debug = dbg;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+void wiidebug_deinit(struct wiimote_data *wdata)
+{
+ struct wiimote_debug *dbg = wdata->debug;
+ unsigned long flags;
+
+ if (!dbg)
+ return;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->debug = NULL;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ kfree(dbg);
+}
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 1f3e53a..89b8851 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -74,6 +74,7 @@ struct wiimote_data {
struct input_dev *ir;
struct power_supply battery;
struct wiimote_ext *ext;
+ struct wiimote_debug *debug;
spinlock_t qlock;
__u8 head;
@@ -137,6 +138,18 @@ static inline void wiiext_handle(void *u, const __u8 *p) { }
#endif
+#ifdef CONFIG_DEBUG_FS
+
+extern int wiidebug_init(struct wiimote_data *wdata);
+extern void wiidebug_deinit(struct wiimote_data *wdata);
+
+#else
+
+static inline int wiidebug_init(void *u) { return 0; }
+static inline void wiidebug_deinit(void *u) { }
+
+#endif
+
/* requires the state.lock spinlock to be held */
static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
__u32 opt)
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 14/16] HID: wiimote: Allow direct eeprom access
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (12 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 13/16] HID: wiimote: Add debugfs support stubs David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 15/16] HID: wiimote: Allow direct DRM debug access David Herrmann
2011-11-13 13:27 ` [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk David Herrmann
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
The wiimote provides direct access to parts of its eeprom. This implements read
support for small chunks of the eeprom. This isn't very fast but prevents the
reader from blocking the wiimote stream for too long.
Write support is not yet supported as the wiimote breaks if we overwrite its
memory. Use hidraw to reverse-engineer the eeprom before implementing write
support here.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-core.c | 10 +----
drivers/hid/hid-wiimote-debug.c | 76 +++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 7 ++++
3 files changed, 85 insertions(+), 8 deletions(-)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 919abba..2fd2f03 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -320,14 +320,8 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
wiimote_queue(wdata, cmd, sizeof(cmd));
}
-#define wiiproto_req_rreg(wdata, os, sz) \
- wiiproto_req_rmem((wdata), false, (os), (sz))
-
-#define wiiproto_req_reeprom(wdata, os, sz) \
- wiiproto_req_rmem((wdata), true, (os), (sz))
-
-static void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom,
- __u32 offset, __u16 size)
+void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, __u32 offset,
+ __u16 size)
{
__u8 cmd[7];
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c
index 6282e3c..f81243c 100644
--- a/drivers/hid/hid-wiimote-debug.c
+++ b/drivers/hid/hid-wiimote-debug.c
@@ -10,12 +10,80 @@
* any later version.
*/
+#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/uaccess.h>
#include "hid-wiimote.h"
struct wiimote_debug {
struct wiimote_data *wdata;
+ struct dentry *eeprom;
+};
+
+static int wiidebug_eeprom_open(struct inode *i, struct file *f)
+{
+ f->private_data = i->i_private;
+ return 0;
+}
+
+static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
+ loff_t *off)
+{
+ struct wiimote_debug *dbg = f->private_data;
+ struct wiimote_data *wdata = dbg->wdata;
+ unsigned long flags;
+ ssize_t ret;
+ char buf[16];
+ __u16 size;
+
+ if (s == 0)
+ return -EINVAL;
+ if (*off > 0xffffff)
+ return 0;
+ if (s > 16)
+ s = 16;
+
+ ret = wiimote_cmd_acquire(wdata);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.cmd_read_size = s;
+ wdata->state.cmd_read_buf = buf;
+ wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff);
+ wiiproto_req_reeprom(wdata, *off, s);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_wait(wdata);
+ if (!ret)
+ size = wdata->state.cmd_read_size;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.cmd_read_buf = NULL;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ wiimote_cmd_release(wdata);
+
+ if (ret)
+ return ret;
+ else if (size == 0)
+ return -EIO;
+
+ if (copy_to_user(u, buf, size))
+ return -EFAULT;
+
+ *off += size;
+ ret = size;
+
+ return ret;
+}
+
+static const struct file_operations wiidebug_eeprom_fops = {
+ .owner = THIS_MODULE,
+ .open = wiidebug_eeprom_open,
+ .read = wiidebug_eeprom_read,
+ .llseek = generic_file_llseek,
};
int wiidebug_init(struct wiimote_data *wdata)
@@ -29,6 +97,13 @@ int wiidebug_init(struct wiimote_data *wdata)
dbg->wdata = wdata;
+ dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR,
+ dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops);
+ if (!dbg->eeprom) {
+ kfree(dbg);
+ return -ENOMEM;
+ }
+
spin_lock_irqsave(&wdata->state.lock, flags);
wdata->debug = dbg;
spin_unlock_irqrestore(&wdata->state.lock, flags);
@@ -48,5 +123,6 @@ void wiidebug_deinit(struct wiimote_data *wdata)
wdata->debug = NULL;
spin_unlock_irqrestore(&wdata->state.lock, flags);
+ debugfs_remove(dbg->eeprom);
kfree(dbg);
}
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 89b8851..7b67657 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -120,6 +120,13 @@ extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,
__u8 *rmem, __u8 size);
+#define wiiproto_req_rreg(wdata, os, sz) \
+ wiiproto_req_rmem((wdata), false, (os), (sz))
+#define wiiproto_req_reeprom(wdata, os, sz) \
+ wiiproto_req_rmem((wdata), true, (os), (sz))
+extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom,
+ __u32 offset, __u16 size);
+
#ifdef CONFIG_HID_WIIMOTE_EXT
extern int wiiext_init(struct wiimote_data *wdata);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 15/16] HID: wiimote: Allow direct DRM debug access
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (13 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 14/16] HID: wiimote: Allow direct eeprom access David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-13 13:27 ` [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk David Herrmann
15 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Keep track of current drm and add new debugfs file which reads or writes the
current DRM.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-core.c | 2 +
drivers/hid/hid-wiimote-debug.c | 107 +++++++++++++++++++++++++++++++++++++--
drivers/hid/hid-wiimote.h | 2 +
3 files changed, 107 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 2fd2f03..745667e 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -238,6 +238,7 @@ void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
cmd[1] = 0;
cmd[2] = drm;
+ wdata->state.drm = drm;
wiiproto_keep_rumble(wdata, &cmd[1]);
wiimote_queue(wdata, cmd, sizeof(cmd));
}
@@ -1141,6 +1142,7 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
spin_lock_init(&wdata->state.lock);
init_completion(&wdata->state.ready);
mutex_init(&wdata->state.sync);
+ wdata->state.drm = WIIPROTO_REQ_DRM_K;
return wdata;
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c
index f81243c..17dabc1 100644
--- a/drivers/hid/hid-wiimote-debug.c
+++ b/drivers/hid/hid-wiimote-debug.c
@@ -12,6 +12,7 @@
#include <linux/debugfs.h>
#include <linux/module.h>
+#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include "hid-wiimote.h"
@@ -19,6 +20,7 @@
struct wiimote_debug {
struct wiimote_data *wdata;
struct dentry *eeprom;
+ struct dentry *drm;
};
static int wiidebug_eeprom_open(struct inode *i, struct file *f)
@@ -86,10 +88,97 @@ static const struct file_operations wiidebug_eeprom_fops = {
.llseek = generic_file_llseek,
};
+static const char *wiidebug_drmmap[] = {
+ [WIIPROTO_REQ_NULL] = "NULL",
+ [WIIPROTO_REQ_DRM_K] = "K",
+ [WIIPROTO_REQ_DRM_KA] = "KA",
+ [WIIPROTO_REQ_DRM_KE] = "KE",
+ [WIIPROTO_REQ_DRM_KAI] = "KAI",
+ [WIIPROTO_REQ_DRM_KEE] = "KEE",
+ [WIIPROTO_REQ_DRM_KAE] = "KAE",
+ [WIIPROTO_REQ_DRM_KIE] = "KIE",
+ [WIIPROTO_REQ_DRM_KAIE] = "KAIE",
+ [WIIPROTO_REQ_DRM_E] = "E",
+ [WIIPROTO_REQ_DRM_SKAI1] = "SKAI1",
+ [WIIPROTO_REQ_DRM_SKAI2] = "SKAI2",
+ [WIIPROTO_REQ_MAX] = NULL
+};
+
+static int wiidebug_drm_show(struct seq_file *f, void *p)
+{
+ struct wiimote_debug *dbg = f->private;
+ const char *str = NULL;
+ unsigned long flags;
+ __u8 drm;
+
+ spin_lock_irqsave(&dbg->wdata->state.lock, flags);
+ drm = dbg->wdata->state.drm;
+ spin_unlock_irqrestore(&dbg->wdata->state.lock, flags);
+
+ if (drm < WIIPROTO_REQ_MAX)
+ str = wiidebug_drmmap[drm];
+ if (!str)
+ str = "unknown";
+
+ seq_printf(f, "%s\n", str);
+
+ return 0;
+}
+
+static int wiidebug_drm_open(struct inode *i, struct file *f)
+{
+ return single_open(f, wiidebug_drm_show, i->i_private);
+}
+
+static ssize_t wiidebug_drm_write(struct file *f, const char __user *u,
+ size_t s, loff_t *off)
+{
+ struct wiimote_debug *dbg = f->private_data;
+ unsigned long flags;
+ char buf[16];
+ ssize_t len;
+ int i;
+
+ if (s == 0)
+ return -EINVAL;
+
+ len = min((size_t) 15, s);
+ if (copy_from_user(buf, u, len))
+ return -EFAULT;
+
+ buf[15] = 0;
+
+ for (i = 0; i < WIIPROTO_REQ_MAX; ++i) {
+ if (!wiidebug_drmmap[i])
+ continue;
+ if (!strcasecmp(buf, wiidebug_drmmap[i]))
+ break;
+ }
+
+ if (i == WIIPROTO_REQ_MAX)
+ i = simple_strtoul(buf, NULL, 10);
+
+ spin_lock_irqsave(&dbg->wdata->state.lock, flags);
+ wiiproto_req_drm(dbg->wdata, (__u8) i);
+ spin_unlock_irqrestore(&dbg->wdata->state.lock, flags);
+
+ return len;
+}
+
+static const struct file_operations wiidebug_drm_fops = {
+ .owner = THIS_MODULE,
+ .open = wiidebug_drm_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = wiidebug_drm_write,
+ .release = single_release,
+};
+
int wiidebug_init(struct wiimote_data *wdata)
{
struct wiimote_debug *dbg;
unsigned long flags;
+ int ret = -ENOMEM;
dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
if (!dbg)
@@ -99,16 +188,25 @@ int wiidebug_init(struct wiimote_data *wdata)
dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR,
dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops);
- if (!dbg->eeprom) {
- kfree(dbg);
- return -ENOMEM;
- }
+ if (!dbg->eeprom)
+ goto err;
+
+ dbg->drm = debugfs_create_file("drm", S_IRUSR,
+ dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops);
+ if (!dbg->drm)
+ goto err_drm;
spin_lock_irqsave(&wdata->state.lock, flags);
wdata->debug = dbg;
spin_unlock_irqrestore(&wdata->state.lock, flags);
return 0;
+
+err_drm:
+ debugfs_remove(dbg->eeprom);
+err:
+ kfree(dbg);
+ return ret;
}
void wiidebug_deinit(struct wiimote_data *wdata)
@@ -123,6 +221,7 @@ void wiidebug_deinit(struct wiimote_data *wdata)
wdata->debug = NULL;
spin_unlock_irqrestore(&wdata->state.lock, flags);
+ debugfs_remove(dbg->drm);
debugfs_remove(dbg->eeprom);
kfree(dbg);
}
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 7b67657..c81dbeb 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -52,6 +52,7 @@ struct wiimote_state {
spinlock_t lock;
__u8 flags;
__u8 accel_split[2];
+ __u8 drm;
/* synchronous cmd requests */
struct mutex sync;
@@ -109,6 +110,7 @@ enum wiiproto_reqs {
WIIPROTO_REQ_DRM_E = 0x3d,
WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
+ WIIPROTO_REQ_MAX
};
#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
` (14 preceding siblings ...)
2011-11-13 13:27 ` [PATCH 15/16] HID: wiimote: Allow direct DRM debug access David Herrmann
@ 2011-11-13 13:27 ` David Herrmann
2011-11-16 17:05 ` Jiri Kosina
15 siblings, 1 reply; 25+ messages in thread
From: David Herrmann @ 2011-11-13 13:27 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, David Herrmann
Newer bluetooth core supports the NO_INIT_REPORTS quirk. We need this for the
wiimote as it does not support report-initialization.
Also bump version level as we are almost feature complete now.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote-core.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 745667e..7ea8754 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -22,7 +22,7 @@
#include "hid-ids.h"
#include "hid-wiimote.h"
-#define WIIMOTE_VERSION "0.2"
+#define WIIMOTE_VERSION "0.3"
enum wiiproto_keys {
WIIPROTO_KEY_LEFT,
@@ -1177,6 +1177,8 @@ static int wiimote_hid_probe(struct hid_device *hdev,
struct wiimote_data *wdata;
int ret;
+ hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+
wdata = wiimote_create(hdev);
if (!wdata) {
hid_err(hdev, "Can't alloc device\n");
--
1.7.7.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 04/16] HID: wiimote: Add extension support stub
2011-11-13 13:27 ` [PATCH 04/16] HID: wiimote: Add extension support stub David Herrmann
@ 2011-11-14 7:54 ` Oliver Neukum
2011-11-14 11:26 ` David Herrmann
0 siblings, 1 reply; 25+ messages in thread
From: Oliver Neukum @ 2011-11-14 7:54 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-input, jkosina
Am Sonntag, 13. November 2011, 14:27:07 schrieb David Herrmann:
> +/* Deinitializes the extension driver of a wiimote */
> +void wiiext_deinit(struct wiimote_data *wdata)
> +{
> + struct wiimote_ext *ext = wdata->ext;
> + unsigned long flags;
> +
> + if (!ext)
> + return;
> +
> + spin_lock_irqsave(&wdata->state.lock, flags);
> + wdata->ext = NULL;
> + spin_unlock_irqrestore(&wdata->state.lock, flags);
> +
> + cancel_work_sync(&ext->worker);
> + kfree(ext);
> +}
Are you sure you are doing this in the correct order?
You are needlessly leaving a window where wdate->ext is NULL
but the worker may run.
Regards
Oliver
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 04/16] HID: wiimote: Add extension support stub
2011-11-14 7:54 ` Oliver Neukum
@ 2011-11-14 11:26 ` David Herrmann
2011-11-14 11:35 ` Oliver Neukum
0 siblings, 1 reply; 25+ messages in thread
From: David Herrmann @ 2011-11-14 11:26 UTC (permalink / raw)
To: Oliver Neukum; +Cc: linux-input, jkosina
Hi Oliver
On Mon, Nov 14, 2011 at 8:54 AM, Oliver Neukum <oneukum@suse.de> wrote:
> Am Sonntag, 13. November 2011, 14:27:07 schrieb David Herrmann:
>> +/* Deinitializes the extension driver of a wiimote */
>> +void wiiext_deinit(struct wiimote_data *wdata)
>> +{
>> + struct wiimote_ext *ext = wdata->ext;
>> + unsigned long flags;
>> +
>> + if (!ext)
>> + return;
>> +
>> + spin_lock_irqsave(&wdata->state.lock, flags);
>> + wdata->ext = NULL;
>> + spin_unlock_irqrestore(&wdata->state.lock, flags);
>> +
>> + cancel_work_sync(&ext->worker);
>> + kfree(ext);
>> +}
>
>
> Are you sure you are doing this in the correct order?
> You are needlessly leaving a window where wdate->ext is NULL
> but the worker may run.
Thanks for reviewing.
I am only removing the wdata->ext relationship here. This is not used
by the worker at all. I never access wdata->ext in this module without
taking the spinlock and without checking it for NULL.
The worker gets "ext" directy and can still access ext->wdata even if
ext->wdata->ext is NULL. This simplifies the locking a lot.
I also know that wdata lives longer than wdata->ext so I cannot find
any race condition here. I have checked all four entry points of the
extension-module and they all seem fine here.
As long as wdata->ext is non-NULL, wiiext_schedule may be called. So I
first need to clear wdata->ext before I kill the worker. Otherwise the
worker may be respawned before I reset wdata->ext ;)
> Regards
> Oliver
Thank you
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 04/16] HID: wiimote: Add extension support stub
2011-11-14 11:26 ` David Herrmann
@ 2011-11-14 11:35 ` Oliver Neukum
2011-11-15 19:24 ` David Herrmann
0 siblings, 1 reply; 25+ messages in thread
From: Oliver Neukum @ 2011-11-14 11:35 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-input, jkosina
Am Montag, 14. November 2011, 12:26:28 schrieb David Herrmann:
> I also know that wdata lives longer than wdata->ext so I cannot find
> any race condition here. I have checked all four entry points of the
> extension-module and they all seem fine here.
>
> As long as wdata->ext is non-NULL, wiiext_schedule may be called. So I
> first need to clear wdata->ext before I kill the worker. Otherwise the
> worker may be respawned before I reset wdata->ext ;)
Hi,
thank you for the detailed explanation. Could you include a comment
to explain the unusual order things are done in this function?
Regards
Oliver
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 04/16] HID: wiimote: Add extension support stub
2011-11-14 11:35 ` Oliver Neukum
@ 2011-11-15 19:24 ` David Herrmann
0 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-15 19:24 UTC (permalink / raw)
To: Oliver Neukum; +Cc: linux-input, jkosina
On Mon, Nov 14, 2011 at 12:35 PM, Oliver Neukum <oneukum@suse.de> wrote:
> Am Montag, 14. November 2011, 12:26:28 schrieb David Herrmann:
>> I also know that wdata lives longer than wdata->ext so I cannot find
>> any race condition here. I have checked all four entry points of the
>> extension-module and they all seem fine here.
>>
>> As long as wdata->ext is non-NULL, wiiext_schedule may be called. So I
>> first need to clear wdata->ext before I kill the worker. Otherwise the
>> worker may be respawned before I reset wdata->ext ;)
>
> Hi,
>
> thank you for the detailed explanation. Could you include a comment
> to explain the unusual order things are done in this function?
Sure. I'll resend the patches in few days if nothing else comes up.
>
> Regards
> Oliver
Regards
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk
2011-11-13 13:27 ` [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk David Herrmann
@ 2011-11-16 17:05 ` Jiri Kosina
2011-11-16 17:49 ` David Herrmann
0 siblings, 1 reply; 25+ messages in thread
From: Jiri Kosina @ 2011-11-16 17:05 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-input
On Sun, 13 Nov 2011, David Herrmann wrote:
> Newer bluetooth core supports the NO_INIT_REPORTS quirk. We need this for the
> wiimote as it does not support report-initialization.
> Also bump version level as we are almost feature complete now.
>
> Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
> ---
> drivers/hid/hid-wiimote-core.c | 4 +++-
> 1 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
> index 745667e..7ea8754 100644
> --- a/drivers/hid/hid-wiimote-core.c
> +++ b/drivers/hid/hid-wiimote-core.c
> @@ -22,7 +22,7 @@
> #include "hid-ids.h"
> #include "hid-wiimote.h"
>
> -#define WIIMOTE_VERSION "0.2"
> +#define WIIMOTE_VERSION "0.3"
Do we really need this?
I generally prefer not having any file versioning for the files that are
implicitly tracked by kernel git.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk
2011-11-16 17:05 ` Jiri Kosina
@ 2011-11-16 17:49 ` David Herrmann
2011-11-16 18:39 ` Jiri Kosina
0 siblings, 1 reply; 25+ messages in thread
From: David Herrmann @ 2011-11-16 17:49 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input
On Wed, Nov 16, 2011 at 6:05 PM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Sun, 13 Nov 2011, David Herrmann wrote:
>
>> Newer bluetooth core supports the NO_INIT_REPORTS quirk. We need this for the
>> wiimote as it does not support report-initialization.
>> Also bump version level as we are almost feature complete now.
>>
>> Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
>> ---
>> drivers/hid/hid-wiimote-core.c | 4 +++-
>> 1 files changed, 3 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
>> index 745667e..7ea8754 100644
>> --- a/drivers/hid/hid-wiimote-core.c
>> +++ b/drivers/hid/hid-wiimote-core.c
>> @@ -22,7 +22,7 @@
>> #include "hid-ids.h"
>> #include "hid-wiimote.h"
>>
>> -#define WIIMOTE_VERSION "0.2"
>> +#define WIIMOTE_VERSION "0.3"
>
> Do we really need this?
>
> I generally prefer not having any file versioning for the files that are
> implicitly tracked by kernel git.
No, not at all. But I thought this was common practice. I have removed
it all together. The next series will be updated.
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs
Thanks
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk
2011-11-16 17:49 ` David Herrmann
@ 2011-11-16 18:39 ` Jiri Kosina
2011-11-17 13:11 ` David Herrmann
0 siblings, 1 reply; 25+ messages in thread
From: Jiri Kosina @ 2011-11-16 18:39 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-input
On Wed, 16 Nov 2011, David Herrmann wrote:
> >> -#define WIIMOTE_VERSION "0.2"
> >> +#define WIIMOTE_VERSION "0.3"
> >
> > Do we really need this?
> >
> > I generally prefer not having any file versioning for the files that are
> > implicitly tracked by kernel git.
>
> No, not at all. But I thought this was common practice. I have removed
> it all together. The next series will be updated.
It definitely might make sense for your internal tracking during driver
development. I just would like to have it dropped for final merge.
Otherwise, I have just finished first round of review, and overall the
driver looks fine, thanks!
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk
2011-11-16 18:39 ` Jiri Kosina
@ 2011-11-17 13:11 ` David Herrmann
0 siblings, 0 replies; 25+ messages in thread
From: David Herrmann @ 2011-11-17 13:11 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input
On Wed, Nov 16, 2011 at 7:39 PM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Wed, 16 Nov 2011, David Herrmann wrote:
>
>> >> -#define WIIMOTE_VERSION "0.2"
>> >> +#define WIIMOTE_VERSION "0.3"
>> >
>> > Do we really need this?
>> >
>> > I generally prefer not having any file versioning for the files that are
>> > implicitly tracked by kernel git.
>>
>> No, not at all. But I thought this was common practice. I have removed
>> it all together. The next series will be updated.
>
> It definitely might make sense for your internal tracking during driver
> development. I just would like to have it dropped for final merge.
>
> Otherwise, I have just finished first round of review, and overall the
> driver looks fine, thanks!
Great. I've resent the revised patches. Let me know if there are any
other issues.
> --
> Jiri Kosina
> SUSE Labs
>
Cheers
David
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2011-11-17 13:11 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-13 13:27 [PATCH 00/16] Wiimote: Extension and Debug Support David Herrmann
2011-11-13 13:27 ` [PATCH 01/16] HID: wiimote: Rename driver to allow multiple source files David Herrmann
2011-11-13 13:27 ` [PATCH 02/16] HID: wiimote: Move common symbols into header David Herrmann
2011-11-13 13:27 ` [PATCH 03/16] HID: wiimote: Add read-mem helpers David Herrmann
2011-11-13 13:27 ` [PATCH 04/16] HID: wiimote: Add extension support stub David Herrmann
2011-11-14 7:54 ` Oliver Neukum
2011-11-14 11:26 ` David Herrmann
2011-11-14 11:35 ` Oliver Neukum
2011-11-15 19:24 ` David Herrmann
2011-11-13 13:27 ` [PATCH 05/16] HID: wiimote: Add extension initializer stubs David Herrmann
2011-11-13 13:27 ` [PATCH 06/16] HID: wiimote: Add extension initializers David Herrmann
2011-11-13 13:27 ` [PATCH 07/16] HID: wiimote: Add extension sysfs attribute David Herrmann
2011-11-13 13:27 ` [PATCH 08/16] HID: wiimote: Register input devices for extensions David Herrmann
2011-11-13 13:27 ` [PATCH 09/16] HID: wiimote: Add extension handler stubs David Herrmann
2011-11-13 13:27 ` [PATCH 10/16] HID: wiimote: Parse motion+ data David Herrmann
2011-11-13 13:27 ` [PATCH 11/16] HID: wiimote: Parse nunchuck data David Herrmann
2011-11-13 13:27 ` [PATCH 12/16] HID: wiimote: Parse classic controller data David Herrmann
2011-11-13 13:27 ` [PATCH 13/16] HID: wiimote: Add debugfs support stubs David Herrmann
2011-11-13 13:27 ` [PATCH 14/16] HID: wiimote: Allow direct eeprom access David Herrmann
2011-11-13 13:27 ` [PATCH 15/16] HID: wiimote: Allow direct DRM debug access David Herrmann
2011-11-13 13:27 ` [PATCH 16/16] HID: wiimote: Enable NO_INIT_REPORTS quirk David Herrmann
2011-11-16 17:05 ` Jiri Kosina
2011-11-16 17:49 ` David Herrmann
2011-11-16 18:39 ` Jiri Kosina
2011-11-17 13:11 ` David Herrmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).