* [PATCH 02/13] Input: introduce ABS_MAX2/CNT2 and friends
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
As we painfully noticed during the 3.12 merge-window our
EVIOCGABS/EVIOCSABS API is limited to ABS_MAX<=0x3f. We tried several
hacks to work around it but if we ever decide to increase ABS_MAX, the
EVIOCSABS ioctl ABI might overflow into the next byte causing horrible
misinterpretations in the kernel that we cannot catch.
Therefore, we decided to go with ABS_MAX2/CNT2 and introduce two new
ioctls to get/set abs-params. They no longer encode the ABS code in the
ioctl number and thus allow up to 4 billion ABS codes.
The new API also allows to query multiple ABS values with one call. To
allow EVIOCSABS2(code = 0, cnt = ABS_CNT2) we need to silently ignore
writes to ABS_MT_SLOT. Other than that, semantics are the same as for the
legacy API.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-debug.c | 2 +-
drivers/hid/hid-input.c | 2 +-
drivers/input/evdev.c | 88 +++++++++++++++++++++++++++++++-
drivers/input/input.c | 14 ++---
drivers/input/keyboard/goldfish_events.c | 6 +--
drivers/input/keyboard/hil_kbd.c | 2 +-
drivers/input/misc/uinput.c | 6 +--
include/linux/hid.h | 2 +-
include/linux/input.h | 6 +--
include/uapi/linux/input.h | 37 +++++++++++++-
include/uapi/linux/uinput.h | 2 +-
11 files changed, 144 insertions(+), 23 deletions(-)
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 8453214..d32fa30 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -862,7 +862,7 @@ static const char *relatives[REL_MAX + 1] = {
[REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
};
-static const char *absolutes[ABS_CNT] = {
+static const char *absolutes[ABS_CNT2] = {
[ABS_X] = "X", [ABS_Y] = "Y",
[ABS_Z] = "Z", [ABS_RX] = "Rx",
[ABS_RY] = "Ry", [ABS_RZ] = "Rz",
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d97f232..a02721c 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1300,7 +1300,7 @@ static bool hidinput_has_been_populated(struct hid_input *hidinput)
for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
r |= hidinput->input->relbit[i];
- for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
+ for (i = 0; i < BITS_TO_LONGS(ABS_CNT2); i++)
r |= hidinput->input->absbit[i];
for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b6ded17..ffe65fd 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -635,7 +635,7 @@ static int handle_eviocgbit(struct input_dev *dev,
case 0: bits = dev->evbit; len = EV_MAX; break;
case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
case EV_REL: bits = dev->relbit; len = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
+ case EV_ABS: bits = dev->absbit; len = ABS_MAX2; break;
case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
@@ -663,6 +663,86 @@ static int handle_eviocgbit(struct input_dev *dev,
}
#undef OLD_KEY_MAX
+static int evdev_handle_get_abs2(struct input_dev *dev, void __user *p)
+{
+ u32 code, cnt, i;
+ struct input_absinfo2 __user *pinfo = p;
+ struct input_absinfo abs;
+
+ if (!dev->absinfo)
+ return -EINVAL;
+
+ if (copy_from_user(&code, &pinfo->code, sizeof(code)))
+ return -EFAULT;
+ if (copy_from_user(&cnt, &pinfo->cnt, sizeof(cnt)))
+ return -EFAULT;
+
+ if (!cnt || code > ABS_MAX2 || cnt > ABS_CNT2)
+ return -EINVAL;
+ if (code + cnt > ABS_MAX2)
+ return -EINVAL;
+
+ for (i = 0; i < cnt; ++i) {
+ /*
+ * Take event lock to ensure that we are not
+ * copying data while EVIOCSABS2 changes it.
+ * Might be inconsistent, otherwise.
+ */
+ spin_lock_irq(&dev->event_lock);
+ abs = dev->absinfo[code + i];
+ spin_unlock_irq(&dev->event_lock);
+
+ if (copy_to_user(&pinfo->info[i], &abs, sizeof(abs)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int evdev_handle_set_abs2(struct input_dev *dev, void __user *p)
+{
+ struct input_absinfo2 __user *pinfo = p;
+ struct input_absinfo *abs;
+ u32 code, cnt, i;
+ size_t size;
+
+ if (!dev->absinfo)
+ return -EINVAL;
+
+ if (copy_from_user(&code, &pinfo->code, sizeof(code)))
+ return -EFAULT;
+ if (copy_from_user(&cnt, &pinfo->cnt, sizeof(cnt)))
+ return -EFAULT;
+
+ if (!cnt || code > ABS_MAX2 || cnt > ABS_CNT2)
+ return -EINVAL;
+ if (code + cnt > ABS_MAX2)
+ return -EINVAL;
+
+ size = cnt * sizeof(*abs);
+ abs = memdup_user(&pinfo->info[0], size);
+ if (IS_ERR(abs))
+ return PTR_ERR(abs);
+
+ /*
+ * Take event lock to ensure that we are not
+ * changing device parameters in the middle
+ * of event.
+ */
+ spin_lock_irq(&dev->event_lock);
+ for (i = 0; i < cnt; ++i) {
+ /* silently drop ABS_MT_SLOT */
+ if (code + i == ABS_MT_SLOT)
+ continue;
+
+ dev->absinfo[code + i] = abs[i];
+ }
+ spin_unlock_irq(&dev->event_lock);
+
+ kfree(abs);
+ return 0;
+}
+
static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
{
struct input_keymap_entry ke = {
@@ -890,6 +970,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
client->clkid = i;
return 0;
+ case EVIOCGABS2:
+ return evdev_handle_get_abs2(dev, p);
+
+ case EVIOCSABS2:
+ return evdev_handle_set_abs2(dev, p);
+
case EVIOCGKEYCODE:
return evdev_handle_get_keycode(dev, p);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c044699..bc88f17 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -305,7 +305,7 @@ static int input_get_disposition(struct input_dev *dev,
break;
case EV_ABS:
- if (is_event_supported(code, dev->absbit, ABS_MAX))
+ if (is_event_supported(code, dev->absbit, ABS_MAX2))
disposition = input_handle_abs_event(dev, code, &value);
break;
@@ -474,7 +474,7 @@ EXPORT_SYMBOL(input_inject_event);
void input_alloc_absinfo(struct input_dev *dev)
{
if (!dev->absinfo)
- dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
+ dev->absinfo = kcalloc(ABS_CNT2, sizeof(struct input_absinfo),
GFP_KERNEL);
WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
@@ -954,7 +954,7 @@ static const struct input_device_id *input_match_device(struct input_handler *ha
if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
continue;
- if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
+ if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX2))
continue;
if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
@@ -1147,7 +1147,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
if (test_bit(EV_REL, dev->evbit))
input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
if (test_bit(EV_ABS, dev->evbit))
- input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
+ input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX2);
if (test_bit(EV_MSC, dev->evbit))
input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
if (test_bit(EV_LED, dev->evbit))
@@ -1333,7 +1333,7 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
len += input_print_modalias_bits(buf + len, size - len,
'r', id->relbit, 0, REL_MAX);
len += input_print_modalias_bits(buf + len, size - len,
- 'a', id->absbit, 0, ABS_MAX);
+ 'a', id->absbit, 0, ABS_MAX2);
len += input_print_modalias_bits(buf + len, size - len,
'm', id->mscbit, 0, MSC_MAX);
len += input_print_modalias_bits(buf + len, size - len,
@@ -1592,7 +1592,7 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
if (test_bit(EV_REL, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
if (test_bit(EV_ABS, dev->evbit))
- INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
+ INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX2);
if (test_bit(EV_MSC, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
if (test_bit(EV_LED, dev->evbit))
@@ -1924,7 +1924,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */
- for (i = 0; i < ABS_CNT; i++) {
+ for (i = 0; i < ABS_CNT2; i++) {
if (test_bit(i, dev->absbit)) {
if (input_is_mt_axis(i))
events += mt_slots;
diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c
index 9f60a2e..9999cea 100644
--- a/drivers/input/keyboard/goldfish_events.c
+++ b/drivers/input/keyboard/goldfish_events.c
@@ -90,8 +90,8 @@ static void events_import_abs_params(struct event_dev *edev)
__raw_writel(PAGE_ABSDATA, addr + REG_SET_PAGE);
count = __raw_readl(addr + REG_LEN) / sizeof(val);
- if (count > ABS_MAX)
- count = ABS_MAX;
+ if (count > ABS_MAX2)
+ count = ABS_MAX2;
for (i = 0; i < count; i++) {
if (!test_bit(i, input_dev->absbit))
@@ -158,7 +158,7 @@ static int events_probe(struct platform_device *pdev)
events_import_bits(edev, input_dev->evbit, EV_SYN, EV_MAX);
events_import_bits(edev, input_dev->keybit, EV_KEY, KEY_MAX);
events_import_bits(edev, input_dev->relbit, EV_REL, REL_MAX);
- events_import_bits(edev, input_dev->absbit, EV_ABS, ABS_MAX);
+ events_import_bits(edev, input_dev->absbit, EV_ABS, ABS_MAX2);
events_import_bits(edev, input_dev->mscbit, EV_MSC, MSC_MAX);
events_import_bits(edev, input_dev->ledbit, EV_LED, LED_MAX);
events_import_bits(edev, input_dev->sndbit, EV_SND, SND_MAX);
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 589e3c2..4e4e010 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -387,7 +387,7 @@ static void hil_dev_pointer_setup(struct hil_dev *ptr)
0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0);
#ifdef TABLET_AUTOADJUST
- for (i = 0; i < ABS_MAX; i++) {
+ for (i = 0; i < ABS_MAX2; i++) {
int diff = input_abs_get_max(input_dev, ABS_X + i) / 10;
input_abs_set_min(input_dev, ABS_X + i,
input_abs_get_min(input_dev, ABS_X + i) + diff);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 3cd84d2..2f7355e 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -311,7 +311,7 @@ static int uinput_validate_absbits(struct input_dev *dev)
unsigned int cnt;
int retval = 0;
- for (cnt = 0; cnt < ABS_CNT; cnt++) {
+ for (cnt = 0; cnt < ABS_CNT2; cnt++) {
int min, max;
if (!test_bit(cnt, dev->absbit))
continue;
@@ -474,7 +474,7 @@ static int uinput_setup_device2(struct uinput_device *udev,
return -EINVAL;
/* rough check to avoid huge kernel space allocations */
- max = ABS_CNT * sizeof(*user_dev2->abs) + sizeof(*user_dev2);
+ max = ABS_CNT2 * sizeof(*user_dev2->abs) + sizeof(*user_dev2);
if (count > max)
return -EINVAL;
@@ -770,7 +770,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
break;
case UI_SET_ABSBIT:
- retval = uinput_set_bit(arg, absbit, ABS_MAX);
+ retval = uinput_set_bit(arg, absbit, ABS_MAX2);
break;
case UI_SET_MSCBIT:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 31b9d29..c21d8bb 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -828,7 +828,7 @@ static inline void hid_map_usage(struct hid_input *hidinput,
switch (type) {
case EV_ABS:
*bit = input->absbit;
- *max = ABS_MAX;
+ *max = ABS_MAX2;
break;
case EV_REL:
*bit = input->relbit;
diff --git a/include/linux/input.h b/include/linux/input.h
index 82ce323..c6add6f 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -129,7 +129,7 @@ struct input_dev {
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
- unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
+ unsigned long absbit[BITS_TO_LONGS(ABS_CNT2)];
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
@@ -210,8 +210,8 @@ struct input_dev {
#error "REL_MAX and INPUT_DEVICE_ID_REL_MAX do not match"
#endif
-#if ABS_MAX != INPUT_DEVICE_ID_ABS_MAX
-#error "ABS_MAX and INPUT_DEVICE_ID_ABS_MAX do not match"
+#if ABS_MAX2 != INPUT_DEVICE_ID_ABS_MAX
+#error "ABS_MAX2 and INPUT_DEVICE_ID_ABS_MAX do not match"
#endif
#if MSC_MAX != INPUT_DEVICE_ID_MSC_MAX
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index a372627..9e525f9 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -74,6 +74,27 @@ struct input_absinfo {
};
/**
+ * struct input_absinfo2 - used by EVIOC[G/S]ABS2 ioctls
+ * @code: First ABS code to query
+ * @cnt: Number of ABS codes to query starting at @code
+ * @info: #@cnt absinfo structures to get/set abs parameters for all codes
+ *
+ * This structure is used by the new EVIOC[G/S]ABS2 ioctls which
+ * do the same as the old EVIOC[G/S]ABS ioctls but avoid encoding
+ * the ABS code in the ioctl number. This allows a much wider
+ * range of ABS codes. Furthermore, it allows to query multiple codes with a
+ * single call.
+ *
+ * Note that this silently drops any requests to set ABS_MT_SLOT. Hence, it is
+ * allowed to call this with code=0 cnt=ABS_CNT2.
+ */
+struct input_absinfo2 {
+ __u32 code;
+ __u32 cnt;
+ struct input_absinfo info[1];
+};
+
+/**
* struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
* @scancode: scancode represented in machine-endian form.
* @len: length of the scancode that resides in @scancode buffer.
@@ -153,6 +174,8 @@ struct input_keymap_entry {
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
#define EVIOCREVOKE _IOW('E', 0x91, int) /* Revoke device access */
+#define EVIOCGABS2 _IOR('E', 0x92, struct input_absinfo2) /* get abs value/limits */
+#define EVIOCSABS2 _IOW('E', 0x93, struct input_absinfo2) /* set abs value/limits */
#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
@@ -832,11 +855,23 @@ struct input_keymap_entry {
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
-
+/*
+ * ABS_MAX/CNT is limited to a maximum of 0x3f due to the design of EVIOCGABS
+ * and EVIOCSABS ioctls. Other kernel APIs like uinput also hardcoded it. Do
+ * not modify this value and instead use the extended ABS_MAX2/CNT2 API.
+ */
#define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1)
/*
+ * Due to API restrictions the legacy evdev API only supports ABS values up to
+ * ABS_MAX/CNT. Use the extended *ABS2 ioctls to operate on any ABS values in
+ * between ABS_MAX and ABS_MAX2.
+ */
+#define ABS_MAX2 0x3f
+#define ABS_CNT2 (ABS_MAX2+1)
+
+/*
* Switch events
*/
diff --git a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h
index c2e8710..27ee521 100644
--- a/include/uapi/linux/uinput.h
+++ b/include/uapi/linux/uinput.h
@@ -140,7 +140,7 @@ struct uinput_user_dev2 {
char name[UINPUT_MAX_NAME_SIZE];
struct input_id id;
__u32 ff_effects_max;
- struct input_absinfo abs[ABS_CNT];
+ struct input_absinfo abs[ABS_CNT2];
};
#endif /* _UAPI__UINPUT_H_ */
--
1.8.4.1
^ permalink raw reply related
* [PATCH 03/13] Input: remove ambigious gamepad comment
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
If only a single trigger combination is present on a device, either can be
reported. If the side of the trigger (left/right) cannot be decided (eg.,
if it's centered), then choose any side. User-space automatically notices
that only a single trigger is reported and thus doesn't care how it is
reported.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
Documentation/input/gamepad.txt | 2 --
1 file changed, 2 deletions(-)
diff --git a/Documentation/input/gamepad.txt b/Documentation/input/gamepad.txt
index 8002c89..c40b109 100644
--- a/Documentation/input/gamepad.txt
+++ b/Documentation/input/gamepad.txt
@@ -136,8 +136,6 @@ Triggers:
Upper trigger buttons are reported as BTN_TR or ABS_HAT1X (right) and BTN_TL
or ABS_HAT1Y (left). Lower trigger buttons are reported as BTN_TR2 or
ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL).
- If only one trigger-button combination is present (upper+lower), they are
- reported as "right" triggers (BTN_TR/ABS_HAT1X).
Menu-Pad:
Menu buttons are always digital and are mapped according to their location
--
1.8.4.1
^ permalink raw reply related
* [PATCH 04/13] Input: add motion-tracking ABS_* bits and docs
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
Motion sensors are getting quite common in mobile devices. To avoid
returning accelerometer data via ABS_X/Y/Z and irritating the Xorg
mouse-driver, this adds separate ABS_* bits for that.
This is needed if gaming devices want to report their normal data plus
accelerometer/gyro data. Usually, ABS_X/Y are already used by analog
sticks, so need separate definitions, anyway.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
Documentation/input/gamepad.txt | 7 ++
Documentation/input/motion-tracking.txt | 149 ++++++++++++++++++++++++++++++++
include/linux/mod_devicetable.h | 2 +-
include/uapi/linux/input.h | 9 +-
4 files changed, 165 insertions(+), 2 deletions(-)
create mode 100644 Documentation/input/motion-tracking.txt
diff --git a/Documentation/input/gamepad.txt b/Documentation/input/gamepad.txt
index c40b109..bd168c0 100644
--- a/Documentation/input/gamepad.txt
+++ b/Documentation/input/gamepad.txt
@@ -57,6 +57,9 @@ Most gamepads have the following features:
- Rumble
Many devices provide force-feedback features. But are mostly just
simple rumble motors.
+ - Motion-tracking
+ Gamepads may include motion-tracking sensors like accelerometers and
+ gyroscopes.
3. Detection
~~~~~~~~~~~~
@@ -150,5 +153,9 @@ Menu-Pad:
Rumble:
Rumble is adverticed as FF_RUMBLE.
+Motion-tracking:
+ Motion-tracking is defined in ./Documentation/input/motion-tracking.txt and
+ gamepads shall comply to the rules defined there.
+
----------------------------------------------------------------------------
Written 2013 by David Herrmann <dh.herrmann@gmail.com>
diff --git a/Documentation/input/motion-tracking.txt b/Documentation/input/motion-tracking.txt
new file mode 100644
index 0000000..0885c9a
--- /dev/null
+++ b/Documentation/input/motion-tracking.txt
@@ -0,0 +1,149 @@
+ Motion Tracking API
+----------------------------------------------------------------------------
+
+1. Intro
+~~~~~~~~
+Motion tracking devices produce device motion events generated from an
+accelerometer, gyroscope or compass. This data can be returned to user-space
+via input events. This document defines how this data is reported.
+
+2. Devices
+~~~~~~~~~~
+In this document, a "device" is one of:
+ - accelerometer
+ - gyroscope
+ - compass
+
+These devices returned their information via different APIs in the past. To
+unify them and define a common API, a set of input evdev codes was created. Old
+drivers might continue using their API, but developers are encouraged to use
+the input evdev API for new drivers.
+
+2.1 Axes
+~~~~~~~~
+Movement data is usually returned as absolute data for the 3 axes of a device.
+In this context, the three axes are defined as:
+ - X: Axis goes from the left to the right side of the device
+ - Y: Axis goes from the bottom to the top of the device
+ - Z: Axis goes from the back to the front of the device
+
+The front of a device is the side faced to the user. For a mobile-phone it
+would be the screen. For devices without a screen, the front is usually the
+side with the most buttons on it.
+
+ Example: Mobile-Phone
+ +-------------------------------------------------------------------------+
+ | TOP |
+ | |
+ | |
+ | +---------------------------+ |
+ | |\ ________________________ \ .__ |
+ | \ \ \ \ \ |\ |
+ | \ \ \ __ \ \ \ RIGHT|
+ | \ \ \ /| \ \ \__ |
+ | \ \ \ __/ \ \ |\ |
+ | \ \ \ /| \ \ \ (Y Axis) |
+ | \ \ \ __/ (Z axis) \ \ \__ |
+ | \ \ \ /| \ \ |\ |
+ | LEFT \ \ \ / \ \ \ |
+ | \ \ \ FRONT \ \ \ |
+ | \ \ \ \ \ |
+ | \ \ \_______________________\ \ |
+ | \ \ ___ \ |
+ | /\ \ \__\ \ |
+ | __/ \ +---------------------------+ |
+ | /| \|___________________________| |
+ | / BACK |
+ | (X axis) |
+ | ------->------->------->-------> |
+ | |
+ | |
+ | BOTTOM |
+ +-------------------------------------------------------------------------+
+
+Rotation-data is reported as clock-wise rotation on an axis. For a given axes,
+the reported rotation would be:
+ ___
+ /|
+ / | (axis)
+ /
+ .-**-.
+ / / \
+ | / \ | /
+ \ / \|/ (clock-wise rotation)
+ /
+ /
+ /
+
+2.2 Calibration
+~~~~~~~~~~~~~~~
+Motion sensors are often highly sensitive and need precise calibration. Users
+are adviced to perform neutral-point calibration themselves or to implement a
+state-machine to normalize input data automatically.
+
+Kernel devices may perform their own calibration and/or normalization. However,
+this is usually sparse and, if implemented, transparent to the user.
+
+There is currently no way to feed calibration data into the kernel in a generic
+way. Proposals welcome!
+
+2.3 Units
+~~~~~~~~~
+(NOTE: This section describes an experimental API. Currently, no device complies
+to these rules so this might change in the future.)
+
+Reported data shall be returned as:
+ - Acceleration: 1/1000 m per s^2
+ - Rotation: 1/1000 degree per second
+
+However, for most devices the reported units are unknown (more precisely: no
+one has the time to measure them and figure them out). Therefore, user-space
+shall use abs-minimum and abs-maximum to calculate relative data and use that
+instead. Devices which return wrong units may be fixed in the future to comply
+to these rules.
+
+3.1 Accelerometer
+~~~~~~~~~~~~~~~~~
+Accelerometers measure movement acceleration of devices. Any combination of the
+three available axes can be used. Usually, all three are supported.
+
+Data is provided as absolute acceleration. A positive integer defines the
+acceleration in the direction of an axis. A negative integer defines
+acceleration in the opposite direction.
+
+The evdev ABS codes used are:
+ - ABS_ACCEL_X: X axis
+ - ABS_ACCEL_Y: Y axis
+ - ABS_ACCEL_Z: Z axis
+
+3.2 Gyroscope
+~~~~~~~~~~~~~
+A gyroscope measures rotational speed (*not* acceleration!). Any combination of
+the three available axes can be used. Usually, all three are supported.
+
+Data is provided as absolute speed. A positive integer defines the rotational
+speed in clock-wise order around a given axis. A negative integer defines it in
+counter-clock-wise order.
+
+The evdev ABS codes used are:
+ - ABS_GYRO_X: X axis (also: Pitch)
+ - ABS_GYRO_Y: Y axis (also: Roll)
+ - ABS_GYRO_Z: Z axis (also: Azimuth/Yaw)
+
+3.3 Compass
+~~~~~~~~~~~
+(NOTE: No compass device currently uses the evdev input subsystem. Thus, this
+API is only a proposal, it hasn't been implemented, yet.)
+
+A compass measures the ambient magnetic field of the three defined axes. This
+makes the data self-contained and independent of the current device position.
+Any combination of the three axes can be used. Usually all three are supported,
+otherwise, it's not really useful as a compass.
+
+Proposed evdev ABS codes are:
+ - ABS_COMPASS_X: X axis
+ - ABS_COMPASS_Y: Y axis
+ - ABS_COMPASS_Z: Z axis
+
+----------------------------------------------------------------------------
+ Written 2013 by David Herrmann <dh.herrmann@gmail.com>
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 45e9214..329aa30 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -277,7 +277,7 @@ struct pcmcia_device_id {
#define INPUT_DEVICE_ID_KEY_MIN_INTERESTING 0x71
#define INPUT_DEVICE_ID_KEY_MAX 0x2ff
#define INPUT_DEVICE_ID_REL_MAX 0x0f
-#define INPUT_DEVICE_ID_ABS_MAX 0x3f
+#define INPUT_DEVICE_ID_ABS_MAX 0x4f
#define INPUT_DEVICE_ID_MSC_MAX 0x07
#define INPUT_DEVICE_ID_LED_MAX 0x0f
#define INPUT_DEVICE_ID_SND_MAX 0x07
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 9e525f9..f347498 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -863,12 +863,19 @@ struct input_keymap_entry {
#define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1)
+#define ABS_ACCEL_X 0x40 /* Accelerometer X axis */
+#define ABS_ACCEL_Y 0x41 /* Accelerometer Y axis */
+#define ABS_ACCEL_Z 0x42 /* Accelerometer Z axis */
+#define ABS_GYRO_X 0x43 /* Gyroscope X axis */
+#define ABS_GYRO_Y 0x44 /* Gyroscope Y axis */
+#define ABS_GYRO_Z 0x45 /* Gyroscope Z axis */
+
/*
* Due to API restrictions the legacy evdev API only supports ABS values up to
* ABS_MAX/CNT. Use the extended *ABS2 ioctls to operate on any ABS values in
* between ABS_MAX and ABS_MAX2.
*/
-#define ABS_MAX2 0x3f
+#define ABS_MAX2 0x4f
#define ABS_CNT2 (ABS_MAX2+1)
/*
--
1.8.4.1
^ permalink raw reply related
* [PATCH 05/13] HID: wiimote: add hid_wiimote.legacy parameter
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
The first hid-wiimote driver had horrible default mappings which we have
to support now for compatibility reasons. This was no big problem as the
wiimote needs special user-space drivers to really make sense, anyway.
However, there are several wiimote extensions which can be used on their
own (especially the gamepads). To allow new mappings which comply to the
common gamepad rules, we introduce the hid_wiimote.legacy parameter so
users can get the old behavior back, if they need it.
This patch only introduces the module parameter, the following patches
will change the mappings.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-core.c | 9 +++++++++
drivers/hid/hid-wiimote.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 1446f52..89ca031 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -20,6 +20,9 @@
#include "hid-ids.h"
#include "hid-wiimote.h"
+/* set to 1 to enable legacy-mode and old reports */
+static unsigned int wiimote_legacy = 0;
+
/* output queue handling */
static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
@@ -1731,6 +1734,9 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
wdata->hdev = hdev;
hid_set_drvdata(hdev, wdata);
+ if (wiimote_legacy)
+ wdata->state.flags |= WIIPROTO_FLAG_LEGACY;
+
spin_lock_init(&wdata->queue.lock);
INIT_WORK(&wdata->queue.worker, wiimote_queue_worker);
@@ -1873,6 +1879,9 @@ static struct hid_driver wiimote_hid_driver = {
};
module_hid_driver(wiimote_hid_driver);
+MODULE_PARM_DESC(legacy, "Enable legacy mode and reports");
+module_param_named(legacy, wiimote_legacy, int, 0600);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
MODULE_DESCRIPTION("Driver for Nintendo Wii / Wii U peripherals");
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 03065f1..6f70823 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -47,6 +47,7 @@
#define WIIPROTO_FLAG_BUILTIN_MP 0x010000
#define WIIPROTO_FLAG_NO_MP 0x020000
#define WIIPROTO_FLAG_PRO_CALIB_DONE 0x040000
+#define WIIPROTO_FLAG_LEGACY 0x080000
#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
--
1.8.4.1
^ permalink raw reply related
* [PATCH 06/13] HID: wiimote: adjust button-mapping to gamepad rules
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
Our gamepad API (./Documentation/input/gamepad.txt) clearly defines rules
how to map buttons for gamepads. A wiimote can easily be used as gamepad
and provides most of the features. Unfortunately, the gamepad API didn't
exist when hid-wiimote was written.
This patch changes the button-mappings to comply to gamepad rules. For
compatibility reasons, we keep the old mappings if legacy-mode was
enabled.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-modules.c | 49 ++++++++++++++++++++++++++++-----------
1 file changed, 36 insertions(+), 13 deletions(-)
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 6b61f01..372fec1 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -48,7 +48,7 @@
* It uses the shared input device.
*/
-static const __u16 wiimod_keys_map[] = {
+static const __u16 wiimod_keys_map_legacy[] = {
KEY_LEFT, /* WIIPROTO_KEY_LEFT */
KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */
KEY_UP, /* WIIPROTO_KEY_UP */
@@ -62,29 +62,48 @@ static const __u16 wiimod_keys_map[] = {
BTN_MODE, /* WIIPROTO_KEY_HOME */
};
+static const __u16 wiimod_keys_map[] = {
+ BTN_DPAD_LEFT, /* WIIPROTO_KEY_LEFT */
+ BTN_DPAD_RIGHT, /* WIIPROTO_KEY_RIGHT */
+ BTN_DPAD_UP, /* WIIPROTO_KEY_UP */
+ BTN_DPAD_DOWN, /* WIIPROTO_KEY_DOWN */
+ BTN_START, /* WIIPROTO_KEY_PLUS */
+ BTN_SELECT, /* WIIPROTO_KEY_MINUS */
+ BTN_TRIGGER_HAPPY1, /* WIIPROTO_KEY_ONE */
+ BTN_TRIGGER_HAPPY2, /* WIIPROTO_KEY_TWO */
+ BTN_SOUTH, /* WIIPROTO_KEY_A */
+ BTN_TR, /* WIIPROTO_KEY_B */
+ BTN_MODE, /* WIIPROTO_KEY_HOME */
+};
+
static void wiimod_keys_in_keys(struct wiimote_data *wdata, const __u8 *keys)
{
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_LEFT],
+ const __u16 *map = wiimod_keys_map;
+
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY)
+ map = wiimod_keys_map_legacy;
+
+ input_report_key(wdata->input, map[WIIPROTO_KEY_LEFT],
!!(keys[0] & 0x01));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_RIGHT],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_RIGHT],
!!(keys[0] & 0x02));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_DOWN],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_DOWN],
!!(keys[0] & 0x04));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_UP],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_UP],
!!(keys[0] & 0x08));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_PLUS],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_PLUS],
!!(keys[0] & 0x10));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_TWO],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_TWO],
!!(keys[1] & 0x01));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_ONE],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_ONE],
!!(keys[1] & 0x02));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_B],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_B],
!!(keys[1] & 0x04));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_A],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_A],
!!(keys[1] & 0x08));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_MINUS],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_MINUS],
!!(keys[1] & 0x10));
- input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_HOME],
+ input_report_key(wdata->input, map[WIIPROTO_KEY_HOME],
!!(keys[1] & 0x80));
input_sync(wdata->input);
}
@@ -92,11 +111,15 @@ static void wiimod_keys_in_keys(struct wiimote_data *wdata, const __u8 *keys)
static int wiimod_keys_probe(const struct wiimod_ops *ops,
struct wiimote_data *wdata)
{
+ const __u16 *map = wiimod_keys_map;
unsigned int i;
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY)
+ map = wiimod_keys_map_legacy;
+
set_bit(EV_KEY, wdata->input->evbit);
for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
- set_bit(wiimod_keys_map[i], wdata->input->keybit);
+ set_bit(map[i], wdata->input->keybit);
return 0;
}
--
1.8.4.1
^ permalink raw reply related
* [PATCH 07/13] HID: wiimote: map nunchuk as real gamepad
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
The nunchuk device can easily be used as reduced gamepad. Add a new
mapping according to linux gamepad rules.
Note that we map it as gamepad with:
- one analog-stick (left)
- two trigger buttons (left upper+lower)
- accelerometer
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-modules.c | 94 ++++++++++++++++++++++++++++-----------
1 file changed, 67 insertions(+), 27 deletions(-)
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 372fec1..a02059c 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -839,15 +839,24 @@ enum wiimod_nunchuk_keys {
WIIMOD_NUNCHUK_KEY_NUM,
};
-static const __u16 wiimod_nunchuk_map[] = {
+static const __u16 wiimod_nunchuk_map_legacy[] = {
BTN_C, /* WIIMOD_NUNCHUK_KEY_C */
BTN_Z, /* WIIMOD_NUNCHUK_KEY_Z */
};
+static const __u16 wiimod_nunchuk_map[] = {
+ BTN_TL, /* WIIMOD_NUNCHUK_KEY_C */
+ BTN_TL2, /* WIIMOD_NUNCHUK_KEY_Z */
+};
+
static void wiimod_nunchuk_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{
+ const __u16 *map = wiimod_nunchuk_map;
__s16 x, y, z, bx, by;
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY)
+ map = wiimod_nunchuk_map_legacy;
+
/* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 |
* -----+----------+---------+---------+----+-----+
* 1 | Button X <7:0> |
@@ -902,26 +911,35 @@ static void wiimod_nunchuk_in_ext(struct wiimote_data *wdata, const __u8 *ext)
y -= 0x200;
z -= 0x200;
- input_report_abs(wdata->extension.input, ABS_HAT0X, bx);
- input_report_abs(wdata->extension.input, ABS_HAT0Y, by);
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ input_report_abs(wdata->extension.input, ABS_HAT0X, bx);
+ input_report_abs(wdata->extension.input, ABS_HAT0Y, by);
- input_report_abs(wdata->extension.input, ABS_RX, x);
- input_report_abs(wdata->extension.input, ABS_RY, y);
- input_report_abs(wdata->extension.input, ABS_RZ, z);
+ input_report_abs(wdata->extension.input, ABS_RX, x);
+ input_report_abs(wdata->extension.input, ABS_RY, y);
+ input_report_abs(wdata->extension.input, ABS_RZ, z);
+ } else {
+ input_report_abs(wdata->extension.input, ABS_X, bx);
+ input_report_abs(wdata->extension.input, ABS_Y, -by);
+
+ input_report_abs(wdata->extension.input, ABS_ACCEL_X, x);
+ input_report_abs(wdata->extension.input, ABS_ACCEL_Y, y);
+ input_report_abs(wdata->extension.input, ABS_ACCEL_Z, z);
+ }
if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
input_report_key(wdata->extension.input,
- wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_Z],
+ map[WIIMOD_NUNCHUK_KEY_Z],
!(ext[5] & 0x04));
input_report_key(wdata->extension.input,
- wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_C],
+ map[WIIMOD_NUNCHUK_KEY_C],
!(ext[5] & 0x08));
} else {
input_report_key(wdata->extension.input,
- wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_Z],
+ map[WIIMOD_NUNCHUK_KEY_Z],
!(ext[5] & 0x01));
input_report_key(wdata->extension.input,
- wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_C],
+ map[WIIMOD_NUNCHUK_KEY_C],
!(ext[5] & 0x02));
}
@@ -955,12 +973,16 @@ static void wiimod_nunchuk_close(struct input_dev *dev)
static int wiimod_nunchuk_probe(const struct wiimod_ops *ops,
struct wiimote_data *wdata)
{
+ const __u16 *map = wiimod_nunchuk_map;
int ret, i;
wdata->extension.input = input_allocate_device();
if (!wdata->extension.input)
return -ENOMEM;
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY)
+ map = wiimod_nunchuk_map_legacy;
+
input_set_drvdata(wdata->extension.input, wdata);
wdata->extension.input->open = wiimod_nunchuk_open;
wdata->extension.input->close = wiimod_nunchuk_close;
@@ -973,25 +995,43 @@ static int wiimod_nunchuk_probe(const struct wiimod_ops *ops,
set_bit(EV_KEY, wdata->extension.input->evbit);
for (i = 0; i < WIIMOD_NUNCHUK_KEY_NUM; ++i)
- set_bit(wiimod_nunchuk_map[i],
- wdata->extension.input->keybit);
+ set_bit(map[i], wdata->extension.input->keybit);
set_bit(EV_ABS, wdata->extension.input->evbit);
- set_bit(ABS_HAT0X, wdata->extension.input->absbit);
- set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT0X, -120, 120, 2, 4);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT0Y, -120, 120, 2, 4);
- set_bit(ABS_RX, wdata->extension.input->absbit);
- set_bit(ABS_RY, wdata->extension.input->absbit);
- set_bit(ABS_RZ, wdata->extension.input->absbit);
- input_set_abs_params(wdata->extension.input,
- ABS_RX, -500, 500, 2, 4);
- input_set_abs_params(wdata->extension.input,
- ABS_RY, -500, 500, 2, 4);
- input_set_abs_params(wdata->extension.input,
- ABS_RZ, -500, 500, 2, 4);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT0X, -120, 120, 2, 4);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT0Y, -120, 120, 2, 4);
+ set_bit(ABS_RX, wdata->extension.input->absbit);
+ set_bit(ABS_RY, wdata->extension.input->absbit);
+ set_bit(ABS_RZ, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_RX, -500, 500, 2, 4);
+ input_set_abs_params(wdata->extension.input,
+ ABS_RY, -500, 500, 2, 4);
+ input_set_abs_params(wdata->extension.input,
+ ABS_RZ, -500, 500, 2, 4);
+ } else {
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, -120, 120, 2, 4);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, -120, 120, 2, 4);
+ set_bit(ABS_ACCEL_X, wdata->extension.input->absbit);
+ set_bit(ABS_ACCEL_Y, wdata->extension.input->absbit);
+ set_bit(ABS_ACCEL_Z, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_ACCEL_X, -500, 500, 2, 4);
+ input_set_abs_params(wdata->extension.input,
+ ABS_ACCEL_Y, -500, 500, 2, 4);
+ input_set_abs_params(wdata->extension.input,
+ ABS_ACCEL_Z, -500, 500, 2, 4);
+ }
ret = input_register_device(wdata->extension.input);
if (ret)
--
1.8.4.1
^ permalink raw reply related
* [PATCH 08/13] HID: wiimote: map classic controller as gamepad
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
Adjust the mappings for the classic-controller extension so it's reported
as normal gamepad. Keep the compatibility mappings so legacy-mode still
works.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-modules.c | 144 ++++++++++++++++++++++++++------------
1 file changed, 100 insertions(+), 44 deletions(-)
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index a02059c..f3de94e 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1090,7 +1090,7 @@ enum wiimod_classic_keys {
WIIMOD_CLASSIC_KEY_NUM,
};
-static const __u16 wiimod_classic_map[] = {
+static const __u16 wiimod_classic_map_legacy[] = {
BTN_A, /* WIIMOD_CLASSIC_KEY_A */
BTN_B, /* WIIMOD_CLASSIC_KEY_B */
BTN_X, /* WIIMOD_CLASSIC_KEY_X */
@@ -1108,10 +1108,32 @@ static const __u16 wiimod_classic_map[] = {
BTN_TR, /* WIIMOD_CLASSIC_KEY_RT */
};
+static const __u16 wiimod_classic_map[] = {
+ BTN_EAST, /* WIIMOD_CLASSIC_KEY_A */
+ BTN_SOUTH, /* WIIMOD_CLASSIC_KEY_B */
+ BTN_NORTH, /* WIIMOD_CLASSIC_KEY_X */
+ BTN_WEST, /* WIIMOD_CLASSIC_KEY_Y */
+ BTN_TL2, /* WIIMOD_CLASSIC_KEY_ZL */
+ BTN_TR2, /* WIIMOD_CLASSIC_KEY_ZR */
+ BTN_START, /* WIIMOD_CLASSIC_KEY_PLUS */
+ BTN_SELECT, /* WIIMOD_CLASSIC_KEY_MINUS */
+ BTN_MODE, /* WIIMOD_CLASSIC_KEY_HOME */
+ BTN_DPAD_LEFT, /* WIIMOD_CLASSIC_KEY_LEFT */
+ BTN_DPAD_RIGHT, /* WIIMOD_CLASSIC_KEY_RIGHT */
+ BTN_DPAD_UP, /* WIIMOD_CLASSIC_KEY_UP */
+ BTN_DPAD_DOWN, /* WIIMOD_CLASSIC_KEY_DOWN */
+ BTN_TL, /* WIIMOD_CLASSIC_KEY_LT */
+ BTN_TR, /* WIIMOD_CLASSIC_KEY_RT */
+};
+
static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{
+ const __u16 *map = wiimod_classic_map;
__s8 rx, ry, lx, ly, lt, rt;
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY)
+ map = wiimod_classic_map_legacy;
+
/* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
* -----+-----+-----+-----+-----+-----+-----+-----+-----+
* 1 | RX <5:4> | LX <5:0> |
@@ -1177,66 +1199,75 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
rt <<= 1;
lt <<= 1;
- input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20);
- input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20);
- input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
- input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
- input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
- input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20);
+ input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
+ input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
+ input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
+ } else {
+ input_report_abs(wdata->extension.input, ABS_X, lx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_Y, 0x20 - ly);
+ input_report_abs(wdata->extension.input, ABS_RX, rx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_RY, 0x20 - ry);
+ input_report_abs(wdata->extension.input, ABS_HAT1X, rt);
+ input_report_abs(wdata->extension.input, ABS_HAT1Y, lt);
+ }
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
+ map[WIIMOD_CLASSIC_KEY_RIGHT],
!(ext[4] & 0x80));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
+ map[WIIMOD_CLASSIC_KEY_DOWN],
!(ext[4] & 0x40));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT],
+ map[WIIMOD_CLASSIC_KEY_LT],
!(ext[4] & 0x20));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_MINUS],
+ map[WIIMOD_CLASSIC_KEY_MINUS],
!(ext[4] & 0x10));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_HOME],
+ map[WIIMOD_CLASSIC_KEY_HOME],
!(ext[4] & 0x08));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_PLUS],
+ map[WIIMOD_CLASSIC_KEY_PLUS],
!(ext[4] & 0x04));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_RT],
+ map[WIIMOD_CLASSIC_KEY_RT],
!(ext[4] & 0x02));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZL],
+ map[WIIMOD_CLASSIC_KEY_ZL],
!(ext[5] & 0x80));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_B],
+ map[WIIMOD_CLASSIC_KEY_B],
!(ext[5] & 0x40));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_Y],
+ map[WIIMOD_CLASSIC_KEY_Y],
!(ext[5] & 0x20));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_A],
+ map[WIIMOD_CLASSIC_KEY_A],
!(ext[5] & 0x10));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_X],
+ map[WIIMOD_CLASSIC_KEY_X],
!(ext[5] & 0x08));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR],
+ map[WIIMOD_CLASSIC_KEY_ZR],
!(ext[5] & 0x04));
if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
+ map[WIIMOD_CLASSIC_KEY_LEFT],
!(ext[1] & 0x01));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
+ map[WIIMOD_CLASSIC_KEY_UP],
!(ext[0] & 0x01));
} else {
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
+ map[WIIMOD_CLASSIC_KEY_LEFT],
!(ext[5] & 0x02));
input_report_key(wdata->extension.input,
- wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
+ map[WIIMOD_CLASSIC_KEY_UP],
!(ext[5] & 0x01));
}
@@ -1270,12 +1301,16 @@ static void wiimod_classic_close(struct input_dev *dev)
static int wiimod_classic_probe(const struct wiimod_ops *ops,
struct wiimote_data *wdata)
{
+ const __u16 *map = wiimod_classic_map;
int ret, i;
wdata->extension.input = input_allocate_device();
if (!wdata->extension.input)
return -ENOMEM;
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY)
+ map = wiimod_classic_map_legacy;
+
input_set_drvdata(wdata->extension.input, wdata);
wdata->extension.input->open = wiimod_classic_open;
wdata->extension.input->close = wiimod_classic_close;
@@ -1288,28 +1323,49 @@ static int wiimod_classic_probe(const struct wiimod_ops *ops,
set_bit(EV_KEY, wdata->extension.input->evbit);
for (i = 0; i < WIIMOD_CLASSIC_KEY_NUM; ++i)
- set_bit(wiimod_classic_map[i],
- wdata->extension.input->keybit);
+ set_bit(map[i], wdata->extension.input->keybit);
set_bit(EV_ABS, wdata->extension.input->evbit);
- set_bit(ABS_HAT1X, wdata->extension.input->absbit);
- set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
- set_bit(ABS_HAT2X, wdata->extension.input->absbit);
- set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
- set_bit(ABS_HAT3X, wdata->extension.input->absbit);
- set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT1X, -30, 30, 1, 1);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT1Y, -30, 30, 1, 1);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT2X, -30, 30, 1, 1);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT2Y, -30, 30, 1, 1);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT3X, -30, 30, 1, 1);
- input_set_abs_params(wdata->extension.input,
- ABS_HAT3Y, -30, 30, 1, 1);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT2X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT3X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1X, -30, 30, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1Y, -30, 30, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT2X, -30, 30, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT2Y, -30, 30, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT3X, -30, 30, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT3Y, -30, 30, 1, 1);
+ } else {
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ set_bit(ABS_RX, wdata->extension.input->absbit);
+ set_bit(ABS_RY, wdata->extension.input->absbit);
+ set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, -24, 24, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, -24, 24, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_RX, -24, 24, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_RY, -24, 24, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1X, 0, 52, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1Y, 0, 52, 1, 1);
+ }
ret = input_register_device(wdata->extension.input);
if (ret)
--
1.8.4.1
^ permalink raw reply related
* [PATCH 09/13] HID: wiimote: use ABS_ACCEL_* for accelerometer
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
Use the new ABS_ACCEL_* bits for accelerometer data _iff_ legacy mode is
not selected. ABS_R? is confusing and ambigiuous. ABS_ACCEL_* was
introduced exactly for accelerometers like the one of the wiimote.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-modules.c | 38 +++++++++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index f3de94e..777f932 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -477,9 +477,16 @@ static void wiimod_accel_in_accel(struct wiimote_data *wdata,
y |= (accel[1] >> 4) & 0x2;
z |= (accel[1] >> 5) & 0x2;
- input_report_abs(wdata->accel, ABS_RX, x - 0x200);
- input_report_abs(wdata->accel, ABS_RY, y - 0x200);
- input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ input_report_abs(wdata->accel, ABS_RX, x - 0x200);
+ input_report_abs(wdata->accel, ABS_RY, y - 0x200);
+ input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
+ } else {
+ input_report_abs(wdata->accel, ABS_ACCEL_X, x - 0x200);
+ input_report_abs(wdata->accel, ABS_ACCEL_Y, y - 0x200);
+ input_report_abs(wdata->accel, ABS_ACCEL_Z, z - 0x200);
+ }
+
input_sync(wdata->accel);
}
@@ -525,12 +532,25 @@ static int wiimod_accel_probe(const struct wiimod_ops *ops,
wdata->accel->name = WIIMOTE_NAME " Accelerometer";
set_bit(EV_ABS, wdata->accel->evbit);
- set_bit(ABS_RX, wdata->accel->absbit);
- set_bit(ABS_RY, wdata->accel->absbit);
- set_bit(ABS_RZ, wdata->accel->absbit);
- input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
- input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
- input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ set_bit(ABS_RX, wdata->accel->absbit);
+ set_bit(ABS_RY, wdata->accel->absbit);
+ set_bit(ABS_RZ, wdata->accel->absbit);
+ input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
+ input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
+ input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
+ } else {
+ set_bit(ABS_ACCEL_X, wdata->accel->absbit);
+ set_bit(ABS_ACCEL_Y, wdata->accel->absbit);
+ set_bit(ABS_ACCEL_Z, wdata->accel->absbit);
+ input_set_abs_params(wdata->accel, ABS_ACCEL_X,
+ -500, 500, 2, 4);
+ input_set_abs_params(wdata->accel, ABS_ACCEL_Y,
+ -500, 500, 2, 4);
+ input_set_abs_params(wdata->accel, ABS_ACCEL_Z,
+ -500, 500, 2, 4);
+ }
ret = input_register_device(wdata->accel);
if (ret) {
--
1.8.4.1
^ permalink raw reply related
* [PATCH 10/13] HID: wiimote: use ABS_GYRO_* bits for MP
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
Use the new gyroscope bits for motion-plus. The used ABS_R? bits are
ambiguous and should be replaced by proper bits to not confuse generic
user-space.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-modules.c | 44 ++++++++++++++++++++++++++++-----------
1 file changed, 32 insertions(+), 12 deletions(-)
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 777f932..e51e82b 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -2222,9 +2222,16 @@ static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext)
else
z *= 9;
- input_report_abs(wdata->mp, ABS_RX, x);
- input_report_abs(wdata->mp, ABS_RY, y);
- input_report_abs(wdata->mp, ABS_RZ, z);
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ input_report_abs(wdata->mp, ABS_RX, x);
+ input_report_abs(wdata->mp, ABS_RY, y);
+ input_report_abs(wdata->mp, ABS_RZ, z);
+ } else {
+ input_report_abs(wdata->mp, ABS_GYRO_X, x);
+ input_report_abs(wdata->mp, ABS_GYRO_Y, y);
+ input_report_abs(wdata->mp, ABS_GYRO_Z, z);
+ }
+
input_sync(wdata->mp);
}
@@ -2274,15 +2281,28 @@ static int wiimod_mp_probe(const struct wiimod_ops *ops,
wdata->mp->name = WIIMOTE_NAME " Motion Plus";
set_bit(EV_ABS, wdata->mp->evbit);
- set_bit(ABS_RX, wdata->mp->absbit);
- set_bit(ABS_RY, wdata->mp->absbit);
- set_bit(ABS_RZ, wdata->mp->absbit);
- input_set_abs_params(wdata->mp,
- ABS_RX, -16000, 16000, 4, 8);
- input_set_abs_params(wdata->mp,
- ABS_RY, -16000, 16000, 4, 8);
- input_set_abs_params(wdata->mp,
- ABS_RZ, -16000, 16000, 4, 8);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_LEGACY) {
+ set_bit(ABS_RX, wdata->mp->absbit);
+ set_bit(ABS_RY, wdata->mp->absbit);
+ set_bit(ABS_RZ, wdata->mp->absbit);
+ input_set_abs_params(wdata->mp,
+ ABS_RX, -16000, 16000, 4, 8);
+ input_set_abs_params(wdata->mp,
+ ABS_RY, -16000, 16000, 4, 8);
+ input_set_abs_params(wdata->mp,
+ ABS_RZ, -16000, 16000, 4, 8);
+ } else {
+ set_bit(ABS_GYRO_X, wdata->mp->absbit);
+ set_bit(ABS_GYRO_Y, wdata->mp->absbit);
+ set_bit(ABS_GYRO_Z, wdata->mp->absbit);
+ input_set_abs_params(wdata->mp,
+ ABS_GYRO_X, -16000, 16000, 4, 8);
+ input_set_abs_params(wdata->mp,
+ ABS_GYRO_Y, -16000, 16000, 4, 8);
+ input_set_abs_params(wdata->mp,
+ ABS_GYRO_Z, -16000, 16000, 4, 8);
+ }
ret = input_register_device(wdata->mp);
if (ret)
--
1.8.4.1
^ permalink raw reply related
* [PATCH 11/13] Input: introduce BTN/ABS bits for drums and guitars
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
There are a bunch of guitar and drums devices out there that all report
similar data. To avoid reporting this as BTN_MISC or ABS_MISC, we
allocate some proper namespace for them. Note that most of these devices
are toys and we cannot report any sophisticated physics via this API.
I did some google-images research and tried to provide definitions that
work with all common devices. That's why I went with 4 toms, 4 cymbals,
one bass, one hi-hat. I haven't seen other drums and I doubt that we need
any additions to that. Anyway, the naming-scheme is intentionally done in
an extensible way.
For guitars, we support 5 frets (normally aligned vertically, compared to
the real horizontal layouts), a single strum-bar with up/down directions,
an optional fret-board and a whammy-bar.
Most of the devices provide pressure values so I went with ABS_* bits. If
we ever support devices which only provide digital input, we have to
decide whether to emulate pressure data or add additional BTN_* bits.
If someone is not familiar with these devices, here are two pictures which
provide almost all introduced interfaces (or try the given keywords
with a google-image search):
Guitar: ("guitar hero world tour guitar")
http://images1.wikia.nocookie.net/__cb20120911023442/applezone/es/images/f/f9/Wii_Guitar.jpg
Drums: ("guitar hero drums")
http://oyster.ignimgs.com/franchises/images/03/55/35526_band-hero-drum-set-hands-on-20090929040735768.jpg
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
include/linux/mod_devicetable.h | 2 +-
include/uapi/linux/input.h | 24 +++++++++++++++++++++++-
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 329aa30..61f358a 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -277,7 +277,7 @@ struct pcmcia_device_id {
#define INPUT_DEVICE_ID_KEY_MIN_INTERESTING 0x71
#define INPUT_DEVICE_ID_KEY_MAX 0x2ff
#define INPUT_DEVICE_ID_REL_MAX 0x0f
-#define INPUT_DEVICE_ID_ABS_MAX 0x4f
+#define INPUT_DEVICE_ID_ABS_MAX 0x5f
#define INPUT_DEVICE_ID_MSC_MAX 0x07
#define INPUT_DEVICE_ID_LED_MAX 0x0f
#define INPUT_DEVICE_ID_SND_MAX 0x07
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index f347498..3aac45a 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -742,6 +742,14 @@ struct input_keymap_entry {
#define BTN_DPAD_LEFT 0x222
#define BTN_DPAD_RIGHT 0x223
+#define BTN_FRET_FAR_UP 0x224
+#define BTN_FRET_UP 0x225
+#define BTN_FRET_MID 0x226
+#define BTN_FRET_LOW 0x227
+#define BTN_FRET_FAR_LOW 0x228
+#define BTN_STRUM_BAR_UP 0x229
+#define BTN_STRUM_BAR_DOWN 0x22a
+
#define BTN_TRIGGER_HAPPY 0x2c0
#define BTN_TRIGGER_HAPPY1 0x2c0
#define BTN_TRIGGER_HAPPY2 0x2c1
@@ -870,12 +878,26 @@ struct input_keymap_entry {
#define ABS_GYRO_Y 0x44 /* Gyroscope Y axis */
#define ABS_GYRO_Z 0x45 /* Gyroscope Z axis */
+/* Drums and guitars (mostly toys) */
+#define ABS_TOM_FAR_LEFT 0x50
+#define ABS_TOM_LEFT 0x51
+#define ABS_TOM_RIGHT 0x52
+#define ABS_TOM_FAR_RIGHT 0x53
+#define ABS_CYMBAL_FAR_LEFT 0x54
+#define ABS_CYMBAL_LEFT 0x55
+#define ABS_CYMBAL_RIGHT 0x56
+#define ABS_CYMBAL_FAR_RIGHT 0x57
+#define ABS_BASS 0x58
+#define ABS_HI_HAT 0x59
+#define ABS_FRET_BOARD 0x5a /* Guitar fret board, vertical pos */
+#define ABS_WHAMMY_BAR 0x5b /* Guitar whammy bar (or vibrato) */
+
/*
* Due to API restrictions the legacy evdev API only supports ABS values up to
* ABS_MAX/CNT. Use the extended *ABS2 ioctls to operate on any ABS values in
* between ABS_MAX and ABS_MAX2.
*/
-#define ABS_MAX2 0x4f
+#define ABS_MAX2 0x5f
#define ABS_CNT2 (ABS_MAX2+1)
/*
--
1.8.4.1
^ permalink raw reply related
* [PATCH 12/13] HID: wiimote: add support for Guitar-Hero drums
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
Guitar-Hero comes with a drums extension. Use the newly introduced input
drums-bits to report this back to user-space. This is a usual extension
like any other device. Nothing special to take care of.
We report this to user-space as "Nintendo Wii Remote Drums". There are
other drums (like "RockBand" drums) which we currently do not support and
maybe will at some point. However, it is quite likely that we can report
these via the same interface. This allows user-space to work with them
without knowing the exact branding.
I couldn't find anyone who owns a "RockBand" device, though.
Initial-work-by: Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-core.c | 7 ++
drivers/hid/hid-wiimote-modules.c | 218 ++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 2 +
3 files changed, 227 insertions(+)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 89ca031..6212678 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -458,6 +458,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
return WIIMOTE_EXT_BALANCE_BOARD;
if (rmem[4] == 0x01 && rmem[5] == 0x20)
return WIIMOTE_EXT_PRO_CONTROLLER;
+ if (rmem[0] == 0x01 && rmem[1] == 0x00 &&
+ rmem[4] == 0x01 && rmem[5] == 0x03)
+ return WIIMOTE_EXT_GUITAR_HERO_DRUMS;
return WIIMOTE_EXT_UNKNOWN;
}
@@ -491,6 +494,7 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
/* map MP with correct pass-through mode */
switch (exttype) {
case WIIMOTE_EXT_CLASSIC_CONTROLLER:
+ case WIIMOTE_EXT_GUITAR_HERO_DRUMS:
wmem = 0x07;
break;
case WIIMOTE_EXT_NUNCHUK:
@@ -1079,6 +1083,7 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller",
[WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
[WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
+ [WIIMOTE_EXT_GUITAR_HERO_DRUMS] = "Nintendo Wii Guitar Hero Drums",
};
/*
@@ -1664,6 +1669,8 @@ static ssize_t wiimote_ext_show(struct device *dev,
return sprintf(buf, "balanceboard\n");
case WIIMOTE_EXT_PRO_CONTROLLER:
return sprintf(buf, "procontroller\n");
+ case WIIMOTE_EXT_GUITAR_HERO_DRUMS:
+ return sprintf(buf, "drums\n");
case WIIMOTE_EXT_UNKNOWN:
/* fallthrough */
default:
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index e51e82b..5f6d66b 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -2090,6 +2090,223 @@ static const struct wiimod_ops wiimod_pro = {
};
/*
+ * Drums
+ * Guitar-Hero, Rock-Band and other games came bundled with drums which can
+ * be plugged as extension to a Wiimote. Drum-reports are still not entirely
+ * figured out, but the most important information is known.
+ * We create a separate device for drums and report all information via this
+ * input device.
+ */
+
+static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata,
+ __u8 none, __u8 which,
+ __u8 pressure, __u8 onoff,
+ __u8 *store, __u16 code,
+ __u8 which_code)
+{
+ static const __u8 default_pressure = 3;
+
+ if (!none && which == which_code) {
+ *store = pressure;
+ input_report_abs(wdata->extension.input, code, *store);
+ } else if (onoff != !!*store) {
+ *store = onoff ? default_pressure : 0;
+ input_report_abs(wdata->extension.input, code, *store);
+ }
+}
+
+static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+ __u8 pressure, which, none, hhp, sx, sy;
+ __u8 o, r, y, g, b, bass, bm, bp;
+
+ /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:0> |
+ * 2 | 0 | 0 | SY <5:0> |
+ * -----+-----+-----+-----------------------------+-----+
+ * 3 | HPP | NON | WHICH <5:1> | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | O | R | Y | G | B | BSS | 1 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * All buttons are 0 if pressed
+ *
+ * With Motion+ enabled, the following bits will get invalid:
+ * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:1> |XXXXX|
+ * 2 | 0 | 0 | SY <5:1> |XXXXX|
+ * -----+-----+-----+-----------------------------+-----+
+ * 3 | HPP | NON | WHICH <5:1> | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 |XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | O | R | Y | G | B | BSS |XXXXX|XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+ pressure = 7 - (ext[3] >> 5);
+ which = (ext[2] >> 1) & 0x1f;
+ none = !!(ext[2] & 0x40);
+ hhp = !(ext[2] & 0x80);
+ sx = ext[0] & 0x3f;
+ sy = ext[1] & 0x3f;
+ o = !(ext[5] & 0x80);
+ r = !(ext[5] & 0x40);
+ y = !(ext[5] & 0x20);
+ g = !(ext[5] & 0x10);
+ b = !(ext[5] & 0x08);
+ bass = !(ext[5] & 0x04);
+ bm = !(ext[4] & 0x10);
+ bp = !(ext[4] & 0x04);
+
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ o, &wdata->state.pressure_drums[0],
+ ABS_CYMBAL_RIGHT, 0x0e);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ r, &wdata->state.pressure_drums[1],
+ ABS_TOM_LEFT, 0x19);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ y, &wdata->state.pressure_drums[2],
+ ABS_CYMBAL_LEFT, 0x11);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ g, &wdata->state.pressure_drums[3],
+ ABS_TOM_FAR_RIGHT, 0x12);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ b, &wdata->state.pressure_drums[4],
+ ABS_TOM_RIGHT, 0x0f);
+
+ /* Bass shares pressure with hi-hat (set via hhp) */
+ wiimod_drums_report_pressure(wdata, none, hhp ? 0xff : which, pressure,
+ bass, &wdata->state.pressure_drums[5],
+ ABS_BASS, 0x1b);
+ /* Hi-hat has no on/off values, just pressure. Force to off/0. */
+ wiimod_drums_report_pressure(wdata, none, hhp ? which : 0xff, pressure,
+ 0, &wdata->state.pressure_drums[6],
+ ABS_HI_HAT, 0x0e);
+
+ input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+
+ input_report_key(wdata->extension.input, BTN_START, bp);
+ input_report_key(wdata->extension.input, BTN_SELECT, bm);
+
+ input_sync(wdata->extension.input);
+}
+
+static int wiimod_drums_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_drums_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_drums_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ int ret;
+
+ wdata->extension.input = input_allocate_device();
+ if (!wdata->extension.input)
+ return -ENOMEM;
+
+ input_set_drvdata(wdata->extension.input, wdata);
+ wdata->extension.input->open = wiimod_drums_open;
+ wdata->extension.input->close = wiimod_drums_close;
+ wdata->extension.input->dev.parent = &wdata->hdev->dev;
+ wdata->extension.input->id.bustype = wdata->hdev->bus;
+ wdata->extension.input->id.vendor = wdata->hdev->vendor;
+ wdata->extension.input->id.product = wdata->hdev->product;
+ wdata->extension.input->id.version = wdata->hdev->version;
+ wdata->extension.input->name = WIIMOTE_NAME " Drums";
+
+ set_bit(EV_KEY, wdata->extension.input->evbit);
+ set_bit(BTN_START, wdata->extension.input->keybit);
+ set_bit(BTN_SELECT, wdata->extension.input->keybit);
+
+ set_bit(EV_ABS, wdata->extension.input->evbit);
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ set_bit(ABS_TOM_LEFT, wdata->extension.input->absbit);
+ set_bit(ABS_TOM_RIGHT, wdata->extension.input->absbit);
+ set_bit(ABS_TOM_FAR_RIGHT, wdata->extension.input->absbit);
+ set_bit(ABS_CYMBAL_LEFT, wdata->extension.input->absbit);
+ set_bit(ABS_CYMBAL_RIGHT, wdata->extension.input->absbit);
+ set_bit(ABS_BASS, wdata->extension.input->absbit);
+ set_bit(ABS_HI_HAT, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_TOM_LEFT, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_TOM_RIGHT, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_TOM_FAR_RIGHT, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_CYMBAL_LEFT, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_CYMBAL_RIGHT, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_BASS, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HI_HAT, 0, 7, 0, 0);
+
+ ret = input_register_device(wdata->extension.input);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ input_free_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+ return ret;
+}
+
+static void wiimod_drums_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ if (!wdata->extension.input)
+ return;
+
+ input_unregister_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_drums = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_drums_probe,
+ .remove = wiimod_drums_remove,
+ .in_ext = wiimod_drums_in_ext,
+};
+
+/*
* Builtin Motion Plus
* This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
* disables polling for Motion-Plus. This should be set only for devices which
@@ -2359,4 +2576,5 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic,
[WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
[WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
+ [WIIMOTE_EXT_GUITAR_HERO_DRUMS] = &wiimod_drums,
};
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 6f70823..c8a7fc3 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -90,6 +90,7 @@ enum wiimote_exttype {
WIIMOTE_EXT_CLASSIC_CONTROLLER,
WIIMOTE_EXT_BALANCE_BOARD,
WIIMOTE_EXT_PRO_CONTROLLER,
+ WIIMOTE_EXT_GUITAR_HERO_DRUMS,
WIIMOTE_EXT_NUM,
};
@@ -139,6 +140,7 @@ struct wiimote_state {
__u16 calib_bboard[4][3];
__s16 calib_pro_sticks[4];
__u8 cache_rumble;
+ __u8 pressure_drums[7];
};
struct wiimote_data {
--
1.8.4.1
^ permalink raw reply related
* [PATCH 13/13] HID: wiimote: add support for Guitar-Hero guitars
From: David Herrmann @ 2013-11-01 20:16 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
Nicolas Adenis-Lamarre, David Herrmann
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
From: Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
Apart from drums, Guitar-Hero also ships with guitars. Use the recently
introduced input ABS/BTN-bits to report this to user-space.
Devices are reported as "Nintendo Wii Remote Guitar". If I ever get my
hands on "RockBand" guitars, I will try to report them via the same
interface so user-space does not have to bother which device it deals
with.
Signed-off-by: Nicolas.Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
(add commit-msg and adjust to new BTN_* IDs)
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/hid/hid-wiimote-core.c | 7 ++
drivers/hid/hid-wiimote-modules.c | 174 ++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-wiimote.h | 1 +
3 files changed, 182 insertions(+)
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 6212678..829e437 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -461,6 +461,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
if (rmem[0] == 0x01 && rmem[1] == 0x00 &&
rmem[4] == 0x01 && rmem[5] == 0x03)
return WIIMOTE_EXT_GUITAR_HERO_DRUMS;
+ if (rmem[0] == 0x00 && rmem[1] == 0x00 &&
+ rmem[4] == 0x01 && rmem[5] == 0x03)
+ return WIIMOTE_EXT_GUITAR_HERO_GUITAR;
return WIIMOTE_EXT_UNKNOWN;
}
@@ -495,6 +498,7 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
switch (exttype) {
case WIIMOTE_EXT_CLASSIC_CONTROLLER:
case WIIMOTE_EXT_GUITAR_HERO_DRUMS:
+ case WIIMOTE_EXT_GUITAR_HERO_GUITAR:
wmem = 0x07;
break;
case WIIMOTE_EXT_NUNCHUK:
@@ -1084,6 +1088,7 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
[WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
[WIIMOTE_EXT_GUITAR_HERO_DRUMS] = "Nintendo Wii Guitar Hero Drums",
+ [WIIMOTE_EXT_GUITAR_HERO_GUITAR] = "Nintendo Wii Guitar Hero Guitar",
};
/*
@@ -1671,6 +1676,8 @@ static ssize_t wiimote_ext_show(struct device *dev,
return sprintf(buf, "procontroller\n");
case WIIMOTE_EXT_GUITAR_HERO_DRUMS:
return sprintf(buf, "drums\n");
+ case WIIMOTE_EXT_GUITAR_HERO_GUITAR:
+ return sprintf(buf, "guitar\n");
case WIIMOTE_EXT_UNKNOWN:
/* fallthrough */
default:
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 5f6d66b..625e1f3 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -2307,6 +2307,179 @@ static const struct wiimod_ops wiimod_drums = {
};
/*
+ * Guitar
+ * Guitar-Hero, Rock-Band and other games came bundled with guitars which can
+ * be plugged as extension to a Wiimote.
+ * We create a separate device for guitars and report all information via this
+ * input device.
+ */
+
+static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+ __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu;
+
+ /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:0> |
+ * 2 | 0 | 0 | SY <5:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 3 | 0 | 0 | 0 | TB <4:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 4 | 0 | 0 | 0 | WB <4:0> |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | BO | BR | BB | BG | BY | 1 | 1 | BU |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * All buttons are 0 if pressed
+ *
+ * With Motion+ enabled, the following bits will get invalid:
+ * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:1> |XXXXX|
+ * 2 | 0 | 0 | SY <5:1> |XXXXX|
+ * -----+-----+-----+-----+-----------------------+-----+
+ * 3 | 0 | 0 | 0 | TB <4:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 4 | 0 | 0 | 0 | WB <4:0> |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 |XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | BO | BR | BB | BG | BY | 1 |XXXXX|XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+ sx = ext[0] & 0x3f;
+ sy = ext[1] & 0x3f;
+ tb = ext[2] & 0x1f;
+ wb = ext[3] & 0x1f;
+ bd = !(ext[4] & 0x40);
+ bm = !(ext[4] & 0x10);
+ bp = !(ext[4] & 0x04);
+ bo = !(ext[5] & 0x80);
+ br = !(ext[5] & 0x40);
+ bb = !(ext[5] & 0x20);
+ bg = !(ext[5] & 0x10);
+ by = !(ext[5] & 0x08);
+ bu = !(ext[5] & 0x01);
+
+ input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+ input_report_abs(wdata->extension.input, ABS_FRET_BOARD, tb);
+ input_report_abs(wdata->extension.input, ABS_WHAMMY_BAR, wb - 0x10);
+
+ input_report_key(wdata->extension.input, BTN_MODE, bm);
+ input_report_key(wdata->extension.input, BTN_START, bp);
+ input_report_key(wdata->extension.input, BTN_STRUM_BAR_UP, bu);
+ input_report_key(wdata->extension.input, BTN_STRUM_BAR_DOWN, bd);
+ input_report_key(wdata->extension.input, BTN_FRET_FAR_UP, bg);
+ input_report_key(wdata->extension.input, BTN_FRET_UP, br);
+ input_report_key(wdata->extension.input, BTN_FRET_MID, by);
+ input_report_key(wdata->extension.input, BTN_FRET_LOW, bb);
+ input_report_key(wdata->extension.input, BTN_FRET_FAR_LOW, bo);
+
+ input_sync(wdata->extension.input);
+}
+
+static int wiimod_guitar_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_guitar_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_guitar_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ int ret;
+
+ wdata->extension.input = input_allocate_device();
+ if (!wdata->extension.input)
+ return -ENOMEM;
+
+ input_set_drvdata(wdata->extension.input, wdata);
+ wdata->extension.input->open = wiimod_guitar_open;
+ wdata->extension.input->close = wiimod_guitar_close;
+ wdata->extension.input->dev.parent = &wdata->hdev->dev;
+ wdata->extension.input->id.bustype = wdata->hdev->bus;
+ wdata->extension.input->id.vendor = wdata->hdev->vendor;
+ wdata->extension.input->id.product = wdata->hdev->product;
+ wdata->extension.input->id.version = wdata->hdev->version;
+ wdata->extension.input->name = WIIMOTE_NAME " Guitar";
+
+ set_bit(EV_KEY, wdata->extension.input->evbit);
+ set_bit(BTN_MODE, wdata->extension.input->keybit);
+ set_bit(BTN_START, wdata->extension.input->keybit);
+ set_bit(BTN_FRET_FAR_UP, wdata->extension.input->keybit);
+ set_bit(BTN_FRET_UP, wdata->extension.input->keybit);
+ set_bit(BTN_FRET_MID, wdata->extension.input->keybit);
+ set_bit(BTN_FRET_LOW, wdata->extension.input->keybit);
+ set_bit(BTN_FRET_FAR_LOW, wdata->extension.input->keybit);
+ set_bit(BTN_STRUM_BAR_UP, wdata->extension.input->keybit);
+ set_bit(BTN_STRUM_BAR_DOWN, wdata->extension.input->keybit);
+
+ set_bit(EV_ABS, wdata->extension.input->evbit);
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ set_bit(ABS_FRET_BOARD, wdata->extension.input->absbit);
+ set_bit(ABS_WHAMMY_BAR, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_FRET_BOARD, 0, 0x1f, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_WHAMMY_BAR, 0, 0x0f, 1, 1);
+
+ ret = input_register_device(wdata->extension.input);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ input_free_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+ return ret;
+}
+
+static void wiimod_guitar_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ if (!wdata->extension.input)
+ return;
+
+ input_unregister_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_guitar = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_guitar_probe,
+ .remove = wiimod_guitar_remove,
+ .in_ext = wiimod_guitar_in_ext,
+};
+
+/*
* Builtin Motion Plus
* This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
* disables polling for Motion-Plus. This should be set only for devices which
@@ -2577,4 +2750,5 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
[WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
[WIIMOTE_EXT_GUITAR_HERO_DRUMS] = &wiimod_drums,
+ [WIIMOTE_EXT_GUITAR_HERO_GUITAR] = &wiimod_guitar,
};
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index c8a7fc3..0ca6262 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -91,6 +91,7 @@ enum wiimote_exttype {
WIIMOTE_EXT_BALANCE_BOARD,
WIIMOTE_EXT_PRO_CONTROLLER,
WIIMOTE_EXT_GUITAR_HERO_DRUMS,
+ WIIMOTE_EXT_GUITAR_HERO_GUITAR,
WIIMOTE_EXT_NUM,
};
--
1.8.4.1
^ permalink raw reply related
* changes to ati_remote to support ATI Remote Wonder Plus RF Remote Control
From: Stephen Oberski @ 2013-11-01 22:45 UTC (permalink / raw)
To: sfo; +Cc: linux-input
I've been attempting to send a message to the linux-input list describing proposed changes to the ati_remote.c (drivers/media/rc/ati_remote.c) module
that would allow for support of the ATI Remote Wonder Plus RF Remote Control.
I've stripped the message down to these few lines to determine if it is the content of the message that is causing it to be rejected.
Thanks,
--
Stephen Oberski
sfo@cargocult.ca
^ permalink raw reply
* [PATCH] INPUT: wacom: Added definition for Wacom CTH680 The Wacom Creative Pen & Touch Tablet M (CTH680, 056A:0303) is a newer revision of the Bamboo series. This patch adds product 0303 to wacom.ko.
From: matthew @ 2013-11-02 19:04 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-input, Matthew Geddes
From: Matthew Geddes <matthew@incomplete.io>
Signed-off-by: Matthew Geddes <matthew@incomplete.io>
---
drivers/input/tablet/wacom_wac.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index c59b797..5015269 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -2128,6 +2128,9 @@ static const struct wacom_features wacom_features_0x300 =
static const struct wacom_features wacom_features_0x301 =
{ "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023,
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x303 =
+ { "Wacom Creative Touch & Pen M", WACOM_PKGLEN_BBPEN, 21648, 13530,
+ 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x6004 =
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2258,6 +2261,7 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x10F) },
{ USB_DEVICE_WACOM(0x300) },
{ USB_DEVICE_WACOM(0x301) },
+ { USB_DEVICE_WACOM(0x303) },
{ USB_DEVICE_WACOM(0x304) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x47) },
--
1.8.3.2
^ permalink raw reply related
* [PATCH] HID: roccat: Fixed Coverity CID 141438
From: Stefan Achatz @ 2013-11-03 5:25 UTC (permalink / raw)
To: Stefan Achatz, Jiri Kosina, linux-input, linux-kernel
Signed-off-by: Stefan Achatz <erazor_de@users.sourceforge.net>
---
drivers/hid/hid-roccat-kovaplus.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 0c8e1ef..9660477 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -554,9 +554,13 @@ static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus,
break;
case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI:
kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1);
+ break;
case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY:
kovaplus->actual_x_sensitivity = button_report->data1;
kovaplus->actual_y_sensitivity = button_report->data2;
+ break;
+ default:
+ break;
}
}
--
1.7.3.4
^ permalink raw reply related
* incorrect determination of the USB-sound card
From: Sohin Vyacheslaw @ 2013-11-04 8:26 UTC (permalink / raw)
To: linux-input
Hi,
when an external USB sound card inserted in the logfile the following
messages:
Oct 28 13:01:34 sldas kernel: [ 3036.571158] usb 2-1.2.1: new full-speed
USB device number 9 using ehci-pci
Oct 28 13:01:35 sldas kernel: [ 3036.663870] usb 2-1.2.1: New USB device
found, idVendor=0d8c, idProduct=000e
Oct 28 13:01:35 sldas kernel: [ 3036.663881] usb 2-1.2.1: New USB device
strings: Mfr=0, Product=1, SerialNumber=0
Oct 28 13:01:35 sldas kernel: [ 3036.663888] usb 2-1.2.1: Product:
Generic USB Audio Device
Oct 28 13:01:35 sldas kernel: [ 3036.682211] input: CM109 USB driver as
/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2.1/2-1.2.1:1.3/input/input16
Oct 28 13:01:35 sldas mtp-probe: checking bus 2, device 9:
"/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2.1"
Oct 28 13:01:35 sldas mtp-probe: bus: 2, device: 9 was not an MTP device
idVendor and idProduct -> correct: C-Media
but CM109 USB driver is for voip phones:
$ modinfo cm109
filename:
/lib/modules/3.2.0-4-686-pae/kernel/drivers/input/misc/cm109.ko
license: GPL
description: CM109 phone driver
author: Alfred E. Heggestad
alias: usb:v0D8Cp000Ed*dc*dsc*dp*ic03isc00ip00*
depends: usbcore
intree: Y
vermagic: 3.2.0-4-686-pae SMP mod_unload modversions 686
parm: phone:Phone name {kip1000, gtalk, usbph01, atcom} (charp)
I've tried to use each parameter (kip1000, gtalk, usbph01, atcom) and
try on a different linux distros with different kernels (also compiled
kernel) - the result is the same card plays audio, but some functions
don't work properly: increase, decrease volume...
In Windows 7 operating system all functions of this sound card correct...
what's the right driver can be used for this card in Linux?
p.s. after enabling CONFIG_USB_DEBUG and rebuild the kernel in logfile
when connecting card:
Oct 30 21:06:35 sky-19 kernel: [ 232.453931] usb 2-1.2: new full-speed
USB device number 7 using ehci-pci
Oct 30 21:06:35 sky-19 kernel: [ 232.546522] usb 2-1.2: skipped 10
descriptors after interface
Oct 30 21:06:35 sky-19 kernel: [ 232.546534] usb 2-1.2: skipped 2
descriptors after interface
Oct 30 21:06:35 sky-19 kernel: [ 232.546541] usb 2-1.2: skipped 1
descriptor after endpoint
Oct 30 21:06:35 sky-19 kernel: [ 232.546547] usb 2-1.2: skipped 2
descriptors after interface
Oct 30 21:06:35 sky-19 kernel: [ 232.546552] usb 2-1.2: skipped 1
descriptor after endpoint
Oct 30 21:06:35 sky-19 kernel: [ 232.546558] usb 2-1.2: skipped 1
descriptor after interface
Oct 30 21:06:35 sky-19 kernel: [ 232.546766] usb 2-1.2: default
language 0x0409
Oct 30 21:06:35 sky-19 kernel: [ 232.547012] usb 2-1.2: udev 7, busnum
2, minor = 134
Oct 30 21:06:35 sky-19 kernel: [ 232.547021] usb 2-1.2: New USB device
found, idVendor=0d8c, idProduct=000e
Oct 30 21:06:35 sky-19 kernel: [ 232.547028] usb 2-1.2: New USB device
strings: Mfr=0, Product=1, SerialNumber=0
Oct 30 21:06:35 sky-19 kernel: [ 232.547034] usb 2-1.2: Product:
Generic USB Audio Device
Oct 30 21:06:35 sky-19 kernel: [ 232.547263] usb 2-1.2: usb_probe_device
Oct 30 21:06:35 sky-19 kernel: [ 232.547271] usb 2-1.2: configuration
#1 chosen from 1 choice
Oct 30 21:06:35 sky-19 kernel: [ 232.547397] usb 2-1.2: adding
2-1.2:1.0 (config #1, interface 0)
Oct 30 21:06:35 sky-19 kernel: [ 232.547477] snd-usb-audio 2-1.2:1.0:
usb_probe_interface
Oct 30 21:06:35 sky-19 kernel: [ 232.547489] snd-usb-audio 2-1.2:1.0:
usb_probe_interface - got id
Oct 30 21:06:35 sky-19 kernel: [ 232.566883] usb 2-1.2: adding
2-1.2:1.1 (config #1, interface 1)
Oct 30 21:06:35 sky-19 kernel: [ 232.566950] usb 2-1.2: adding
2-1.2:1.2 (config #1, interface 2)
Oct 30 21:06:35 sky-19 kernel: [ 232.567009] usb 2-1.2: adding
2-1.2:1.3 (config #1, interface 3)
Oct 30 21:06:35 sky-19 kernel: [ 232.567062] usbhid 2-1.2:1.3:
usb_probe_interface
Oct 30 21:06:35 sky-19 kernel: [ 232.567069] usbhid 2-1.2:1.3:
usb_probe_interface - got id
Oct 30 21:06:35 sky-19 kernel: [ 232.567186] hub 2-1:1.0: state 7 ports
6 chg 0000 evt 0004
Oct 30 21:06:35 sky-19 mtp-probe: checking bus 2, device 7:
"/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2"
Oct 30 21:06:35 sky-19 mtp-probe: bus: 2, device: 7 was not an MTP device
Oct 30 21:06:35 sky-19 kernel: [ 232.606164] cm109: Keymap for
Komunikate KIP1000 phone loaded
Oct 30 21:06:35 sky-19 kernel: [ 232.606189] cm109 2-1.2:1.3:
usb_probe_interface
Oct 30 21:06:35 sky-19 kernel: [ 232.606193] cm109 2-1.2:1.3:
usb_probe_interface - got id
Oct 30 21:06:35 sky-19 kernel: [ 232.606279] input: CM109 USB driver as
/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.3/input/input15
Oct 30 21:06:35 sky-19 kernel: [ 232.606474] usb 2-1.2: link
qh32-0e01/ee754bc0 start 5 [1/2 us]
Oct 30 21:06:35 sky-19 kernel: [ 232.607234] usbcore: registered new
interface driver cm109
Oct 30 21:06:35 sky-19 kernel: [ 232.607238] cm109: CM109 phone driver:
20080805 (C) Alfred E. Heggestad
Oct 30 21:06:35 sky-19 kernel: [ 232.611347] usb 2-1.2: unlink
qh32-0e01/ee754bc0 start 5 [1/2 us]
Oct 30 21:06:35 sky-19 kernel: [ 232.613491] ehci-pci 0000:00:1d.0:
reused qh ee754bc0 schedule
Oct 30 21:06:35 sky-19 kernel: [ 232.613498] usb 2-1.2: link
qh32-0e01/ee754bc0 start 5 [1/2 us]
--
Best wishes,
Sohin Vyacheslav
^ permalink raw reply
* Re: [PATCH] HID: roccat: Fixed Coverity CID 141438
From: Jiri Kosina @ 2013-11-04 9:59 UTC (permalink / raw)
To: Stefan Achatz; +Cc: linux-input, linux-kernel
In-Reply-To: <1383456333.4017.2.camel@neuromancer.tessier-ashpool>
Applied, thanks Stefan.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCHv7][ 1/4] Input: tsc2007: Add device tree support.
From: Linus Walleij @ 2013-11-04 12:01 UTC (permalink / raw)
To: Thierry Reding
Cc: Denis Carikli, Rob Herring, Shawn Guo, Eric Bénard,
Sascha Hauer, linux-arm-kernel@lists.infradead.org, Grant Likely,
Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell,
devicetree@vger.kernel.org, Dmitry Torokhov, Linux Input,
Lothar Waßmann
In-Reply-To: <20131024151736.GE9044@ulmo.nvidia.com>
On Thu, Oct 24, 2013 at 5:17 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Thu, Oct 24, 2013 at 02:42:13PM +0200, Denis Carikli wrote:
>> +Optional properties:
>> +- gpios: the interrupt gpio the chip is connected to (trough the penirq pin)
>> + (see GPIO binding[2] for more details).
>> +- interrupt-parent: the phandle for the gpio controller
>> + (see interrupt binding[1]).
>> +- interrupts: (gpio) interrupt to which the chip is connected
>> + (see interrupt binding[1]).
>> +- pinctrl-0: Should specify pin control groups used for the gpio
>> + (see pinctrl bindings[0]).
>> +- pinctrl-names: Should contain only one value - "default"
>> + (see pinctrl bindings[0]).
>
> Also I haven't seen a response as to why this can't be handled by the
> GPIO driver. Adding Linus Walleij, perhaps he knows a more definitive
> answer.
>
> Linus, the issue here is that the pinctrl properties for this chip are
> supposed to pinmux the pendown GPIO for this chip. I was under the
> impression that this should be handled by the GPIO controller itself, so
> that when gpio_request() was called on a pin it would be the GPIO
> controller driver's responsibility to pinmux it appropriately.
If this is the only thing it does (just mux in the GPIO and not setting
any pulls or other pin config properties) then it can fall through from
the GPIO controller's request function to pinctrl_request_gpio()
and then pinctrl_free_gpio(), pinctrl_gpio_direction_input()
and pinctrl_gpio_direction_output() respectively so that pin control
provides a muxing back end to the GPIO driver.
Actually these functions are up to the driver to implement, but
the core will call ->gpio_request_enable() on the pinctrl driver,
and if all GPIOs are set up the same way (i.e. the same bits
are always poked into the hardware) then this can be done
in that routine.
If more fine-grained control is needed, this approach providing
a full pin control handle and state settings connected to the
struct device * can and should be used instead.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 00/13] Input/HID: Bits and Pieces
From: Jiri Kosina @ 2013-11-04 13:04 UTC (permalink / raw)
To: David Herrmann
Cc: linux-input, Dmitry Torokhov, Peter Hutterer, Benjamin Tissoires
In-Reply-To: <1383336984-26601-1-git-send-email-dh.herrmann@gmail.com>
On Fri, 1 Nov 2013, David Herrmann wrote:
> My backlog kept growing and most of the stuff depends on the ABS_* fixes, so I
> gave it another try. The first 2 patches introduce EVIOC[GS]ABS2 and friends.
> The rest is wiimote stuff that was laying around for some time and just needs
> new ABS bits. So once the ABS stuff is in, I see no reason to delay the wiimote
> patches (as they're even tested already). Hence, I put it all in a single
> series.
>
> Jiri, Dmitry, feel free to bribe me to split / not split the series so the
> other one has to take it through their tree. Highest bid wins!
I am fine with the HID changes, but Dmitry definitely needs to Ack the
ABS_MAX2 stuff.
After that is done, I can either take the series through my tree with his
Ack, or vice versa, I don't really have strong opinion there.
> And I am still running tests, so please don't merge, yet. I will report back my
> results. Besides, it's probably too late for 3.13, anyway and we should put it
> into -next for 3.14 for some while.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: About the PS3 Sixaxis linux driver
From: Benjamin Tissoires @ 2013-11-04 20:37 UTC (permalink / raw)
To: case; +Cc: linux-input
In-Reply-To: <526A697E.7050605@corpsmoderne.net>
Hi Marc,
(adding in CC the linux-input mailing list)
Regarding your problem I vaguely remember something about not having duplicated axis with the buttons. My memory is rather confuse about this, so I may be wrong (but others on the list may have a fresher memory).
Other than that, if only one axis is not working, then it is definitively a bug...
I'll try to add this to my todo list, but I can not guarantee anything soon. If someone else can confirm and fix this, I'll be happy.
Cheers,
Benjamin
----- Original Message -----
From: "case" <case@corpsmoderne.net>
To: "Benjamin Tissoires" <benjamin.tissoires@redhat.com>
Sent: Friday, October 25, 2013 8:52:14 AM
Subject: About the PS3 Sixaxis linux driver
Hello Benjamin,
I'm mailing you because it seems you're one of the kernel developers
the most involved with the hid-sony.c driver lately, with which I think
I've an issue. If you feel like I'm mailing the wrong person,
I apologize, and would be glad if you could point me to the right
person.
I'm a game developer experimenting with the sixaxis for a while, and
I've a big issue with the current state of the driver:
On the sixaxis all the buttons (except select and start) are mapped
as buttons but also as axis, which is pretty rad. That was working great
in 2010 when I started to experiment with the sixaxis but in more
recent versions of the kernel, one the the buttons has lost his axis.
It's the left button the the D-PAD, witch is only mapped as button 7
(up is button 4 and axis 8, right is button 5 axis 9, bottom is button
6 axis 10).
This is quite inconsistent and makes impossible to rely on the axis for
all the D-PAD buttons.
Again, this bug wasn't there in 2.6.32 . I noticed it for the first time
in 3.5.x . I'm currently running 3.11.0 and this bug is still here.
As my experience with kernel hacking is minimal I'm not even sure
the problem lies in hid-sony, but that's where my investigations lead
me.
Thank you to have taken the time to read my mail, I hope it will help
to fix this issue, and again, sorry if you're not the right person to
write to.
Regards,
--
Marc Planard
^ permalink raw reply
* Re: About the PS3 Sixaxis linux driver
From: simon @ 2013-11-04 21:07 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: case, linux-input
In-Reply-To: <1256411740.1745741.1383597450835.JavaMail.root@redhat.com>
> Hi Marc,
>
> (adding in CC the linux-input mailing list)
>
> Regarding your problem I vaguely remember something about not having
> duplicated axis with the buttons. My memory is rather confuse about this,
> so I may be wrong (but others on the list may have a fresher memory).
> Other than that, if only one axis is not working, then it is definitively
> a bug...
>
> I'll try to add this to my todo list, but I can not guarantee anything
> soon. If someone else can confirm and fix this, I'll be happy.
There was something a couple of years ago with the multi-touch stuff
screening out HID reports for the D-Pad axis.
http://comments.gmane.org/gmane.linux.kernel.input/19632
Don't know the current situation,
Simon
^ permalink raw reply
* Re: About the PS3 Sixaxis linux driver
From: Antonio Ospite @ 2013-11-04 21:18 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: case, linux-input
In-Reply-To: <1256411740.1745741.1383597450835.JavaMail.root@redhat.com>
On Mon, 4 Nov 2013 15:37:30 -0500 (EST)
Benjamin Tissoires <btissoir@redhat.com> wrote:
> Hi Marc,
>
> (adding in CC the linux-input mailing list)
>
> Regarding your problem I vaguely remember something about not having duplicated axis with the buttons. My memory is rather confuse about this, so I may be wrong (but others on the list may have a fresher memory).
> Other than that, if only one axis is not working, then it is definitively a bug...
>
The problem with the left D-PAD should be the one I talk about here:
http://www.spinics.net/lists/linux-input/msg16881.html
Basically the keycode is a multi-touch one and it gets discarded being
the device not a MT one.
I was told the hack I came up with is not OK for mainline, but people
can apply it locally for the time being.
> I'll try to add this to my todo list, but I can not guarantee anything soon. If someone else can confirm and fix this, I'll be happy.
>
Will remapping just the faulty keycode be enough?
Actually I intended to rewrite the whole HID descriptor and add a sane
mapping for all the buttons (maybe following the Gamepad API and
even using the new ABS_ACCEL_* and ABS_GYRO_* events from David
Hermann).
I may try to do some work along these lines myself in the next weeks
but I cannot promise an ETA either.
Marc, if you need the latest BlueZ patches for pairing the sixaxis for
BT operation just let me know.
Ciao,
Antonio
> Cheers,
> Benjamin
>
> ----- Original Message -----
> From: "case" <case@corpsmoderne.net>
> To: "Benjamin Tissoires" <benjamin.tissoires@redhat.com>
> Sent: Friday, October 25, 2013 8:52:14 AM
> Subject: About the PS3 Sixaxis linux driver
>
> Hello Benjamin,
>
> I'm mailing you because it seems you're one of the kernel developers
> the most involved with the hid-sony.c driver lately, with which I think
> I've an issue. If you feel like I'm mailing the wrong person,
> I apologize, and would be glad if you could point me to the right
> person.
>
> I'm a game developer experimenting with the sixaxis for a while, and
> I've a big issue with the current state of the driver:
>
> On the sixaxis all the buttons (except select and start) are mapped
> as buttons but also as axis, which is pretty rad. That was working great
> in 2010 when I started to experiment with the sixaxis but in more
> recent versions of the kernel, one the the buttons has lost his axis.
> It's the left button the the D-PAD, witch is only mapped as button 7
> (up is button 4 and axis 8, right is button 5 axis 9, bottom is button
> 6 axis 10).
>
> This is quite inconsistent and makes impossible to rely on the axis for
> all the D-PAD buttons.
>
> Again, this bug wasn't there in 2.6.32 . I noticed it for the first time
> in 3.5.x . I'm currently running 3.11.0 and this bug is still here.
>
> As my experience with kernel hacking is minimal I'm not even sure
> the problem lies in hid-sony, but that's where my investigations lead
> me.
>
> Thank you to have taken the time to read my mail, I hope it will help
> to fix this issue, and again, sorry if you're not the right person to
> write to.
>
> Regards,
> --
> Marc Planard
> --
> 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
>
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* Re: About the PS3 Sixaxis linux driver
From: simon @ 2013-11-04 21:40 UTC (permalink / raw)
To: Antonio Ospite; +Cc: Benjamin Tissoires, case, linux-input
In-Reply-To: <20131104221824.2bd181e60f01f41e1e4f4898@studenti.unina.it>
> Actually I intended to rewrite the whole HID descriptor and add a sane
> mapping for all the buttons (maybe following the Gamepad API and
> even using the new ABS_ACCEL_* and ABS_GYRO_* events from David
> Hermann).
I think that the root of the problem here is simply the large number of
axis, and that the keycodes start at 'axis-x' then overflow into/past the
MultiTouch keycode.
This problem is going to be a more common one as HID drivers present more
buttons/axis.
We did some patching here:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/hid/hid-sony.c?id=refs/tags/v3.12#n301
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/hid/hid-sony.c?id=61ab44bebdefab296487e7cd723a634849278827
Do we need to fix this is the HID descriptor, or in 'hid-sony' input stuff?
Do you have example of another driver to copy?
Simon
^ permalink raw reply
* Re: About the PS3 Sixaxis linux driver
From: Marc @ 2013-11-04 23:03 UTC (permalink / raw)
To: Antonio Ospite, Benjamin Tissoires; +Cc: linux-input
In-Reply-To: <20131104221824.2bd181e60f01f41e1e4f4898@studenti.unina.it>
Thanks a lot Benjamin (and everyone) to handle this.
Just to let you know, I've updated from 3.5 to 3.11
(basically, from stock ubuntu-12.04 to stock ubuntu-13.10)
and the bug is still there.
On 11/04/2013 10:18 PM, Antonio Ospite wrote:
> The problem with the left D-PAD should be the one I talk about here:
> http://www.spinics.net/lists/linux-input/msg16881.html
I'll try that as soon as possible, but as you noted, it's not a viable
solution for the long term...
> Marc, if you need the latest BlueZ patches for pairing the sixaxis for
> BT operation just let me know.
I forgot to say I've only tested through tethered USB. I'm not even
sure to have a functioning BT host :) but thanks for the proposal.
On 11/04/2013 10:40 PM, simon@mungewell.org wrote:
> We did some patching here:
>
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/hid/hid-sony.c?id=refs/tags/v3.12#n301
>
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/hid/hid-sony.c?id=61ab44bebdefab296487e7cd723a634849278827
The kernel I'm currently running (ubuntu-saucy) includes this patch.
Also, I'm not very good at this, but I've made a diff of the last
version of hid-sony.c and the version currently in ubuntu-saucy (3.11) :
the changes are minimal and can't have fixed the bug (see bellow).
$ diff hid-sony.c ~/ubuntu-saucy/drivers/hid/hid-sony.c
631c631
< sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
---
> sc = kzalloc(sizeof(*sc), GFP_KERNEL);
643c643
< return ret;
---
> goto err_free;
656c656
< return ret;
---
> goto err_free;
675a676,677
> err_free:
> kfree(sc);
686a689
> kfree(sc);
--
Marc
^ permalink raw reply
* Re: incorrect determination of the USB-sound card
From: Sohin Vyacheslaw @ 2013-11-05 6:30 UTC (permalink / raw)
To: linux-input@vger.kernel.org
In-Reply-To: <52775A40.9050209@yandex.ua>
can anybody explain why the usb soundcard is defined as a voip phone in Linux or do I need another mailing list?
--
Best wishes,
Sohin Vyacheslav
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox