* Re: hid-sony patch to add rumble and led support for nyko core controllers
[not found] <CANksHftPp87NMpaFEF=2zz4MiPv2DwLiLUqpDYm-B94ErYUXeQ@mail.gmail.com>
@ 2015-12-09 1:34 ` Dmitry Torokhov
0 siblings, 0 replies; only message in thread
From: Dmitry Torokhov @ 2015-12-09 1:34 UTC (permalink / raw)
To: Scott Moreau; +Cc: Frank Praznik, Antonio Ospite, Jiri Kosina, Linux Input
Hi Scott,
On Tue, Dec 08, 2015 at 03:05:54AM -0700, Scott Moreau wrote:
> Hi Dimtry,
>
> I managed to get rumble and led's sorted out for the nyko core controller
> with this patch. The code probably isn't the greatest but do you think you
> might be able to help me get it cleaned up and submitted? Thanks in advance
> for your time, you're awesome!
I do not normally work in HID components, so I added a few people who
do. Also please find some random comments below.
>
> - Scott
>
>
>
> From 2ed82af9ebe6fd09c13c30352bf5bb53bffc80ea Mon Sep 17 00:00:00 2001
> From: Scott Moreau <oreaus@gmail.com>
> Date: Tue, 8 Dec 2015 02:58:59 -0700
> Subject: [PATCH] HID: sony: Add rumble and LED support for Nyko Core
> Controller
>
> The Nyko Core Controller, vendor:1345 product:3008, is a usb controller
> marketed
> as a PS3 controller. It works as an HID device for input. It has a single
> left
> rumble motor and no accelerometers, so it isn't a sixaxis. This patch adds
> rumble
> and led support in the hid-sony driver.
> ---
> drivers/hid/hid-core.c | 1 +
> drivers/hid/hid-ids.h | 3 ++
> drivers/hid/hid-sony.c | 109
> ++++++++++++++++++++++++++++++++++++++++++++++---
> 3 files changed, 107 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index c6f7a69..bcaf96e 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -2008,6 +2008,7 @@ static const struct hid_device_id
> hid_have_special_driver[] = {
> { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY,
> USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
> { HID_USB_DEVICE(USB_VENDOR_ID_SONY,
> USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
> { HID_USB_DEVICE(USB_VENDOR_ID_SONY,
> USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
> + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE,
> USB_DEVICE_ID_SINO_LITE_CONTROLLER) },
> { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
> USB_DEVICE_ID_STEELSERIES_SRWS1) },
> { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS,
> USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
> { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 9024a3d..3ce4817 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -874,6 +874,9 @@
> #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
> #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000
>
> +#define USB_VENDOR_ID_SINO_LITE 0x1345
> +#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008
> +
> #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-sony.c b/drivers/hid/hid-sony.c
> index 774cd22..1ac13fe 100644
> --- a/drivers/hid/hid-sony.c
> +++ b/drivers/hid/hid-sony.c
> @@ -50,6 +50,7 @@
> #define MOTION_CONTROLLER_BT BIT(8)
> #define NAVIGATION_CONTROLLER_USB BIT(9)
> #define NAVIGATION_CONTROLLER_BT BIT(10)
> +#define NYKO_CORE_CONTROLLER BIT(11)
>
> #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
> #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
> @@ -59,11 +60,11 @@
> DUALSHOCK4_CONTROLLER_BT)
> #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
> DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
> - NAVIGATION_CONTROLLER)
> + NAVIGATION_CONTROLLER | NYKO_CORE_CONTROLLER)
> #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
> MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
> #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
> - MOTION_CONTROLLER)
> + MOTION_CONTROLLER | NYKO_CORE_CONTROLLER)
>
> #define MAX_LEDS 4
>
> @@ -1002,6 +1003,28 @@ union sixaxis_output_report_01 {
> __u8 buf[36];
> };
>
> +struct nyko_rumble {
> + __u8 right_duration; /* Right motor duration (0xff means forever) */
> + __u8 right_motor_on; /* Right (small) motor on/off, only supports
> values of 0 or 1 (off/on) */
> + __u8 left_duration; /* Left motor duration (0xff means forever) */
> + __u8 left_motor_force; /* left (large) motor, supports force values
> from 0 to 255 */
Usually in pure kernel code we use names without underscores (u8). I see
this driver uses mix of both, would be nice to convert to the same
style.
Also I am not sure if it is your mailer or not, we you need to indent
with tabs. I assume it is your mailer as the patch is also
line-wrapped.
> +} __packed;
> +
> +struct nyko_output_report {
> + __u8 report_id;
> + struct nyko_rumble rumble;
> + __u8 padding[4];
> + __u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 =
> 0x04, ... */
> + struct sixaxis_led led[4]; /* LEDx at (4 - x) */
> + struct sixaxis_led _reserved; /* LED5, not actually soldered */
> + __u8 pad;
> +} __packed;
> +
> +union nyko_output_report_01 {
> + struct nyko_output_report data;
> + __u8 buf[36];
> +};
> +
> struct motion_output_report_02 {
> u8 type, zero;
> u8 r, g, b;
> @@ -1116,6 +1139,9 @@ static __u8 *sony_report_fixup(struct hid_device
> *hdev, __u8 *rdesc,
> {
> struct sony_sc *sc = hid_get_drvdata(hdev);
>
> + if (sc->quirks & NYKO_CORE_CONTROLLER)
> + return rdesc;
> +
> /*
> * Some Sony RF receivers wrongly declare the mouse pointer as a
> * a constant non-data variable.
> @@ -1393,6 +1419,7 @@ static int sixaxis_set_operational_usb(struct
> hid_device *hdev)
> const int buf_size =
> max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
> __u8 *buf;
> + struct sony_sc *sc = hid_get_drvdata(hdev);
> int ret;
>
> buf = kmalloc(buf_size, GFP_KERNEL);
> @@ -1406,6 +1433,9 @@ static int sixaxis_set_operational_usb(struct
> hid_device *hdev)
> goto out;
> }
>
> + if (sc->quirks & NYKO_CORE_CONTROLLER)
> + goto out;
> +
> /*
> * Some compatible controllers like the Speedlink Strike FX and
> * Gasia need another query plus an USB interrupt to get operational.
> @@ -1568,7 +1598,8 @@ static void sony_led_set_brightness(struct
> led_classdev *led,
> * controller to avoid having to toggle the state of an LED just to
> * stop the flashing later on.
> */
> - force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
> + force_update = !!((drv_data->quirks & SIXAXIS_CONTROLLER_USB) ||
> + (drv_data->quirks & NYKO_CORE_CONTROLLER));
You do not need double negate (!!) result of logical operation, it is
already boolean. Although you could also write the condition as:
force_update = !!(drv_data->quirks &
(SIXAXIS_CONTROLLER_USB |
NYKO_CORE_CONTROLLER));
>
> for (n = 0; n < drv_data->led_count; n++) {
> if (led == drv_data->leds[n] && (force_update ||
> @@ -1803,6 +1834,7 @@ static void sixaxis_state_worker(struct work_struct
> *work)
> 0x00, 0x00, 0x00, 0x00, 0x00
> }
> };
> +
> struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
> struct sixaxis_output_report *report =
> (struct sixaxis_output_report *)sc->output_report_dmabuf;
> @@ -1846,6 +1878,62 @@ static void sixaxis_state_worker(struct work_struct
> *work)
> HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
> }
>
> +static void nyko_state_worker(struct work_struct *work)
> +{
> + static const union nyko_output_report_01 default_report = {
> + .buf = {
> + 0x01,
> + 0x00, 0x00, 0x00, 0x00, 0x00,
> + 0x00, 0x00, 0x00, 0x00, 0xff,
> + 0x30, 0x27, 0x30, 0x30, 0xff,
> + 0x30, 0x27, 0x30, 0x30, 0xff,
> + 0x30, 0x27, 0x30, 0x30, 0xff,
> + 0x30, 0x27, 0x30, 0x30, 0x00,
> + 0x00, 0x00, 0x00, 0x00, 0x00
> + }
> + };
> +
> + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
> + struct nyko_output_report *report =
> + (struct nyko_output_report *)sc->output_report_dmabuf;
> + int n;
> +
> + /* Initialize the report with default values */
> + memcpy(report, &default_report, sizeof(struct nyko_output_report));
> +
> +#ifdef CONFIG_SONY_FF
> + report->rumble.left_motor_force = (sc->right / 2) + (sc->left * 2);
> + report->rumble.right_duration = 0x00;
> + report->rumble.left_duration = 0xff;
> +#endif
> +
> + report->leds_bitmap |= sc->led_state[0] << 1;
> + report->leds_bitmap |= sc->led_state[1] << 2;
> + report->leds_bitmap |= sc->led_state[2] << 3;
> + report->leds_bitmap |= sc->led_state[3] << 4;
> +
> + /*
> + * The LEDs in the report are indexed in reverse order to their
> + * corresponding light on the controller.
> + * Index 0 = LED 4, index 1 = LED 3, etc...
> + *
> + * In the case of both delay values being zero (blinking disabled) the
> + * default report values should be used or the controller LED will be
> + * always off.
> + */
> + for (n = 0; n < 4; n++) {
> + if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
> + report->led[3 - n].duty_off = sc->led_delay_off[n];
> + report->led[3 - n].duty_on = sc->led_delay_on[n];
> + }
> + }
> +
> + hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report,
> + sizeof(struct nyko_output_report),
> + HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
> +
> +}
> +
> static void dualshock4_state_worker(struct work_struct *work)
> {
> struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
> @@ -1917,7 +2005,8 @@ static void motion_state_worker(struct work_struct
> *work)
> static int sony_allocate_output_report(struct sony_sc *sc)
> {
> if ((sc->quirks & SIXAXIS_CONTROLLER) ||
> - (sc->quirks & NAVIGATION_CONTROLLER))
> + (sc->quirks & NAVIGATION_CONTROLLER) ||
> + (sc->quirks & NYKO_CORE_CONTROLLER))
> sc->output_report_dmabuf =
> kmalloc(sizeof(union sixaxis_output_report_01),
> GFP_KERNEL);
> @@ -2170,7 +2259,8 @@ static int sony_check_add(struct sony_sc *sc)
>
> memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
> } else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
> - (sc->quirks & NAVIGATION_CONTROLLER_USB)) {
> + (sc->quirks & NAVIGATION_CONTROLLER_USB) ||
> + (sc->quirks & NYKO_CORE_CONTROLLER)) {
> buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
> if (!buf)
> return -ENOMEM;
> @@ -2218,7 +2308,8 @@ static int sony_set_device_id(struct sony_sc *sc)
> * All others are set to -1.
> */
> if ((sc->quirks & SIXAXIS_CONTROLLER) ||
> - (sc->quirks & DUALSHOCK4_CONTROLLER)) {
> + (sc->quirks & DUALSHOCK4_CONTROLLER) ||
> + (sc->quirks & NYKO_CORE_CONTROLLER)) {
> ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
> GFP_KERNEL);
> if (ret < 0) {
> @@ -2320,6 +2411,9 @@ static int sony_probe(struct hid_device *hdev, const
> struct hid_device_id *id)
> hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
> ret = sixaxis_set_operational_usb(hdev);
> sony_init_work(sc, sixaxis_state_worker);
> + } else if (sc->quirks & NYKO_CORE_CONTROLLER) {
> + ret = sixaxis_set_operational_usb(hdev);
> + sony_init_work(sc, nyko_state_worker);
> } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
> (sc->quirks & NAVIGATION_CONTROLLER_BT)) {
> /*
> @@ -2458,6 +2552,9 @@ static const struct hid_device_id sony_devices[] = {
> .driver_data = DUALSHOCK4_CONTROLLER_USB },
> { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY,
> USB_DEVICE_ID_SONY_PS4_CONTROLLER),
> .driver_data = DUALSHOCK4_CONTROLLER_BT },
> + /* Nyko Core Controller for PS3 */
> + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE,
> USB_DEVICE_ID_SINO_LITE_CONTROLLER),
> + .driver_data = NYKO_CORE_CONTROLLER },
> { }
> };
> MODULE_DEVICE_TABLE(hid, sony_devices);
> --
> 2.5.0
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2015-12-09 1:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CANksHftPp87NMpaFEF=2zz4MiPv2DwLiLUqpDYm-B94ErYUXeQ@mail.gmail.com>
2015-12-09 1:34 ` hid-sony patch to add rumble and led support for nyko core controllers Dmitry Torokhov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).