2015-06-10 03:27:27

by Simon Wood

[permalink] [raw]
Subject: [PATCH 1/4] HID: hid-sony: Add quirk for MOTION_CONTROLLER_BT

Split quirk for PS Move Controller as it has to be treated differently
when connected via BT.

Signed-off-by: Simon Wood <[email protected]>
---
drivers/hid/hid-sony.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 6fcc2b4..28dba6c 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -46,9 +46,11 @@
#define PS3REMOTE BIT(4)
#define DUALSHOCK4_CONTROLLER_USB BIT(5)
#define DUALSHOCK4_CONTROLLER_BT BIT(6)
-#define MOTION_CONTROLLER BIT(7)
+#define MOTION_CONTROLLER_USB BIT(7)
+#define MOTION_CONTROLLER_BT BIT(8)

#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
+#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
#define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
DUALSHOCK4_CONTROLLER_BT)
#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
@@ -2261,9 +2263,9 @@ static const struct hid_device_id sony_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
.driver_data = SIXAXIS_CONTROLLER_USB },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
- .driver_data = MOTION_CONTROLLER },
+ .driver_data = MOTION_CONTROLLER_USB },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
- .driver_data = MOTION_CONTROLLER },
+ .driver_data = MOTION_CONTROLLER_BT },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
.driver_data = SIXAXIS_CONTROLLER_BT },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
--
2.1.4


2015-06-10 03:27:36

by Simon Wood

[permalink] [raw]
Subject: [PATCH 2/4] HID_ hid-sony_ Add support PS3 Move Battery via BT

Add support for the battery charge level and state to be read via BT.

This is not support via USB as there is no know way to get the device
sending 'input' reports over USB.

Signed-off-by: Simon Wood <[email protected]>
---
drivers/hid/hid-sony.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 28dba6c..d9fa804 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -55,7 +55,8 @@
DUALSHOCK4_CONTROLLER_BT)
#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER)
-#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
+#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
+ MOTION_CONTROLLER_BT)
#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
MOTION_CONTROLLER)

@@ -1041,6 +1042,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
{
static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
unsigned long flags;
+ int offset;
__u8 cable_state, battery_capacity, battery_charging;

/*
@@ -1049,12 +1051,14 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
* It does not report the actual level while charging so it
* is set to 100% while charging is in progress.
*/
- if (rd[30] >= 0xee) {
+ offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
+
+ if (rd[offset] >= 0xee) {
battery_capacity = 100;
- battery_charging = !(rd[30] & 0x01);
+ battery_charging = !(rd[offset] & 0x01);
cable_state = 1;
} else {
- __u8 index = rd[30] <= 5 ? rd[30] : 5;
+ __u8 index = rd[offset] <= 5 ? rd[offset] : 5;
battery_capacity = sixaxis_battery_capacity[index];
battery_charging = 0;
cable_state = 0;
@@ -1155,6 +1159,8 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
swap(rd[47], rd[48]);

sixaxis_parse_report(sc, rd, size);
+ } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
+ sixaxis_parse_report(sc, rd, size);
} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
&& rd[0] == 0x11 && size == 78)) {
@@ -1976,6 +1982,7 @@ static int sony_check_add(struct sony_sc *sc)
int n, ret;

if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
+ (sc->quirks & MOTION_CONTROLLER_BT) ||
(sc->quirks & SIXAXIS_CONTROLLER_BT)) {
/*
* sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
--
2.1.4

2015-06-10 03:28:04

by Simon Wood

[permalink] [raw]
Subject: [PATCH 3/4] HID: hid-sony: PS3 Move enable LEDs and Rumble via BT

The LED and Rumble control only function via BT if the full output report
is sent. The large report still functions via USB.

Signed-off-by: Simon Wood <[email protected]>
---
drivers/hid/hid-sony.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index d9fa804..51cb1ac 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -902,6 +902,7 @@ struct motion_output_report_02 {
#define DS4_REPORT_0x81_SIZE 7
#define SIXAXIS_REPORT_0xF2_SIZE 17
#define SIXAXIS_REPORT_0xF5_SIZE 8
+#define MOTION_REPORT_0x02_SIZE 49

static DEFINE_SPINLOCK(sony_dev_list_lock);
static LIST_HEAD(sony_device_list);
@@ -1746,7 +1747,7 @@ static void motion_state_worker(struct work_struct *work)
struct motion_output_report_02 *report =
(struct motion_output_report_02 *)sc->output_report_dmabuf;

- memset(report, 0, sizeof(struct motion_output_report_02));
+ memset(report, 0, MOTION_REPORT_0x02_SIZE);

report->type = 0x02; /* set leds */
report->r = sc->led_state[0];
@@ -1757,8 +1758,7 @@ static void motion_state_worker(struct work_struct *work)
report->rumble = max(sc->right, sc->left);
#endif

- hid_hw_output_report(hdev, (__u8 *)report,
- sizeof(struct motion_output_report_02));
+ hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
}

