Re: hid-sony patch to add rumble and led support for nyko core controllers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux