From: Jason Flatt <jflatt@cox.net>
To: linux-input@vger.kernel.org
Subject: [PATCH] Support for Sony NSG-MR5U
Date: Wed, 19 Jun 2013 23:43:38 -0700 [thread overview]
Message-ID: <1497744.kpqTRKsYBt@desktop> (raw)
[-- Attachment #1: Type: text/plain, Size: 345 bytes --]
Hello,
This is a patch for Sony's GoogleTV multitouch bluetooth remotes, it adds into
the shared hid-sony module, and is based on the methods used in the apple
magicmouse module. It builds against the 3.9.0 git tree at:
git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
Please let me know how it looks, this is my first patch.
Thank you
[-- Attachment #2: nsgmr5u.patch --]
[-- Type: text/x-patch, Size: 9647 bytes --]
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 512b01c..a61d9dc 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1701,6 +1701,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY_TOUCH_REMOTE, USB_DEVICE_ID_SONY_TOUCH_REMOTE_LYRA) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY_TOUCH_REMOTE, USB_DEVICE_ID_SONY_TOUCH_REMOTE_LEO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 92e47e5..fd85e26 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -723,6 +723,10 @@
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
+#define USB_VENDOR_ID_SONY_TOUCH_REMOTE 0x0609
+#define USB_DEVICE_ID_SONY_TOUCH_REMOTE_LYRA 0x0368
+#define USB_DEVICE_ID_SONY_TOUCH_REMOTE_LEO 0x0369
+
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 7a1ebb8..53b3eb9 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1180,6 +1180,14 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
+ /* Sony CE Remote */
+ { .driver_data = MT_CLS_DEFAULT,
+ MT_BT_DEVICE(USB_VENDOR_ID_SONY_TOUCH_REMOTE,
+ USB_DEVICE_ID_SONY_TOUCH_REMOTE_LYRA) },
+ { .driver_data = MT_CLS_DEFAULT,
+ MT_BT_DEVICE(USB_VENDOR_ID_SONY_TOUCH_REMOTE,
+ USB_DEVICE_ID_SONY_TOUCH_REMOTE_LEO) },
+
/* Stantum panels */
{ .driver_data = MT_CLS_CONFIDENCE,
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM,
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 312098e..44e81f8 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -6,6 +6,7 @@
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
* Copyright (c) 2008 Jiri Slaby
* Copyright (c) 2006-2008 Jiri Kosina
+ * Copyright (c) 2013 Jason Flatt <jflatt@cox.net>
*/
/*
@@ -17,6 +18,7 @@
#include <linux/device.h>
#include <linux/hid.h>
+#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/usb.h>
@@ -26,6 +28,17 @@
#define VAIO_RDESC_CONSTANT (1 << 0)
#define SIXAXIS_CONTROLLER_USB (1 << 1)
#define SIXAXIS_CONTROLLER_BT (1 << 2)
+#define CE_REMOTE_BT (1 << 4)
+
+/* measured on real hardware */
+#define CE_REMOTE_MIN_X 0
+#define CE_REMOTE_MAX_X 1667
+#define CE_REMOTE_SIZE_X (float)48 /* size in mm */
+#define CE_REMOTE_MIN_Y 0
+#define CE_REMOTE_MAX_Y 1868
+#define CE_REMOTE_SIZE_Y (float)51
+#define CE_REMOTE_RES_X ((CE_REMOTE_MAX_X - CE_REMOTE_MIN_X) / CE_REMOTE_SIZE_X)
+#define CE_REMOTE_RES_Y ((CE_REMOTE_MAX_Y - CE_REMOTE_MIN_Y) / CE_REMOTE_SIZE_Y)
static const u8 sixaxis_rdesc_fixup[] = {
0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
@@ -57,6 +70,7 @@ static const u8 sixaxis_rdesc_fixup2[] = {
struct sony_sc {
unsigned long quirks;
+ struct input_dev *input;
};
/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
@@ -94,10 +108,27 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize, (int)sizeof(sixaxis_rdesc_fixup2));
*rsize = sizeof(sixaxis_rdesc_fixup2);
memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
+ } else if ((sc->quirks & CE_REMOTE_BT) && *rsize == 359 &&
+ rdesc[358] == 0x0) {
+ hid_info(hdev, "Fixing up Sony CE Remote report descriptor\n");
+ *rsize = 358;
}
return rdesc;
}
+static int sony_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct sony_sc *sc = hid_get_drvdata(hdev);
+ if (sc->quirks & CE_REMOTE_BT) {
+ if (!sc->input)
+ sc->input = hi->input;
+ }
+
+ return 0;
+}
+
static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
__u8 *rd, int size)
{
@@ -112,8 +143,55 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
swap(rd[43], rd[44]);
swap(rd[45], rd[46]);
swap(rd[47], rd[48]);
+ } else if (sc->quirks & CE_REMOTE_BT) {
+ struct input_dev *input = sc->input;
+ if (!input) {
+ hid_err(hdev, "Sony CE Remote no input data structure");
+ return 0;
+ }
+ if (rd[0] == 0x2) { /* report id = trackpad */
+ __u8 button0 = rd[1] & 0x1;
+ __u8 button2 = (rd[1] & 0x4) >> 2;
+ __u8 contact0 = (rd[1] & 0x30) >> 4;
+ __u8 contact1 = (rd[1] & 0xc0) >> 6;
+ __u16 touch0x = rd[2] | (rd[3] & 0xf) << 8;
+ __u16 touch0y = (rd[3] & 0xf0) >> 4 | rd[4] << 4;
+ __u8 touch0w = rd[5] & 0xf;
+ __u8 touch0h = (rd[5] & 0xf0) >> 4;
+ int8_t xrel = rd[6];
+ __u16 touch1x = rd[7] | (rd[8] & 0xf) << 8;
+ __u16 touch1y = (rd[8] & 0xf0) >> 4 | rd[9] << 4;
+ __u8 touch1w = rd[10] & 0xf;
+ __u8 touch1h = (rd[10] & 0xf0) >> 4;
+ int8_t yrel = rd[11];
+
+ input_mt_slot(input, 0);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, contact0);
+ /* flip Y-axis */
+ if (contact0) {
+ input_report_abs(input, ABS_MT_TOUCH_MAJOR, max(touch0w, touch0h));
+ input_report_abs(input, ABS_MT_TOUCH_MINOR, min(touch0w, touch0h));
+ input_report_abs(input, ABS_MT_ORIENTATION, (bool)(touch0w > touch0h));
+ input_report_abs(input, ABS_MT_POSITION_X, touch0x);
+ input_report_abs(input, ABS_MT_POSITION_Y, CE_REMOTE_MAX_Y - touch0y);
+ }
+ input_mt_slot(input, 1);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, contact1);
+ if (contact1) {
+ input_report_abs(input, ABS_MT_TOUCH_MAJOR, max(touch1w, touch1h));
+ input_report_abs(input, ABS_MT_TOUCH_MINOR, min(touch1w, touch1h));
+ input_report_abs(input, ABS_MT_ORIENTATION, (bool)(touch1w > touch1h));
+ input_report_abs(input, ABS_MT_POSITION_X, touch1x);
+ input_report_abs(input, ABS_MT_POSITION_Y, CE_REMOTE_MAX_Y - touch1y);
+ }
+ input_report_rel(input, REL_X, xrel);
+ input_report_rel(input, REL_Y, yrel);
+
+ input_report_key(input, BTN_MOUSE, button0 | button2);
+ input_mt_report_pointer_emulation(input, true);
+ }
+ input_sync(input);
}
-
return 0;
}
@@ -192,6 +270,43 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev)
return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
}
+static int ce_remote_setup_input(struct input_dev *input, struct hid_device *hdev)
+{
+ const int FUZZ = 4;
+ int error;
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(EV_REL, input->evbit);
+ __set_bit(EV_ABS, input->evbit);
+ __clear_bit(BTN_RIGHT, input->keybit);
+ __clear_bit(BTN_MIDDLE, input->keybit);
+ __set_bit(BTN_MOUSE, input->keybit);
+ __set_bit(BTN_TOOL_FINGER, input->keybit);
+ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ __set_bit(INPUT_PROP_POINTER, input->propbit);
+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
+ error = input_mt_init_slots(input, 2, 0);
+ if (error)
+ return error;
+
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 15, FUZZ, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 15, FUZZ, 0);
+ input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+
+ input_set_abs_params(input, ABS_X, CE_REMOTE_MIN_X, CE_REMOTE_MAX_X, FUZZ, 0);
+ input_set_abs_params(input, ABS_Y, CE_REMOTE_MIN_Y, CE_REMOTE_MAX_Y, FUZZ, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_X, CE_REMOTE_MIN_X, CE_REMOTE_MAX_X, FUZZ, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, CE_REMOTE_MIN_Y, CE_REMOTE_MAX_Y, FUZZ, 0);
+
+ input_abs_set_res(input, ABS_X, CE_REMOTE_RES_X);
+ input_abs_set_res(input, ABS_Y, CE_REMOTE_RES_Y);
+ input_abs_set_res(input, ABS_MT_POSITION_X, CE_REMOTE_RES_X);
+ input_abs_set_res(input, ABS_MT_POSITION_Y, CE_REMOTE_RES_Y);
+
+ return 0;
+}
+
static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
@@ -226,6 +341,15 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
ret = sixaxis_set_operational_bt(hdev);
+ else if (sc->quirks & CE_REMOTE_BT) {
+ if (sc->input) {
+ ret = ce_remote_setup_input(sc->input, hdev);
+ if (ret) {
+ hid_err(hdev, "Sony Touch Remote setup input failed (%d)\n", ret);
+ goto err_stop;
+ }
+ }
+ }
else
ret = 0;
@@ -257,6 +381,10 @@ static const struct hid_device_id sony_devices[] = {
.driver_data = VAIO_RDESC_CONSTANT },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
.driver_data = VAIO_RDESC_CONSTANT },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY_TOUCH_REMOTE, USB_DEVICE_ID_SONY_TOUCH_REMOTE_LYRA),
+ .driver_data = CE_REMOTE_BT },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY_TOUCH_REMOTE, USB_DEVICE_ID_SONY_TOUCH_REMOTE_LEO),
+ .driver_data = CE_REMOTE_BT },
{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);
@@ -266,6 +394,7 @@ static struct hid_driver sony_driver = {
.id_table = sony_devices,
.probe = sony_probe,
.remove = sony_remove,
+ .input_mapping = sony_input_mapping,
.report_fixup = sony_report_fixup,
.raw_event = sony_raw_event
};
next reply other threads:[~2013-06-20 6:54 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-20 6:43 Jason Flatt [this message]
2013-06-20 8:33 ` [PATCH] Support for Sony NSG-MR5U Benjamin Tissoires
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1497744.kpqTRKsYBt@desktop \
--to=jflatt@cox.net \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.