static int sony_allocate_output_report(struct sony_sc *sc)
@@ -1774,9 +1774,8 @@ static int sony_allocate_output_report(struct sony_sc *sc)
sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
GFP_KERNEL);
else if (sc->quirks & MOTION_CONTROLLER)
- sc->output_report_dmabuf =
- kmalloc(sizeof(struct motion_output_report_02),
- GFP_KERNEL);
+ sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
+ GFP_KERNEL);
else
return 0;

--
2.1.4

2015-06-10 03:27:50

by Simon Wood

[permalink] [raw]
Subject: [PATCH 4/4] HID: hid-sony: PS Move fix report descriptor

Fix the report descriptor so that the buttons and trigger are correctly reported.

The format of the input report is described here:
https://github.com/nitsch/moveonpc/wiki/Input-report

The Accelerometers and Gyros (1st frame only) are also reported as axis, but
the Magnetometers are NOT as 'fixing' their byte order would break user-space
drivers such as PSMoveAPI.

It is hoped to resolve this at a future time.

Signed-off-by: Simon Wood <[email protected]>
---
drivers/hid/hid-sony.c | 69 ++++++++++++++++++++++++++++++++------------------
1 file changed, 44 insertions(+), 25 deletions(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 51cb1ac..2ce0295 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -153,52 +153,71 @@ static __u8 motion_rdesc[] = {
0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */
0x85, 0x01, /* Report ID (1), */
- 0x75, 0x08, /* Report Size (8), */
- 0x95, 0x01, /* Report Count (1), */
- 0x15, 0x00, /* Logical Minimum (0), */
- 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
- 0x81, 0x03, /* Input (Constant, Variable), */
0x75, 0x01, /* Report Size (1), */
- 0x95, 0x13, /* Report Count (19), */
+ 0x95, 0x15, /* Report Count (21), */
0x15, 0x00, /* Logical Minimum (0), */
0x25, 0x01, /* Logical Maximum (1), */
0x35, 0x00, /* Physical Minimum (0), */
0x45, 0x01, /* Physical Maximum (1), */
0x05, 0x09, /* Usage Page (Button), */
0x19, 0x01, /* Usage Minimum (01h), */
- 0x29, 0x13, /* Usage Maximum (13h), */
- 0x81, 0x02, /* Input (Variable), */
- 0x75, 0x01, /* Report Size (1), */
- 0x95, 0x0D, /* Report Count (13), */
+ 0x29, 0x15, /* Usage Maximum (15h), */
+ 0x81, 0x02, /* Input (Variable), * Buttons */
+ 0x95, 0x0B, /* Report Count (11), */
0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
- 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x81, 0x03, /* Input (Constant, Variable), * Padding */
0x15, 0x00, /* Logical Minimum (0), */
0x26, 0xFF, 0x00, /* Logical Maximum (255), */
0x05, 0x01, /* Usage Page (Desktop), */
- 0x09, 0x01, /* Usage (Pointer), */
0xA1, 0x00, /* Collection (Physical), */
0x75, 0x08, /* Report Size (8), */
- 0x95, 0x04, /* Report Count (4), */
+ 0x95, 0x01, /* Report Count (1), */
0x35, 0x00, /* Physical Minimum (0), */
0x46, 0xFF, 0x00, /* Physical Maximum (255), */
0x09, 0x30, /* Usage (X), */
- 0x09, 0x31, /* Usage (Y), */
- 0x09, 0x32, /* Usage (Z), */
- 0x09, 0x35, /* Usage (Rz), */
- 0x81, 0x02, /* Input (Variable), */
+ 0x81, 0x02, /* Input (Variable), * Trigger */
0xC0, /* End Collection, */
- 0x05, 0x01, /* Usage Page (Desktop), */
- 0x95, 0x13, /* Report Count (19), */
- 0x09, 0x01, /* Usage (Pointer), */
+ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x07, /* Report Count (7), * skip 7 bytes */
0x81, 0x02, /* Input (Variable), */
- 0x95, 0x0C, /* Report Count (12), */
- 0x81, 0x01, /* Input (Constant), */
+ 0x05, 0x01, /* Usage Page (Desktop), */
0x75, 0x10, /* Report Size (16), */
- 0x95, 0x04, /* Report Count (4), */
- 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
- 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */
+ 0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */
+ 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */
+ 0x95, 0x03, /* Report Count (3), * 3x Accels */
+ 0x09, 0x33, /* Usage (rX), */
+ 0x09, 0x34, /* Usage (rY), */
+ 0x09, 0x35, /* Usage (rZ), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+ 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x01, /* Usage (Pointer), */
+ 0x95, 0x03, /* Report Count (3), * 3x Gyros */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+ 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */
0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x0C, /* Report Size (12), */
+ 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */
+ 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */
+ 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+ 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x30, /* Report Count (48), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0x91, 0x02, /* Output (Variable), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x30, /* Report Count (48), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0xA1, 0x02, /* Collection (Logical), */
0x85, 0x02, /* Report ID (2), */
--
2.1.4

2015-06-12 11:15:21

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH 1/4] HID: hid-sony: Add quirk for MOTION_CONTROLLER_BT

On Tue, 9 Jun 2015, Simon Wood wrote:

> Split quirk for PS Move Controller as it has to be treated differently
> when connected via BT.

I have applied the series.

Thanks,

--
Jiri Kosina
SUSE Labs