From 7b1998116bbb2f3e5dd6cb9a8ee6db479b0b50a9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 11 Nov 2013 22:41:56 +0100 Subject: ACPI / driver core: Store an ACPI device pointer in struct acpi_dev_node Modify struct acpi_dev_node to contain a pointer to struct acpi_device associated with the given device object (that is, its ACPI companion device) instead of an ACPI handle corresponding to it. Introduce two new macros for manipulating that pointer in a CONFIG_ACPI-safe way, ACPI_COMPANION() and ACPI_COMPANION_SET(), and rework the ACPI_HANDLE() macro to take the above changes into account. Drop the ACPI_HANDLE_SET() macro entirely and rework its users to use ACPI_COMPANION_SET() instead. For some of them who used to pass the result of acpi_get_child() directly to ACPI_HANDLE_SET() introduce a helper routine acpi_preset_companion() doing an equivalent thing. The main motivation for doing this is that there are things represented by struct acpi_device objects that don't have valid ACPI handles (so called fixed ACPI hardware features, such as power and sleep buttons) and we would like to create platform device objects for them and "glue" them to their ACPI companions in the usual way (which currently is impossible due to the lack of valid ACPI handles). However, there are more reasons why it may be useful. First, struct acpi_device pointers allow of much better type checking than void pointers which are ACPI handles, so it should be more difficult to write buggy code using modified struct acpi_dev_node and the new macros. Second, the change should help to reduce (over time) the number of places in which the result of ACPI_HANDLE() is passed to acpi_bus_get_device() in order to obtain a pointer to the struct acpi_device associated with the given "physical" device, because now that pointer is returned by ACPI_COMPANION() directly. Finally, the change should make it easier to write generic code that will build both for CONFIG_ACPI set and unset without adding explicit compiler directives to it. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Tested-by: Mika Westerberg # on Haswell Reviewed-by: Mika Westerberg Reviewed-by: Aaron Lu # for ATA and SDIO part --- drivers/hid/i2c-hid/i2c-hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index fd7ce374f812..b7ecc3623a43 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1012,7 +1012,7 @@ static int i2c_hid_probe(struct i2c_client *client, hid->hid_get_raw_report = i2c_hid_get_raw_report; hid->hid_output_raw_report = i2c_hid_output_raw_report; hid->dev.parent = &client->dev; - ACPI_HANDLE_SET(&hid->dev, ACPI_HANDLE(&client->dev)); + ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); hid->bus = BUS_I2C; hid->version = le16_to_cpu(ihid->hdesc.bcdVersion); hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); -- cgit v1.2.3 From 9fee8240cfd37081c88e2d84852c497ba18baeac Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sun, 17 Nov 2013 13:51:23 -0800 Subject: HID: usbkbd: fix inconsistent debugging output It looks like this typo was introduced by a mistake in a copy-and-paste in commit ddbe32491951. Signed-off-by: Adam Cozzette Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/usbkbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index 796086980f4a..9a332e683db7 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -146,7 +146,7 @@ static void usb_kbd_irq(struct urb *urb) input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); else hid_info(urb->dev, - "Unknown key (scancode %#x) released.\n", + "Unknown key (scancode %#x) pressed.\n", kbd->new[i]); } } -- cgit v1.2.3 From 92b5c411ab3a3441ccbf2053bc4b00eca6cc8c96 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:28 +0100 Subject: HID: sony: Rename rumble_* functions/variables to state_* The commands used to modify the rumble motor state also modifies the LEDs at the same time. The functionality used to modify this state in the driver has to be shared between the rumble and LED part. It is therefore better to replace the "rumble" part of the names with "state". Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 098af2f84b8c..28b847ad5458 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -226,7 +226,7 @@ struct sony_sc { unsigned long quirks; #ifdef CONFIG_SONY_FF - struct work_struct rumble_worker; + struct work_struct state_worker; struct hid_device *hdev; __u8 left; __u8 right; @@ -622,9 +622,9 @@ static void buzz_remove(struct hid_device *hdev) } #ifdef CONFIG_SONY_FF -static void sony_rumble_worker(struct work_struct *work) +static void sony_state_worker(struct work_struct *work) { - struct sony_sc *sc = container_of(work, struct sony_sc, rumble_worker); + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); unsigned char buf[] = { 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, @@ -655,7 +655,7 @@ static int sony_play_effect(struct input_dev *dev, void *data, sc->left = effect->u.rumble.strong_magnitude / 256; sc->right = effect->u.rumble.weak_magnitude ? 1 : 0; - schedule_work(&sc->rumble_worker); + schedule_work(&sc->state_worker); return 0; } @@ -667,7 +667,7 @@ static int sony_init_ff(struct hid_device *hdev) struct sony_sc *sc = hid_get_drvdata(hdev); sc->hdev = hdev; - INIT_WORK(&sc->rumble_worker, sony_rumble_worker); + INIT_WORK(&sc->state_worker, sony_state_worker); input_set_capability(input_dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(input_dev, NULL, sony_play_effect); @@ -677,7 +677,7 @@ static void sony_destroy_ff(struct hid_device *hdev) { struct sony_sc *sc = hid_get_drvdata(hdev); - cancel_work_sync(&sc->rumble_worker); + cancel_work_sync(&sc->state_worker); } #else -- cgit v1.2.3 From f1c458caa11430d30b3beae72d8ec9dfdce9c3ac Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:29 +0100 Subject: HID: sony: Use BIT(x) macro to define quirks constants Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 28b847ad5458..067729290012 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -33,11 +33,11 @@ #include "hid-ids.h" -#define VAIO_RDESC_CONSTANT (1 << 0) -#define SIXAXIS_CONTROLLER_USB (1 << 1) -#define SIXAXIS_CONTROLLER_BT (1 << 2) -#define BUZZ_CONTROLLER (1 << 3) -#define PS3REMOTE (1 << 4) +#define VAIO_RDESC_CONSTANT BIT(0) +#define SIXAXIS_CONTROLLER_USB BIT(1) +#define SIXAXIS_CONTROLLER_BT BIT(2) +#define BUZZ_CONTROLLER BIT(3) +#define PS3REMOTE BIT(4) static const u8 sixaxis_rdesc_fixup[] = { 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, -- cgit v1.2.3 From c53825190ac58d44d6ade6c6e6c8ad22f77ff954 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:30 +0100 Subject: HID: sony: Rename buzz_* functions to sony_led_* More controllers managed by the hid-sony module have 4 LEDs. These can share most of the functionality provided by the buzz functions. Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 067729290012..cdb24192db96 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -466,7 +466,7 @@ static void buzz_set_leds(struct hid_device *hdev, int leds) hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } -static void buzz_led_set_brightness(struct led_classdev *led, +static void sony_led_set_brightness(struct led_classdev *led, enum led_brightness value) { struct device *dev = led->dev->parent; @@ -498,7 +498,7 @@ static void buzz_led_set_brightness(struct led_classdev *led, } } -static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) +static enum led_brightness sony_led_get_brightness(struct led_classdev *led) { struct device *dev = led->dev->parent; struct hid_device *hdev = container_of(dev, struct hid_device, dev); @@ -525,7 +525,7 @@ static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) return on ? LED_FULL : LED_OFF; } -static int buzz_init(struct hid_device *hdev) +static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; struct buzz_extra *buzz; @@ -567,8 +567,8 @@ static int buzz_init(struct hid_device *hdev) led->name = name; led->brightness = 0; led->max_brightness = 1; - led->brightness_get = buzz_led_get_brightness; - led->brightness_set = buzz_led_set_brightness; + led->brightness_get = sony_led_get_brightness; + led->brightness_set = sony_led_set_brightness; if (led_classdev_register(&hdev->dev, led)) { hid_err(hdev, "Failed to register LED %d\n", n); @@ -596,7 +596,7 @@ error_leds: return ret; } -static void buzz_remove(struct hid_device *hdev) +static void sony_leds_remove(struct hid_device *hdev) { struct sony_sc *drv_data; struct buzz_extra *buzz; @@ -733,7 +733,7 @@ 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 & BUZZ_CONTROLLER) - ret = buzz_init(hdev); + ret = sony_leds_init(hdev); else ret = 0; @@ -755,7 +755,7 @@ static void sony_remove(struct hid_device *hdev) struct sony_sc *sc = hid_get_drvdata(hdev); if (sc->quirks & BUZZ_CONTROLLER) - buzz_remove(hdev); + sony_leds_remove(hdev); sony_destroy_ff(hdev); -- cgit v1.2.3 From 2251b85f3dfd7be140e2d6a1f9d1e78287367a4f Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:31 +0100 Subject: HID: sony: Move LED data to the main structure It is not necessary to keep the LED information in an extra struct which is only used by the Buzz device. It can also be used by other devices. Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 58 +++++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 41 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index cdb24192db96..2f93aab11056 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -223,6 +223,7 @@ static const unsigned int buzz_keymap[] = { }; struct sony_sc { + struct led_classdev *leds[4]; unsigned long quirks; #ifdef CONFIG_SONY_FF @@ -232,12 +233,7 @@ struct sony_sc { __u8 right; #endif - void *extra; -}; - -struct buzz_extra { - int led_state; - struct led_classdev *leds[4]; + __u8 led_state; }; static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, @@ -472,26 +468,24 @@ static void sony_led_set_brightness(struct led_classdev *led, struct device *dev = led->dev->parent; struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct sony_sc *drv_data; - struct buzz_extra *buzz; int n; drv_data = hid_get_drvdata(hdev); - if (!drv_data || !drv_data->extra) { + if (!drv_data) { hid_err(hdev, "No device data\n"); return; } - buzz = drv_data->extra; for (n = 0; n < 4; n++) { - if (led == buzz->leds[n]) { - int on = !! (buzz->led_state & (1 << n)); + if (led == drv_data->leds[n]) { + int on = !!(drv_data->led_state & (1 << n)); if (value == LED_OFF && on) { - buzz->led_state &= ~(1 << n); - buzz_set_leds(hdev, buzz->led_state); + drv_data->led_state &= ~(1 << n); + buzz_set_leds(hdev, drv_data->led_state); } else if (value != LED_OFF && !on) { - buzz->led_state |= (1 << n); - buzz_set_leds(hdev, buzz->led_state); + drv_data->led_state |= (1 << n); + buzz_set_leds(hdev, drv_data->led_state); } break; } @@ -503,21 +497,19 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) struct device *dev = led->dev->parent; struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct sony_sc *drv_data; - struct buzz_extra *buzz; int n; int on = 0; drv_data = hid_get_drvdata(hdev); - if (!drv_data || !drv_data->extra) { + if (!drv_data) { hid_err(hdev, "No device data\n"); return LED_OFF; } - buzz = drv_data->extra; for (n = 0; n < 4; n++) { - if (led == buzz->leds[n]) { - on = !! (buzz->led_state & (1 << n)); + if (led == drv_data->leds[n]) { + on = !!(drv_data->led_state & (1 << n)); break; } } @@ -528,7 +520,6 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; - struct buzz_extra *buzz; int n, ret = 0; struct led_classdev *led; size_t name_sz; @@ -541,13 +532,6 @@ static int sony_leds_init(struct hid_device *hdev) if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) return -ENODEV; - buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); - if (!buzz) { - hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); - return -ENOMEM; - } - drv_data->extra = buzz; - /* Clear LEDs as we have no way of reading their initial state. This is * only relevant if the driver is loaded after somebody actively set the * LEDs to on */ @@ -576,49 +560,41 @@ static int sony_leds_init(struct hid_device *hdev) goto error_leds; } - buzz->leds[n] = led; + drv_data->leds[n] = led; } return ret; error_leds: for (n = 0; n < 4; n++) { - led = buzz->leds[n]; - buzz->leds[n] = NULL; + led = drv_data->leds[n]; + drv_data->leds[n] = NULL; if (!led) continue; led_classdev_unregister(led); kfree(led); } - kfree(drv_data->extra); - drv_data->extra = NULL; return ret; } static void sony_leds_remove(struct hid_device *hdev) { struct sony_sc *drv_data; - struct buzz_extra *buzz; struct led_classdev *led; int n; drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); - buzz = drv_data->extra; - for (n = 0; n < 4; n++) { - led = buzz->leds[n]; - buzz->leds[n] = NULL; + led = drv_data->leds[n]; + drv_data->leds[n] = NULL; if (!led) continue; led_classdev_unregister(led); kfree(led); } - - kfree(drv_data->extra); - drv_data->extra = NULL; } #ifdef CONFIG_SONY_FF -- cgit v1.2.3 From 0a286ef278529f2bc4f4bb27c4cf99c05999c818 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:32 +0100 Subject: HID: sony: Add LED support for Sixaxis/Dualshock3 USB The PS3 Sixaxis controller has 4 LEDs which can be controlled using the same command as the rumble functionality. It seems not to be possible to only change the LED without modifying the rumble motor state. Thus both have to be stored on the host and retransmitted when either the LED or rumble state is changed. Third party controllers may not support to disable all LEDs at once. These controllers automatically switch to blinking of all LEDs when no LED is active anymore. Signed-off-by: Sven Eckelmann Tested-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 120 +++++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 48 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 2f93aab11056..b60bc38903db 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -39,6 +39,8 @@ #define BUZZ_CONTROLLER BIT(3) #define PS3REMOTE BIT(4) +#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER) + static const u8 sixaxis_rdesc_fixup[] = { 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, @@ -223,12 +225,12 @@ static const unsigned int buzz_keymap[] = { }; struct sony_sc { + struct hid_device *hdev; struct led_classdev *leds[4]; unsigned long quirks; + struct work_struct state_worker; #ifdef CONFIG_SONY_FF - struct work_struct state_worker; - struct hid_device *hdev; __u8 left; __u8 right; #endif @@ -462,6 +464,18 @@ static void buzz_set_leds(struct hid_device *hdev, int leds) hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } +static void sony_set_leds(struct hid_device *hdev, __u8 leds) +{ + struct sony_sc *drv_data = hid_get_drvdata(hdev); + + if (drv_data->quirks & BUZZ_CONTROLLER) { + buzz_set_leds(hdev, leds); + } else if (drv_data->quirks & SIXAXIS_CONTROLLER_USB) { + drv_data->led_state = leds; + schedule_work(&drv_data->state_worker); + } +} + static void sony_led_set_brightness(struct led_classdev *led, enum led_brightness value) { @@ -482,10 +496,10 @@ static void sony_led_set_brightness(struct led_classdev *led, int on = !!(drv_data->led_state & (1 << n)); if (value == LED_OFF && on) { drv_data->led_state &= ~(1 << n); - buzz_set_leds(hdev, drv_data->led_state); + sony_set_leds(hdev, drv_data->led_state); } else if (value != LED_OFF && !on) { drv_data->led_state |= (1 << n); - buzz_set_leds(hdev, drv_data->led_state); + sony_set_leds(hdev, drv_data->led_state); } break; } @@ -517,6 +531,25 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) return on ? LED_FULL : LED_OFF; } +static void sony_leds_remove(struct hid_device *hdev) +{ + struct sony_sc *drv_data; + struct led_classdev *led; + int n; + + drv_data = hid_get_drvdata(hdev); + BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); + + for (n = 0; n < 4; n++) { + led = drv_data->leds[n]; + drv_data->leds[n] = NULL; + if (!led) + continue; + led_classdev_unregister(led); + kfree(led); + } +} + static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; @@ -524,20 +557,29 @@ static int sony_leds_init(struct hid_device *hdev) struct led_classdev *led; size_t name_sz; char *name; + size_t name_len; + const char *name_fmt; drv_data = hid_get_drvdata(hdev); - BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); - - /* Validate expected report characteristics. */ - if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) - return -ENODEV; + BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); + + if (drv_data->quirks & BUZZ_CONTROLLER) { + name_len = strlen("::buzz#"); + name_fmt = "%s::buzz%d"; + /* Validate expected report characteristics. */ + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; + } else { + name_len = strlen("::sony#"); + name_fmt = "%s::sony%d"; + } /* Clear LEDs as we have no way of reading their initial state. This is * only relevant if the driver is loaded after somebody actively set the * LEDs to on */ - buzz_set_leds(hdev, 0x00); + sony_set_leds(hdev, 0x00); - name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; + name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; for (n = 0; n < 4; n++) { led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); @@ -547,7 +589,7 @@ static int sony_leds_init(struct hid_device *hdev) } name = (void *)(&led[1]); - snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); + snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); led->name = name; led->brightness = 0; led->max_brightness = 1; @@ -566,45 +608,18 @@ static int sony_leds_init(struct hid_device *hdev) return ret; error_leds: - for (n = 0; n < 4; n++) { - led = drv_data->leds[n]; - drv_data->leds[n] = NULL; - if (!led) - continue; - led_classdev_unregister(led); - kfree(led); - } + sony_leds_remove(hdev); return ret; } -static void sony_leds_remove(struct hid_device *hdev) -{ - struct sony_sc *drv_data; - struct led_classdev *led; - int n; - - drv_data = hid_get_drvdata(hdev); - BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); - - for (n = 0; n < 4; n++) { - led = drv_data->leds[n]; - drv_data->leds[n] = NULL; - if (!led) - continue; - led_classdev_unregister(led); - kfree(led); - } -} - -#ifdef CONFIG_SONY_FF static void sony_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); unsigned char buf[] = { 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, @@ -612,13 +627,18 @@ static void sony_state_worker(struct work_struct *work) 0x00, 0x00, 0x00, 0x00, 0x00 }; +#ifdef CONFIG_SONY_FF buf[3] = sc->right; buf[5] = sc->left; +#endif + + buf[10] |= (sc->led_state & 0xf) << 1; sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT); } +#ifdef CONFIG_SONY_FF static int sony_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { @@ -640,10 +660,6 @@ static int sony_init_ff(struct hid_device *hdev) struct hid_input *hidinput = list_entry(hdev->inputs.next, struct hid_input, list); struct input_dev *input_dev = hidinput->input; - struct sony_sc *sc = hid_get_drvdata(hdev); - - sc->hdev = hdev; - INIT_WORK(&sc->state_worker, sony_state_worker); input_set_capability(input_dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(input_dev, NULL, sony_play_effect); @@ -682,6 +698,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) sc->quirks = quirks; hid_set_drvdata(hdev, sc); + sc->hdev = hdev; ret = hid_parse(hdev); if (ret) { @@ -705,23 +722,30 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) if (sc->quirks & SIXAXIS_CONTROLLER_USB) { hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; ret = sixaxis_set_operational_usb(hdev); + INIT_WORK(&sc->state_worker, sony_state_worker); } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ret = sixaxis_set_operational_bt(hdev); - else if (sc->quirks & BUZZ_CONTROLLER) - ret = sony_leds_init(hdev); else ret = 0; if (ret < 0) goto err_stop; + if (sc->quirks & SONY_LED_SUPPORT) { + ret = sony_leds_init(hdev); + if (ret < 0) + goto err_stop; + } + ret = sony_init_ff(hdev); if (ret < 0) goto err_stop; return 0; err_stop: + if (sc->quirks & SONY_LED_SUPPORT) + sony_leds_remove(hdev); hid_hw_stop(hdev); return ret; } @@ -730,7 +754,7 @@ static void sony_remove(struct hid_device *hdev) { struct sony_sc *sc = hid_get_drvdata(hdev); - if (sc->quirks & BUZZ_CONTROLLER) + if (sc->quirks & SONY_LED_SUPPORT) sony_leds_remove(hdev); sony_destroy_ff(hdev); -- cgit v1.2.3 From 94037efe81d8e734e28f12b98f76a6e8005495d6 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 13 Nov 2013 13:34:18 +0200 Subject: HID: i2c-hid: disable interrupt on suspend When an I2C HID device is powered of during system sleep, as a result of removing its power resources (by the ACPI core) the interrupt line might go low as well. This results inadvertent interrupt and wakes the system from sleep immediately. To prevent this we disable the device interrupt in the drivers suspend method and enable it on resume. The device can still wake the system up if it is wake capable (this also means that not all of its power will be removed to keep the interrupt line high). Reported-by: Jerome Blin Signed-off-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index ae48d18ee315..20ab6853950e 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1061,6 +1061,7 @@ static int i2c_hid_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + disable_irq(client->irq); if (device_may_wakeup(&client->dev)) enable_irq_wake(client->irq); @@ -1075,6 +1076,7 @@ static int i2c_hid_resume(struct device *dev) int ret; struct i2c_client *client = to_i2c_client(dev); + enable_irq(client->irq); ret = i2c_hid_hwreset(client); if (ret) return ret; -- cgit v1.2.3 From 765e5fbd3e04ba753b2585e9f852fdcd34b95d10 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 27 Nov 2013 10:05:56 +0800 Subject: HID: usbhid: merge the sis quirk USB_VENDOR_ID_SIS and USB_VENDOR_ID_SIS2_TOUCH are identical, so refine the code and merge the quirks. Signed-off-by: AceLan Kao Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 5 ++--- drivers/hid/usbhid/hid-quirks.c | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 76559629568c..90e9806e864b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -755,9 +755,10 @@ #define USB_VENDOR_ID_SIGMATEL 0x066F #define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 -#define USB_VENDOR_ID_SIS2_TOUCH 0x0457 +#define USB_VENDOR_ID_SIS_TOUCH 0x0457 #define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 #define USB_DEVICE_ID_SIS817_TOUCH 0x0817 +#define USB_DEVICE_ID_SIS_TS 0x1013 #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 @@ -936,7 +937,5 @@ #define USB_VENDOR_ID_PRIMAX 0x0461 #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 -#define USB_VENDOR_ID_SIS 0x0457 -#define USB_DEVICE_ID_SIS_TS 0x1013 #endif diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0db9a67278ba..37307dc2d1f7 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -84,8 +84,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, @@ -114,7 +115,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SIS, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From d8e2e7581d2521910398c4c80d7a3b78e84da7d5 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 27 Nov 2013 10:05:57 +0800 Subject: HID: usbhid: quirk for Synaptics HD touchscreen Add Synaptics HD touchscreen(06cb:0ac3) to no init report quirk. Signed-off-by: AceLan Kao Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 90e9806e864b..56ed3a00ee2d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -810,6 +810,7 @@ #define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 #define USB_DEVICE_ID_SYNAPTICS_LTS1 0x0af8 #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 +#define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 37307dc2d1f7..11facfbadead 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -115,6 +115,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From 12f508aede4bda5d20a2dd3ff3deb16ef47a97e9 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 27 Nov 2013 10:05:58 +0800 Subject: HID: usbhid: quirk for Synaptics Quad HD touchscreen Add Synaptics HD touchscreen(06cb:1ac3) to no init report quirk Signed-off-by: AceLan Kao Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 56ed3a00ee2d..cb219dee5e64 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -811,6 +811,7 @@ #define USB_DEVICE_ID_SYNAPTICS_LTS1 0x0af8 #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 #define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 +#define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 11facfbadead..b3c7684e8706 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -116,6 +116,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From 6d16e9c301290268b92ce3d48114f982e9c4b00a Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Mon, 2 Dec 2013 23:19:24 +0800 Subject: HID: usbhid: fix sis quirk Since commit 765e5fbd merged the sis quirk, then USB_VENDOR_ID_SIS2_TOUCH remains undefined. Reported-by: Fengguang Wu Signed-off-by: Wanlong Gao Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 ++-- drivers/hid/hid-multitouch.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8c10f2742233..36cb475b1934 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1822,8 +1822,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index a2cedb8ae1c0..9ce8e8b757db 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1301,10 +1301,10 @@ static const struct hid_device_id mt_devices[] = { /* SiS panels */ { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, /* Stantum panels */ -- cgit v1.2.3 From 9f740ffa8134aaef770f964485dac3ed6780d8b7 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 27 Nov 2013 22:19:00 +0000 Subject: HID: hid-sensor-hub: Add logical min and max Exporting logical minimum and maximum of HID fields as part of the hid sensor attribute info. This can be used for range checking and to calculate enumeration base for NAry fields of HID sensor hub. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/hid/hid-sensor-hub.c | 20 ++++++++------------ include/linux/hid-sensor-hub.h | 2 ++ 2 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index a184e1921c11..d87f7cb4bee5 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -112,13 +112,15 @@ static int sensor_hub_get_physical_device_count( static void sensor_hub_fill_attr_info( struct hid_sensor_hub_attribute_info *info, - s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size) + s32 index, s32 report_id, struct hid_field *field) { info->index = index; info->report_id = report_id; - info->units = units; - info->unit_expo = unit_expo; - info->size = size/8; + info->units = field->unit; + info->unit_expo = field->unit_exponent; + info->size = (field->report_size * field->report_count)/8; + info->logical_minimum = field->logical_minimum; + info->logical_maximum = field->logical_maximum; } static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( @@ -325,9 +327,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, if (field->physical == usage_id && field->logical == attr_usage_id) { sensor_hub_fill_attr_info(info, i, report->id, - field->unit, field->unit_exponent, - field->report_size * - field->report_count); + field); ret = 0; } else { for (j = 0; j < field->maxusage; ++j) { @@ -336,11 +336,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, field->usage[j].collection_index == collection_index) { sensor_hub_fill_attr_info(info, - i, report->id, - field->unit, - field->unit_exponent, - field->report_size * - field->report_count); + i, report->id, field); ret = 0; break; } diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index 206a2af6b62b..b914ca3f57ba 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -42,6 +42,8 @@ struct hid_sensor_hub_attribute_info { s32 units; s32 unit_expo; s32 size; + s32 logical_minimum; + s32 logical_maximum; }; /** -- cgit v1.2.3 From 56d0c8b7c8fb63505a06b50364d12817ded88daa Mon Sep 17 00:00:00 2001 From: Vitaly Katraew Date: Sat, 30 Nov 2013 13:51:28 +0400 Subject: HID: add support for Logitech Dual Action gamepads I have two Logitech Dual Action gamepads, both have same Vendor/Device id pair. Newest gamepad (A) can switch between old mode (HID) and XBox gamepad emulation mode. Old gamepad (B) can only work in HID mode. In HID mode gamepad A sends many EPIPE errors during initialization and was disconnected immediately after connect to usb port. It works fine in Win and Mac. After adding NOGET quirk in driver, it was working properly. Gamepad B works fine before and after changes. I tested both gamepads with 3.8.0 and 3.11.6 kernels with modified driver. Follow patch can apply for current git kernel version. I can send pcap log from usb bus with both gamepads or any other additional information if it is needed Signed-off-by: Vitaly Katraew Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-lg.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index cb219dee5e64..92b2ddc83516 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -551,6 +551,7 @@ #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 +#define USB_DEVICE_ID_LOGITECH_DUAL_ACTION 0xc216 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 06eb45fa6331..9fe9d4ac3114 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -758,6 +758,8 @@ static const struct hid_device_id lg_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), .driver_data = LG_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION), + .driver_data = LG_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), .driver_data = LG_NOGET | LG_FF4 }, -- cgit v1.2.3 From dcdc50e72b8b8c21aca598705192dcbf96f4fb64 Mon Sep 17 00:00:00 2001 From: Olivier Gay Date: Tue, 3 Dec 2013 00:17:24 +0100 Subject: HID: logitech-dj: add HIDRAW dependency in Kconfig hid-logitech-dj.c driver needs hidraw to work correctly. Without hidraw, hid-logitech-dj.c fails during probe() and Logitech Unifying devices HID reports aren't recognized. The unifying receiver has 3 usb interfaces. When hid-logitech-dj driver is loaded, interfaces 0 and 1 are discarded. Interface 2 consists of a hid class interface with 3 collections, each of which sports the 'vendor' usage, thus, there is no reason for hid_input to claim any of them. On the other hand, hidraw has no issue in claiming the collections, even if they are 'vendor'. As of today, hid-logitech-dj uses hidraw api to send configuration/control reports to interface 2 of the Unifying receiver. Without the hid-logitech-dj driver, interfaces 0 and 1 are claimed by hid-input, as they correspond to a keyboard and a mouse. But that is not relevant to the discussion. [jkosina@suse.cz: make the changelog more verbose, thanks to Nestor] Signed-off-by: Olivier Gay Signed-off-by: Nestor Lopez Casado Signed-off-by: Mathieu Meisser Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 329fbb9b5976..c8a66b94b6dd 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -344,6 +344,7 @@ config HID_LOGITECH config HID_LOGITECH_DJ tristate "Logitech Unifying receivers full support" + depends on HIDRAW depends on HID_LOGITECH ---help--- Say Y if you want support for Logitech Unifying receivers and devices. -- cgit v1.2.3 From 954bb3da814e794f546f55449c508299a127fef8 Mon Sep 17 00:00:00 2001 From: Emanuel Krenz Date: Fri, 13 Dec 2013 14:51:53 +0100 Subject: HID: add support for SiS multitouch panel in the touch monitor LG 23ET83V [jkosina@suse.cz: refresh to apply after SIS quirk merging] Signed-off-by: Emanuel Krenz Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 4 files changed, 6 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 36cb475b1934..48296c02ed01 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1824,6 +1824,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 92b2ddc83516..c1077ba1bde0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -760,6 +760,7 @@ #define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 #define USB_DEVICE_ID_SIS817_TOUCH 0x0817 #define USB_DEVICE_ID_SIS_TS 0x1013 +#define USB_DEVICE_ID_SIS1030_TOUCH 0x1030 #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 9ce8e8b757db..1f0ba5c8e644 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1306,6 +1306,9 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, + USB_DEVICE_ID_SIS1030_TOUCH) }, /* Stantum panels */ { .driver_data = MT_CLS_CONFIDENCE, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index b3c7684e8706..175ec0afb70c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -87,6 +87,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -- cgit v1.2.3 From 7a5d49a33ca4b753b66c9b288dc4af60c2b787f7 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 13 Dec 2013 15:45:24 +0100 Subject: HID: remove SIS entries from hid_have_special_driver[] The entries are not needed, as hid-multitouch gets bound correctly automatically by contact ID. Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 48296c02ed01..b0de25824fb6 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1822,9 +1822,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, -- cgit v1.2.3 From a443255c3ed5688931d89adcaa640dd10e1aeef0 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 17 Dec 2013 12:52:48 +0100 Subject: HID: debug: add labels for some new buttons Add labels for BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT and BTN_TOOL_QUADTAP. [jkosina@suse.cz: make changelog more verbose] Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 8453214ec376..53b771d5683c 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -768,6 +768,8 @@ static const char *keys[KEY_MAX + 1] = { [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", + [BTN_DPAD_UP] = "BtnDPadUp", [BTN_DPAD_DOWN] = "BtnDPadDown", + [BTN_DPAD_LEFT] = "BtnDPadLeft", [BTN_DPAD_RIGHT] = "BtnDPadRight", [BTN_0] = "Btn0", [BTN_1] = "Btn1", [BTN_2] = "Btn2", [BTN_3] = "Btn3", [BTN_4] = "Btn4", [BTN_5] = "Btn5", @@ -797,7 +799,8 @@ static const char *keys[KEY_MAX + 1] = { [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", - [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", + [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_TOOL_QUADTAP] = "ToolQuadrupleTap", + [BTN_GEAR_DOWN] = "WheelBtn", [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", -- cgit v1.2.3 From bbe3175408cde792fbaa5bd1e41e430ea9e4fb4f Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 19 Dec 2013 11:05:13 -0500 Subject: HID: input: fix input sysfs path for hid devices we used to set the parent of the input device as the parent of the hid bus. This was introduced when we created hid as a real bus, and to keep backward compatibility. Now, it's time to proper set the parent so that sysfs has an idea of which input device is attached to which hid device. Signed-off-by: Benjamin Tissoires David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d97f2323af57..d50e7313b171 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1279,7 +1279,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) input_dev->id.vendor = hid->vendor; input_dev->id.product = hid->product; input_dev->id.version = hid->version; - input_dev->dev.parent = hid->dev.parent; + input_dev->dev.parent = &hid->dev; hidinput->input = input_dev; list_add_tail(&hidinput->list, &hid->inputs); -- cgit v1.2.3 From 8cd5fcda24b48b162699730da7ead7329b27159e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Dec 2013 23:47:27 +0100 Subject: HID: sony: fix error return code Currently the return variable ret is always 0. Set it to other values in error cases, as used in the direct return. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b60bc38903db..f57ab5e2832f 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -585,6 +585,7 @@ static int sony_leds_init(struct hid_device *hdev) led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); if (!led) { hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); + ret = -ENOMEM; goto error_leds; } @@ -596,7 +597,8 @@ static int sony_leds_init(struct hid_device *hdev) led->brightness_get = sony_led_get_brightness; led->brightness_set = sony_led_set_brightness; - if (led_classdev_register(&hdev->dev, led)) { + ret = led_classdev_register(&hdev->dev, led); + if (ret) { hid_err(hdev, "Failed to register LED %d\n", n); kfree(led); goto error_leds; -- cgit v1.2.3 From 618345359ed99a78e63f5cef8a09a8494589ee11 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 6 Jan 2014 16:43:27 +0100 Subject: HID: hidraw: make comment more accurate and nicer Reformat and reword some of the comments to make them more understandable. Signed-off-by: Jiri Kosina --- drivers/hid/hidraw.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 6a6dd5cd7833..cb0137b3718d 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -6,7 +6,7 @@ * to work on raw hid events as they want to, and avoids a need to * use a transport-specific userspace libhid/libusb libraries. * - * Copyright (c) 2007 Jiri Kosina + * Copyright (c) 2007-2014 Jiri Kosina */ /* @@ -104,8 +104,11 @@ out: return ret; } -/* The first byte is expected to be a report number. - * This function is to be called with the minors_lock mutex held */ +/* + * The first byte of the report buffer is expected to be a report number. + * + * This function is to be called with the minors_lock mutex held. + */ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type) { unsigned int minor = iminor(file_inode(file)); @@ -157,7 +160,6 @@ out: return ret; } -/* the first byte is expected to be a report number */ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { ssize_t ret; @@ -168,12 +170,15 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t } -/* This function performs a Get_Report transfer over the control endpoint +/* + * This function performs a Get_Report transfer over the control endpoint * per section 7.2.1 of the HID specification, version 1.1. The first byte * of buffer is the report number to request, or 0x0 if the defice does not * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT - * or HID_INPUT_REPORT. This function is to be called with the minors_lock - * mutex held. */ + * or HID_INPUT_REPORT. + * + * This function is to be called with the minors_lock mutex held. + */ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type) { unsigned int minor = iminor(file_inode(file)); @@ -209,8 +214,10 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t goto out; } - /* Read the first byte from the user. This is the report number, - * which is passed to dev->hid_get_raw_report(). */ + /* + * Read the first byte from the user. This is the report number, + * which is passed to dev->hid_get_raw_report(). + */ if (copy_from_user(&report_number, buffer, 1)) { ret = -EFAULT; goto out_free; @@ -498,7 +505,7 @@ int hidraw_connect(struct hid_device *hid) int minor, result; struct hidraw *dev; - /* we accept any HID device, no matter the applications */ + /* we accept any HID device, all applications */ dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL); if (!dev) -- cgit v1.2.3 From 0bd88dd3dd5e73e5d43b8d1e7a96b841978df562 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 11 Jan 2014 15:12:42 -0500 Subject: HID: sony: Add force-feedback support for the Dualshock 4 Adds the Dualshock 4 to the HID device list and enables force-feedback. Adds a Dualshock 4 specific worker function since the Dualshock 4 needs a different report than the Sixaxis. The right motor in the Dualshock 4 is variable so the full rumble value is now passed to the worker function and clamped there if necessary. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 ++ drivers/hid/hid-ids.h | 1 + drivers/hid/hid-sony.c | 39 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 957d35ba84bc..70cc4682044a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1831,6 +1831,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_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, + { 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_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 60336f06874c..ce24459284e3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -766,6 +766,7 @@ #define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374 #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 +#define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index f57ab5e2832f..8020d10ce703 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -38,6 +38,7 @@ #define SIXAXIS_CONTROLLER_BT BIT(2) #define BUZZ_CONTROLLER BIT(3) #define PS3REMOTE BIT(4) +#define DUALSHOCK4_CONTROLLER BIT(5) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER) @@ -630,7 +631,7 @@ static void sony_state_worker(struct work_struct *work) }; #ifdef CONFIG_SONY_FF - buf[3] = sc->right; + buf[3] = sc->right ? 1 : 0; buf[5] = sc->left; #endif @@ -640,6 +641,29 @@ static void sony_state_worker(struct work_struct *work) HID_OUTPUT_REPORT); } +static void dualshock4_state_worker(struct work_struct *work) +{ + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); + unsigned char buf[] = { + 0x05, + 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + }; + +#ifdef CONFIG_SONY_FF + buf[4] = sc->right; + buf[5] = sc->left; +#endif + + sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), + HID_OUTPUT_REPORT); +} + #ifdef CONFIG_SONY_FF static int sony_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) @@ -651,7 +675,7 @@ static int sony_play_effect(struct input_dev *dev, void *data, return 0; sc->left = effect->u.rumble.strong_magnitude / 256; - sc->right = effect->u.rumble.weak_magnitude ? 1 : 0; + sc->right = effect->u.rumble.weak_magnitude / 256; schedule_work(&sc->state_worker); return 0; @@ -728,8 +752,12 @@ 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 + else if (sc->quirks & DUALSHOCK4_CONTROLLER) { ret = 0; + INIT_WORK(&sc->state_worker, dualshock4_state_worker); + } else { + ret = 0; + } if (ret < 0) goto err_stop; @@ -787,6 +815,11 @@ static const struct hid_device_id sony_devices[] = { /* Logitech Harmony Adapter for PS3 */ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), .driver_data = PS3REMOTE }, + /* Sony Dualshock 4 controllers for PS4 */ + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), + .driver_data = DUALSHOCK4_CONTROLLER }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), + .driver_data = DUALSHOCK4_CONTROLLER }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); -- cgit v1.2.3 From 60781cf487e3aae5134b5fec85fe60ece31ff627 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 11 Jan 2014 15:13:15 -0500 Subject: HID: sony: Add LED controls for the Dualshock 4 Add LED lightbar controls for the Dualshock 4. The Dualshock 4 light bar has 3 separate RGB LEDs that can range in brightness from 0 to 255 so a full byte is now needed to store each LED's state Changed the module to support an arbitrary number of LEDs instead of being hardcoded to 4. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 77 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 27 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 8020d10ce703..79e0d5808a92 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -40,7 +40,9 @@ #define PS3REMOTE BIT(4) #define DUALSHOCK4_CONTROLLER BIT(5) -#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER) +#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER) + +#define MAX_LEDS 4 static const u8 sixaxis_rdesc_fixup[] = { 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, @@ -227,7 +229,7 @@ static const unsigned int buzz_keymap[] = { struct sony_sc { struct hid_device *hdev; - struct led_classdev *leds[4]; + struct led_classdev *leds[MAX_LEDS]; unsigned long quirks; struct work_struct state_worker; @@ -236,7 +238,8 @@ struct sony_sc { __u8 right; #endif - __u8 led_state; + __u8 led_state[MAX_LEDS]; + __u8 led_count; }; static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, @@ -447,7 +450,7 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); } -static void buzz_set_leds(struct hid_device *hdev, int leds) +static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds) { struct list_head *report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; @@ -456,23 +459,28 @@ static void buzz_set_leds(struct hid_device *hdev, int leds) __s32 *value = report->field[0]->value; value[0] = 0x00; - value[1] = (leds & 1) ? 0xff : 0x00; - value[2] = (leds & 2) ? 0xff : 0x00; - value[3] = (leds & 4) ? 0xff : 0x00; - value[4] = (leds & 8) ? 0xff : 0x00; + value[1] = leds[0] ? 0xff : 0x00; + value[2] = leds[1] ? 0xff : 0x00; + value[3] = leds[2] ? 0xff : 0x00; + value[4] = leds[3] ? 0xff : 0x00; value[5] = 0x00; value[6] = 0x00; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } -static void sony_set_leds(struct hid_device *hdev, __u8 leds) +static void sony_set_leds(struct hid_device *hdev, const __u8 *leds, int count) { struct sony_sc *drv_data = hid_get_drvdata(hdev); + int n; - if (drv_data->quirks & BUZZ_CONTROLLER) { + BUG_ON(count > MAX_LEDS); + + if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) { buzz_set_leds(hdev, leds); - } else if (drv_data->quirks & SIXAXIS_CONTROLLER_USB) { - drv_data->led_state = leds; + } else if ((drv_data->quirks & SIXAXIS_CONTROLLER_USB) || + (drv_data->quirks & DUALSHOCK4_CONTROLLER)) { + for (n = 0; n < count; n++) + drv_data->led_state[n] = leds[n]; schedule_work(&drv_data->state_worker); } } @@ -492,15 +500,11 @@ static void sony_led_set_brightness(struct led_classdev *led, return; } - for (n = 0; n < 4; n++) { + for (n = 0; n < drv_data->led_count; n++) { if (led == drv_data->leds[n]) { - int on = !!(drv_data->led_state & (1 << n)); - if (value == LED_OFF && on) { - drv_data->led_state &= ~(1 << n); - sony_set_leds(hdev, drv_data->led_state); - } else if (value != LED_OFF && !on) { - drv_data->led_state |= (1 << n); - sony_set_leds(hdev, drv_data->led_state); + if (value != drv_data->led_state[n]) { + drv_data->led_state[n] = value; + sony_set_leds(hdev, drv_data->led_state, drv_data->led_count); } break; } @@ -522,9 +526,9 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) return LED_OFF; } - for (n = 0; n < 4; n++) { + for (n = 0; n < drv_data->led_count; n++) { if (led == drv_data->leds[n]) { - on = !!(drv_data->led_state & (1 << n)); + on = !!(drv_data->led_state[n]); break; } } @@ -541,7 +545,7 @@ static void sony_leds_remove(struct hid_device *hdev) drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); - for (n = 0; n < 4; n++) { + for (n = 0; n < drv_data->led_count; n++) { led = drv_data->leds[n]; drv_data->leds[n] = NULL; if (!led) @@ -549,17 +553,21 @@ static void sony_leds_remove(struct hid_device *hdev) led_classdev_unregister(led); kfree(led); } + + drv_data->led_count = 0; } static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; int n, ret = 0; + int max_brightness; struct led_classdev *led; size_t name_sz; char *name; size_t name_len; const char *name_fmt; + static const __u8 initial_values[MAX_LEDS] = { 0x00, 0x00, 0x00, 0x00 }; drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); @@ -575,14 +583,22 @@ static int sony_leds_init(struct hid_device *hdev) name_fmt = "%s::sony%d"; } + if (drv_data->quirks & DUALSHOCK4_CONTROLLER) { + drv_data->led_count = 3; + max_brightness = 255; + } else { + drv_data->led_count = 4; + max_brightness = 1; + } + /* Clear LEDs as we have no way of reading their initial state. This is * only relevant if the driver is loaded after somebody actively set the * LEDs to on */ - sony_set_leds(hdev, 0x00); + sony_set_leds(hdev, initial_values, drv_data->led_count); name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; - for (n = 0; n < 4; n++) { + for (n = 0; n < drv_data->led_count; n++) { led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); if (!led) { hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); @@ -594,7 +610,7 @@ static int sony_leds_init(struct hid_device *hdev) snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); led->name = name; led->brightness = 0; - led->max_brightness = 1; + led->max_brightness = max_brightness; led->brightness_get = sony_led_get_brightness; led->brightness_set = sony_led_set_brightness; @@ -635,7 +651,10 @@ static void sony_state_worker(struct work_struct *work) buf[5] = sc->left; #endif - buf[10] |= (sc->led_state & 0xf) << 1; + buf[10] |= sc->led_state[0] << 1; + buf[10] |= sc->led_state[1] << 2; + buf[10] |= sc->led_state[2] << 3; + buf[10] |= sc->led_state[3] << 4; sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT); @@ -660,6 +679,10 @@ static void dualshock4_state_worker(struct work_struct *work) buf[5] = sc->left; #endif + buf[6] = sc->led_state[0]; + buf[7] = sc->led_state[1]; + buf[8] = sc->led_state[2]; + sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT); } -- cgit v1.2.3 From cad665a2a937d070e5909beec37f891a95911bef Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 11 Jan 2014 15:13:54 -0500 Subject: HID: sony: Rename worker function Rename sony_state_worker to sixaxis_state_worker since the function is now sixaxis specific. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 79e0d5808a92..1dfed2365d40 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -632,7 +632,7 @@ error_leds: return ret; } -static void sony_state_worker(struct work_struct *work) +static void sixaxis_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); unsigned char buf[] = { @@ -771,7 +771,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) if (sc->quirks & SIXAXIS_CONTROLLER_USB) { hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; ret = sixaxis_set_operational_usb(hdev); - INIT_WORK(&sc->state_worker, sony_state_worker); + INIT_WORK(&sc->state_worker, sixaxis_state_worker); } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ret = sixaxis_set_operational_bt(hdev); -- cgit v1.2.3 From 42c22dbf81ebd1146960875ddfe71630cb2b3ae6 Mon Sep 17 00:00:00 2001 From: Benjamin Tisssoires Date: Wed, 8 Jan 2014 17:18:45 -0500 Subject: HID: logitech-dj: Fix USB 3.0 issue This fix (not very clean though) should fix the long time USB3 issue that was spotted last year. The rational has been given by Hans de Goede: ---- I think the most likely cause for this is a firmware bug in the unifying receiver, likely a race condition. The most prominent difference between having a USB-2 device plugged into an EHCI (so USB-2 only) port versus an XHCI port will be inter packet timing. Specifically if you send packets (ie hid reports) one at a time, then with the EHCI controller their will be a significant pause between them, where with XHCI they will be very close together in time. The reason for this is the difference in EHCI / XHCI controller OS <-> driver interfaces. For non periodic endpoints (control, bulk) the EHCI uses a circular linked-list of commands in dma-memory, which it follows to execute commands, if the list is empty, it will go into an idle state and re-check periodically. The XHCI uses a ring of commands per endpoint, and if the OS places anything new on the ring it will do an ioport write, waking up the XHCI making it send the new packet immediately. For periodic transfers (isoc, interrupt) the delay between packets when sending one at a time (rather then queuing them up) will be even larger, because they need to be inserted into the EHCI schedule 2 ms in the future so the OS driver can be sure that the EHCI driver does not try to start executing the time slot in question before the insertion has completed. So a possible fix may be to insert a delay between packets being send to the receiver. ---- I tested this on a buggy Haswell USB 3.0 motherboard, and I always get the notification after adding the msleep. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-dj.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index a7947d8251a8..f45279c3b11a 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -516,6 +516,14 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout; retval = logi_dj_recv_send_report(djrcv_dev, dj_report); kfree(dj_report); + + /* + * Ugly sleep to work around a USB 3.0 bug when the receiver is still + * processing the "switch-to-dj" command while we send an other command. + * 50 msec should gives enough time to the receiver to be ready. + */ + msleep(50); + return retval; } -- cgit v1.2.3 From 875e36f8a2ce6cfc2010af6c91fb5351bd530d48 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 14 Jan 2014 09:30:20 -0800 Subject: HID: hid-sensor-hub: Fix buggy report descriptors This addresses regression caused by commit id "751d17e23a9f7" iio: hid-sensors: Fix power and report state. This commit removed a quirk, to change the enumeration base to 1 from 0 based on an CONFIG paramter. There was objection to add more changes under this quirk, instead suggested to add an HID quirk. But there is no easy way to add HID qurik as the reports are not properly using collection class. The solution was to use logical minimum, which is a correct way. There were changes done in firmware to address this. Unfortunately some devices, still use old FW and can't be upgraded to newer version on Linux devices as there is no FW upgrade tool available for Linux devices. So we need to fix report descriptors, for such devices. This will not have any impact, if the FW uses logical 1 as minimum. In this patch we look for usage id for "power and report state", and modify logical minimum value to 1. Background on enum: In the original HID sensor hub firmwares all Named array enums were to 0-based. But the most recent hub implemented as 1-based, because of the implementation by one of the major OS vendor. Using logical minimum for the field as the base of enum. So we add logical minimum to the selector values before setting those fields. Some sensor hub FWs already changed logical minimum from 0 to 1 to reflect this and hope every other vendor will follow. There is no easy way to add a common HID quirk for NAry elements, even if the standard specifies these field as NAry, the collection used to describe selectors is still just "logical". Signed-off-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 4 ++++ drivers/hid/hid-sensor-hub.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f9304cb37154..fe9cd9df7011 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -445,6 +445,10 @@ #define USB_VENDOR_ID_ILITEK 0x222a #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 +#define USB_VENDOR_ID_INTEL_0 0x8086 +#define USB_VENDOR_ID_INTEL_1 0x8087 +#define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa + #define USB_VENDOR_ID_ION 0x15e4 #define USB_DEVICE_ID_ICADE 0x0132 diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 8fab82829f8b..46f4480035bc 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -26,6 +26,8 @@ #include #include "hid-ids.h" +#define HID_SENSOR_HUB_ENUM_QUIRK 0x01 + /** * struct sensor_hub_pending - Synchronous read pending information * @status: Pending status true/false. @@ -64,6 +66,7 @@ struct sensor_hub_data { spinlock_t dyn_callback_lock; struct mfd_cell *hid_sensor_hub_client_devs; int hid_sensor_client_cnt; + unsigned long quirks; }; /** @@ -497,6 +500,40 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev) } EXPORT_SYMBOL_GPL(sensor_hub_device_close); +static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + int index; + struct sensor_hub_data *sd = hid_get_drvdata(hdev); + unsigned char report_block[] = { + 0x0a, 0x16, 0x03, 0x15, 0x00, 0x25, 0x05}; + unsigned char power_block[] = { + 0x0a, 0x19, 0x03, 0x15, 0x00, 0x25, 0x05}; + + if (!(sd->quirks & HID_SENSOR_HUB_ENUM_QUIRK)) { + hid_dbg(hdev, "No Enum quirks\n"); + return rdesc; + } + + /* Looks for power and report state usage id and force to 1 */ + for (index = 0; index < *rsize; ++index) { + if (((*rsize - index) > sizeof(report_block)) && + !memcmp(&rdesc[index], report_block, + sizeof(report_block))) { + rdesc[index + 4] = 0x01; + index += sizeof(report_block); + } + if (((*rsize - index) > sizeof(power_block)) && + !memcmp(&rdesc[index], power_block, + sizeof(power_block))) { + rdesc[index + 4] = 0x01; + index += sizeof(power_block); + } + } + + return rdesc; +} + static int sensor_hub_probe(struct hid_device *hdev, const struct hid_device_id *id) { @@ -520,6 +557,7 @@ static int sensor_hub_probe(struct hid_device *hdev, return -ENOMEM; } hid_set_drvdata(hdev, sd); + sd->quirks = id->driver_data; sd->hsdev->hdev = hdev; sd->hsdev->vendor_id = hdev->vendor; sd->hsdev->product_id = hdev->product; @@ -621,6 +659,12 @@ static void sensor_hub_remove(struct hid_device *hdev) } static const struct hid_device_id sensor_hub_devices[] = { + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_0, + USB_DEVICE_ID_INTEL_HID_SENSOR), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, + USB_DEVICE_ID_INTEL_HID_SENSOR), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) }, { } @@ -633,6 +677,7 @@ static struct hid_driver sensor_hub_driver = { .probe = sensor_hub_probe, .remove = sensor_hub_remove, .raw_event = sensor_hub_raw_event, + .report_fixup = sensor_hub_report_fixup, #ifdef CONFIG_PM .suspend = sensor_hub_suspend, .resume = sensor_hub_resume, -- cgit v1.2.3 From 274be3eb653c421d68514684024c6d915c94b728 Mon Sep 17 00:00:00 2001 From: Kharlamov Alexey Date: Tue, 14 Jan 2014 16:09:09 +0400 Subject: HID: hid-holtek-mouse: add new a070 mouse Added support of RITMIX ROM-316 mouse to hid-holtek-mouse workaround module Signed-off-by: Alexey Kharlamov Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-holtek-mouse.c | 3 +++ drivers/hid/hid-ids.h | 1 + 3 files changed, 5 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b0de25824fb6..23498ccc4c2b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1715,6 +1715,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c index 0caa676de622..d60fbd0adc0c 100644 --- a/drivers/hid/hid-holtek-mouse.c +++ b/drivers/hid/hid-holtek-mouse.c @@ -49,6 +49,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, } break; case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A: + case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070: case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081: if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f && rdesc[111] == 0xff && rdesc[112] == 0x7f) { @@ -65,6 +66,8 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, static const struct hid_device_id holtek_mouse_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c1077ba1bde0..436fc19c5ca0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -455,6 +455,7 @@ #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 +#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070 0xa070 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072 0xa072 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081 -- cgit v1.2.3 From 8ab1676b614e4ef816a83ba214523b4fac256fce Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 16 Jan 2014 21:42:31 -0500 Subject: HID: sony: Use separate identifiers for USB and Bluetooth connected Dualshock 4 controllers. Use separate identifiers for Dualshock 4 controllers connected via USB and Bluetooth. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 1dfed2365d40..2f992e12f6f9 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -38,9 +38,10 @@ #define SIXAXIS_CONTROLLER_BT BIT(2) #define BUZZ_CONTROLLER BIT(3) #define PS3REMOTE BIT(4) -#define DUALSHOCK4_CONTROLLER BIT(5) +#define DUALSHOCK4_CONTROLLER_USB BIT(5) +#define DUALSHOCK4_CONTROLLER_BT BIT(6) -#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER) +#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB) #define MAX_LEDS 4 @@ -478,7 +479,7 @@ static void sony_set_leds(struct hid_device *hdev, const __u8 *leds, int count) if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) { buzz_set_leds(hdev, leds); } else if ((drv_data->quirks & SIXAXIS_CONTROLLER_USB) || - (drv_data->quirks & DUALSHOCK4_CONTROLLER)) { + (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB)) { for (n = 0; n < count; n++) drv_data->led_state[n] = leds[n]; schedule_work(&drv_data->state_worker); @@ -583,7 +584,7 @@ static int sony_leds_init(struct hid_device *hdev) name_fmt = "%s::sony%d"; } - if (drv_data->quirks & DUALSHOCK4_CONTROLLER) { + if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) { drv_data->led_count = 3; max_brightness = 255; } else { @@ -775,7 +776,7 @@ 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 & DUALSHOCK4_CONTROLLER) { + else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { ret = 0; INIT_WORK(&sc->state_worker, dualshock4_state_worker); } else { @@ -840,9 +841,9 @@ static const struct hid_device_id sony_devices[] = { .driver_data = PS3REMOTE }, /* Sony Dualshock 4 controllers for PS4 */ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), - .driver_data = DUALSHOCK4_CONTROLLER }, + .driver_data = DUALSHOCK4_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), - .driver_data = DUALSHOCK4_CONTROLLER }, + .driver_data = DUALSHOCK4_CONTROLLER_BT }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); -- cgit v1.2.3 From 0da8ea6581d59f523880e7856bccfb35d33cffdf Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 16 Jan 2014 21:42:51 -0500 Subject: HID: sony: Use standard output reports instead of raw reports to send data to the Dualshock 4. Use regular HID output reports instead of raw reports in the dualshock4_state_worker function. (Thanks Simon Mungewell) Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 2f992e12f6f9..e6231318cf7a 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -664,28 +664,39 @@ static void sixaxis_state_worker(struct work_struct *work) static void dualshock4_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); - unsigned char buf[] = { - 0x05, - 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - }; + struct hid_device *hdev = sc->hdev; + struct list_head *head, *list; + struct hid_report *report; + __s32 *value; + + list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; + + list_for_each(head, list) { + report = list_entry(head, struct hid_report, list); + + /* Report 5 is used to send data to the controller via USB */ + if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && report->id == 5) + break; + } + + if (head == list) { + hid_err(hdev, "Dualshock 4 output report not found\n"); + return; + } + + value = report->field[0]->value; + value[0] = 0x03; #ifdef CONFIG_SONY_FF - buf[4] = sc->right; - buf[5] = sc->left; + value[3] = sc->right; + value[4] = sc->left; #endif - buf[6] = sc->led_state[0]; - buf[7] = sc->led_state[1]; - buf[8] = sc->led_state[2]; + value[5] = sc->led_state[0]; + value[6] = sc->led_state[1]; + value[7] = sc->led_state[2]; - sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), - HID_OUTPUT_REPORT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } #ifdef CONFIG_SONY_FF -- cgit v1.2.3 From 6c79c18c97411cd1b0302169e7bc9dbe40f5d286 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 16 Jan 2014 21:43:03 -0500 Subject: HID: sony: Fix spacing in the device definitions. Fix cosmetic spacing in the device definitions. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index e6231318cf7a..a7c81677c540 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -33,11 +33,11 @@ #include "hid-ids.h" -#define VAIO_RDESC_CONSTANT BIT(0) -#define SIXAXIS_CONTROLLER_USB BIT(1) -#define SIXAXIS_CONTROLLER_BT BIT(2) -#define BUZZ_CONTROLLER BIT(3) -#define PS3REMOTE BIT(4) +#define VAIO_RDESC_CONSTANT BIT(0) +#define SIXAXIS_CONTROLLER_USB BIT(1) +#define SIXAXIS_CONTROLLER_BT BIT(2) +#define BUZZ_CONTROLLER BIT(3) +#define PS3REMOTE BIT(4) #define DUALSHOCK4_CONTROLLER_USB BIT(5) #define DUALSHOCK4_CONTROLLER_BT BIT(6) -- cgit v1.2.3 From ed19d8cf28b2b03ec05e75de9c1f73981b342978 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Thu, 16 Jan 2014 21:43:12 -0500 Subject: HID: sony: Map gyroscopes and accelerometers to axes Use a modified HID descriptor for the Dualshock 4 to assign the gyroscope sensors and accelerometers to axes. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index a7c81677c540..edffe2c47cf9 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -73,6 +73,73 @@ static const u8 sixaxis_rdesc_fixup2[] = { 0xb1, 0x02, 0xc0, 0xc0, }; +static u8 dualshock4_usb_rdesc[] = { + 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, + 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, + 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, + 0x04, 0x81, 0x02, 0x09, 0x39, 0x15, 0x00, 0x25, + 0x07, 0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, + 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x65, 0x00, + 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, + 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e, 0x81, 0x02, + 0x06, 0x00, 0xff, 0x09, 0x20, 0x75, 0x06, 0x95, + 0x01, 0x15, 0x00, 0x25, 0x7f, 0x81, 0x02, 0x05, + 0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, + 0xff, 0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, + 0x06, 0x00, 0xff, 0x09, 0x21, 0x95, 0x03, 0x81, + 0x02, 0x05, 0x01, 0x19, 0x40, 0x29, 0x42, 0x16, + 0x00, 0x80, 0x26, 0x00, 0x7f, 0x75, 0x10, 0x95, + 0x03, 0x81, 0x02, 0x05, 0x01, 0x19, 0x43, 0x29, + 0x45, 0x16, 0xff, 0xbf, 0x26, 0x00, 0x40, 0x95, + 0x03, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x21, + 0x75, 0x08, 0x95, 0x27, 0x81, 0x02, 0x85, 0x05, + 0x09, 0x22, 0x95, 0x1f, 0x91, 0x02, 0x85, 0x04, + 0x09, 0x23, 0x95, 0x24, 0xb1, 0x02, 0x85, 0x02, + 0x09, 0x24, 0x95, 0x24, 0xb1, 0x02, 0x85, 0x08, + 0x09, 0x25, 0x95, 0x03, 0xb1, 0x02, 0x85, 0x10, + 0x09, 0x26, 0x95, 0x04, 0xb1, 0x02, 0x85, 0x11, + 0x09, 0x27, 0x95, 0x02, 0xb1, 0x02, 0x85, 0x12, + 0x06, 0x02, 0xff, 0x09, 0x21, 0x95, 0x0f, 0xb1, + 0x02, 0x85, 0x13, 0x09, 0x22, 0x95, 0x16, 0xb1, + 0x02, 0x85, 0x14, 0x06, 0x05, 0xff, 0x09, 0x20, + 0x95, 0x10, 0xb1, 0x02, 0x85, 0x15, 0x09, 0x21, + 0x95, 0x2c, 0xb1, 0x02, 0x06, 0x80, 0xff, 0x85, + 0x80, 0x09, 0x20, 0x95, 0x06, 0xb1, 0x02, 0x85, + 0x81, 0x09, 0x21, 0x95, 0x06, 0xb1, 0x02, 0x85, + 0x82, 0x09, 0x22, 0x95, 0x05, 0xb1, 0x02, 0x85, + 0x83, 0x09, 0x23, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0x84, 0x09, 0x24, 0x95, 0x04, 0xb1, 0x02, 0x85, + 0x85, 0x09, 0x25, 0x95, 0x06, 0xb1, 0x02, 0x85, + 0x86, 0x09, 0x26, 0x95, 0x06, 0xb1, 0x02, 0x85, + 0x87, 0x09, 0x27, 0x95, 0x23, 0xb1, 0x02, 0x85, + 0x88, 0x09, 0x28, 0x95, 0x22, 0xb1, 0x02, 0x85, + 0x89, 0x09, 0x29, 0x95, 0x02, 0xb1, 0x02, 0x85, + 0x90, 0x09, 0x30, 0x95, 0x05, 0xb1, 0x02, 0x85, + 0x91, 0x09, 0x31, 0x95, 0x03, 0xb1, 0x02, 0x85, + 0x92, 0x09, 0x32, 0x95, 0x03, 0xb1, 0x02, 0x85, + 0x93, 0x09, 0x33, 0x95, 0x0c, 0xb1, 0x02, 0x85, + 0xa0, 0x09, 0x40, 0x95, 0x06, 0xb1, 0x02, 0x85, + 0xa1, 0x09, 0x41, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0xa2, 0x09, 0x42, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0xa3, 0x09, 0x43, 0x95, 0x30, 0xb1, 0x02, 0x85, + 0xa4, 0x09, 0x44, 0x95, 0x0d, 0xb1, 0x02, 0x85, + 0xa5, 0x09, 0x45, 0x95, 0x15, 0xb1, 0x02, 0x85, + 0xa6, 0x09, 0x46, 0x95, 0x15, 0xb1, 0x02, 0x85, + 0xf0, 0x09, 0x47, 0x95, 0x3f, 0xb1, 0x02, 0x85, + 0xf1, 0x09, 0x48, 0x95, 0x3f, 0xb1, 0x02, 0x85, + 0xf2, 0x09, 0x49, 0x95, 0x0f, 0xb1, 0x02, 0x85, + 0xa7, 0x09, 0x4a, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0xa8, 0x09, 0x4b, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0xa9, 0x09, 0x4c, 0x95, 0x08, 0xb1, 0x02, 0x85, + 0xaa, 0x09, 0x4e, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0xab, 0x09, 0x4f, 0x95, 0x39, 0xb1, 0x02, 0x85, + 0xac, 0x09, 0x50, 0x95, 0x39, 0xb1, 0x02, 0x85, + 0xad, 0x09, 0x51, 0x95, 0x0b, 0xb1, 0x02, 0x85, + 0xae, 0x09, 0x52, 0x95, 0x01, 0xb1, 0x02, 0x85, + 0xaf, 0x09, 0x53, 0x95, 0x02, 0xb1, 0x02, 0x85, + 0xb0, 0x09, 0x54, 0x95, 0x3f, 0xb1, 0x02, 0xc0, +}; + static __u8 ps3remote_rdesc[] = { 0x05, 0x01, /* GUsagePage Generic Desktop */ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ @@ -307,6 +374,17 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[55] = 0x06; } + /* + * The default Dualshock 4 USB descriptor doesn't assign + * the gyroscope values to corresponding axes so we need a + * modified one. + */ + if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) { + hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); + rdesc = dualshock4_usb_rdesc; + *rsize = sizeof(dualshock4_usb_rdesc); + } + /* The HID descriptor exposed over BT has a trailing zero byte */ if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) || ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) && -- cgit v1.2.3 From c4e1ddf2680b357868deb3c7f5618d3d8ea500e2 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 17 Jan 2014 14:46:26 -0500 Subject: HID: sony: Cache the output report for the Dualshock 4 Retrieve and cache the output report for the Dualshock 4 in sony_probe() instead of repeatedly walking the report list in the worker function. Signed-off-by: Frank Praznik Reviewed-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 55 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index edffe2c47cf9..9013005a9f35 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -298,6 +298,7 @@ static const unsigned int buzz_keymap[] = { struct sony_sc { struct hid_device *hdev; struct led_classdev *leds[MAX_LEDS]; + struct hid_report *output_report; unsigned long quirks; struct work_struct state_worker; @@ -743,26 +744,9 @@ static void dualshock4_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); struct hid_device *hdev = sc->hdev; - struct list_head *head, *list; - struct hid_report *report; - __s32 *value; - - list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; - - list_for_each(head, list) { - report = list_entry(head, struct hid_report, list); - - /* Report 5 is used to send data to the controller via USB */ - if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && report->id == 5) - break; - } - - if (head == list) { - hid_err(hdev, "Dualshock 4 output report not found\n"); - return; - } + struct hid_report *report = sc->output_report; + __s32 *value = report->field[0]->value; - value = report->field[0]->value; value[0] = 0x03; #ifdef CONFIG_SONY_FF @@ -822,6 +806,33 @@ static void sony_destroy_ff(struct hid_device *hdev) } #endif +static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size) +{ + struct list_head *head, *list; + struct hid_report *report; + struct hid_device *hdev = sc->hdev; + + list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; + + list_for_each(head, list) { + report = list_entry(head, struct hid_report, list); + + if (report->id == req_id) { + if (report->size < req_size) { + hid_err(hdev, "Output report 0x%02x (%i bits) is smaller than requested size (%i bits)\n", + req_id, report->size, req_size); + return -EINVAL; + } + sc->output_report = report; + return 0; + } + } + + hid_err(hdev, "Unable to locate output report 0x%02x\n", req_id); + + return -EINVAL; +} + static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; @@ -866,7 +877,11 @@ 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 & DUALSHOCK4_CONTROLLER_USB) { - ret = 0; + /* Report 5 (31 bytes) is used to send data to the controller via USB */ + ret = sony_set_output_report(sc, 0x05, 248); + if (ret < 0) + goto err_stop; + INIT_WORK(&sc->state_worker, dualshock4_state_worker); } else { ret = 0; -- cgit v1.2.3 From 58d7027b7f92b1c4d883126a54782c656a76cafd Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 20 Jan 2014 12:27:01 -0500 Subject: HID: sony: Add annotated HID descriptor for the Dualshock 4 Add annotated HID descriptor for the Dualshock 4. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 320 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 256 insertions(+), 64 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 9013005a9f35..62765c76c56a 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -73,71 +73,263 @@ static const u8 sixaxis_rdesc_fixup2[] = { 0xb1, 0x02, 0xc0, 0xc0, }; +/* The default descriptor doesn't provide mapping for the accelerometers + * or orientation sensors. This fixed descriptor maps the accelerometers + * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors + * to usage values 0x43, 0x44 and 0x45. + */ static u8 dualshock4_usb_rdesc[] = { - 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, - 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, - 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, - 0x04, 0x81, 0x02, 0x09, 0x39, 0x15, 0x00, 0x25, - 0x07, 0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, - 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x65, 0x00, - 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, - 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e, 0x81, 0x02, - 0x06, 0x00, 0xff, 0x09, 0x20, 0x75, 0x06, 0x95, - 0x01, 0x15, 0x00, 0x25, 0x7f, 0x81, 0x02, 0x05, - 0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, - 0xff, 0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, - 0x06, 0x00, 0xff, 0x09, 0x21, 0x95, 0x03, 0x81, - 0x02, 0x05, 0x01, 0x19, 0x40, 0x29, 0x42, 0x16, - 0x00, 0x80, 0x26, 0x00, 0x7f, 0x75, 0x10, 0x95, - 0x03, 0x81, 0x02, 0x05, 0x01, 0x19, 0x43, 0x29, - 0x45, 0x16, 0xff, 0xbf, 0x26, 0x00, 0x40, 0x95, - 0x03, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x21, - 0x75, 0x08, 0x95, 0x27, 0x81, 0x02, 0x85, 0x05, - 0x09, 0x22, 0x95, 0x1f, 0x91, 0x02, 0x85, 0x04, - 0x09, 0x23, 0x95, 0x24, 0xb1, 0x02, 0x85, 0x02, - 0x09, 0x24, 0x95, 0x24, 0xb1, 0x02, 0x85, 0x08, - 0x09, 0x25, 0x95, 0x03, 0xb1, 0x02, 0x85, 0x10, - 0x09, 0x26, 0x95, 0x04, 0xb1, 0x02, 0x85, 0x11, - 0x09, 0x27, 0x95, 0x02, 0xb1, 0x02, 0x85, 0x12, - 0x06, 0x02, 0xff, 0x09, 0x21, 0x95, 0x0f, 0xb1, - 0x02, 0x85, 0x13, 0x09, 0x22, 0x95, 0x16, 0xb1, - 0x02, 0x85, 0x14, 0x06, 0x05, 0xff, 0x09, 0x20, - 0x95, 0x10, 0xb1, 0x02, 0x85, 0x15, 0x09, 0x21, - 0x95, 0x2c, 0xb1, 0x02, 0x06, 0x80, 0xff, 0x85, - 0x80, 0x09, 0x20, 0x95, 0x06, 0xb1, 0x02, 0x85, - 0x81, 0x09, 0x21, 0x95, 0x06, 0xb1, 0x02, 0x85, - 0x82, 0x09, 0x22, 0x95, 0x05, 0xb1, 0x02, 0x85, - 0x83, 0x09, 0x23, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0x84, 0x09, 0x24, 0x95, 0x04, 0xb1, 0x02, 0x85, - 0x85, 0x09, 0x25, 0x95, 0x06, 0xb1, 0x02, 0x85, - 0x86, 0x09, 0x26, 0x95, 0x06, 0xb1, 0x02, 0x85, - 0x87, 0x09, 0x27, 0x95, 0x23, 0xb1, 0x02, 0x85, - 0x88, 0x09, 0x28, 0x95, 0x22, 0xb1, 0x02, 0x85, - 0x89, 0x09, 0x29, 0x95, 0x02, 0xb1, 0x02, 0x85, - 0x90, 0x09, 0x30, 0x95, 0x05, 0xb1, 0x02, 0x85, - 0x91, 0x09, 0x31, 0x95, 0x03, 0xb1, 0x02, 0x85, - 0x92, 0x09, 0x32, 0x95, 0x03, 0xb1, 0x02, 0x85, - 0x93, 0x09, 0x33, 0x95, 0x0c, 0xb1, 0x02, 0x85, - 0xa0, 0x09, 0x40, 0x95, 0x06, 0xb1, 0x02, 0x85, - 0xa1, 0x09, 0x41, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0xa2, 0x09, 0x42, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0xa3, 0x09, 0x43, 0x95, 0x30, 0xb1, 0x02, 0x85, - 0xa4, 0x09, 0x44, 0x95, 0x0d, 0xb1, 0x02, 0x85, - 0xa5, 0x09, 0x45, 0x95, 0x15, 0xb1, 0x02, 0x85, - 0xa6, 0x09, 0x46, 0x95, 0x15, 0xb1, 0x02, 0x85, - 0xf0, 0x09, 0x47, 0x95, 0x3f, 0xb1, 0x02, 0x85, - 0xf1, 0x09, 0x48, 0x95, 0x3f, 0xb1, 0x02, 0x85, - 0xf2, 0x09, 0x49, 0x95, 0x0f, 0xb1, 0x02, 0x85, - 0xa7, 0x09, 0x4a, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0xa8, 0x09, 0x4b, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0xa9, 0x09, 0x4c, 0x95, 0x08, 0xb1, 0x02, 0x85, - 0xaa, 0x09, 0x4e, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0xab, 0x09, 0x4f, 0x95, 0x39, 0xb1, 0x02, 0x85, - 0xac, 0x09, 0x50, 0x95, 0x39, 0xb1, 0x02, 0x85, - 0xad, 0x09, 0x51, 0x95, 0x0b, 0xb1, 0x02, 0x85, - 0xae, 0x09, 0x52, 0x95, 0x01, 0xb1, 0x02, 0x85, - 0xaf, 0x09, 0x53, 0x95, 0x02, 0xb1, 0x02, 0x85, - 0xb0, 0x09, 0x54, 0x95, 0x3f, 0xb1, 0x02, 0xc0, + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x05, /* Usage (Gamepad), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x01, /* Report ID (1), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x09, 0x32, /* Usage (Z), */ + 0x09, 0x35, /* Usage (Rz), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x04, /* Report Count (4), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x39, /* Usage (Hat Switch), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x25, 0x07, /* Logical Maximum (7), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ + 0x65, 0x14, /* Unit (Degrees), */ + 0x75, 0x04, /* Report Size (4), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x42, /* Input (Variable, Null State), */ + 0x65, 0x00, /* Unit, */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x0E, /* Usage Maximum (0Eh), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x0E, /* Report Count (14), */ + 0x81, 0x02, /* Input (Variable), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x09, 0x20, /* Usage (20h), */ + 0x75, 0x06, /* Report Size (6), */ + 0x95, 0x01, /* Report Count (1), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x25, 0x7F, /* Logical Maximum (127), */ + 0x81, 0x02, /* Input (Variable), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x33, /* Usage (Rx), */ + 0x09, 0x34, /* Usage (Ry), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x02, /* Input (Variable), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x09, 0x21, /* Usage (21h), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x19, 0x40, /* Usage Minimum (40h), */ + 0x29, 0x42, /* Usage Maximum (42h), */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ + 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x19, 0x43, /* Usage Minimum (43h), */ + 0x29, 0x45, /* Usage Maximum (45h), */ + 0x16, 0xFF, 0xBF, /* Logical Minimum (-16385), */ + 0x26, 0x00, 0x40, /* Logical Maximum (16384), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x09, 0x21, /* Usage (21h), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x25, 0xFF, /* Logical Maximum (255), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x27, /* Report Count (39), */ + 0x81, 0x02, /* Input (Variable), */ + 0x85, 0x05, /* Report ID (5), */ + 0x09, 0x22, /* Usage (22h), */ + 0x95, 0x1F, /* Report Count (31), */ + 0x91, 0x02, /* Output (Variable), */ + 0x85, 0x04, /* Report ID (4), */ + 0x09, 0x23, /* Usage (23h), */ + 0x95, 0x24, /* Report Count (36), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x02, /* Report ID (2), */ + 0x09, 0x24, /* Usage (24h), */ + 0x95, 0x24, /* Report Count (36), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x08, /* Report ID (8), */ + 0x09, 0x25, /* Usage (25h), */ + 0x95, 0x03, /* Report Count (3), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x10, /* Report ID (16), */ + 0x09, 0x26, /* Usage (26h), */ + 0x95, 0x04, /* Report Count (4), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x11, /* Report ID (17), */ + 0x09, 0x27, /* Usage (27h), */ + 0x95, 0x02, /* Report Count (2), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x12, /* Report ID (18), */ + 0x06, 0x02, 0xFF, /* Usage Page (FF02h), */ + 0x09, 0x21, /* Usage (21h), */ + 0x95, 0x0F, /* Report Count (15), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x13, /* Report ID (19), */ + 0x09, 0x22, /* Usage (22h), */ + 0x95, 0x16, /* Report Count (22), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x14, /* Report ID (20), */ + 0x06, 0x05, 0xFF, /* Usage Page (FF05h), */ + 0x09, 0x20, /* Usage (20h), */ + 0x95, 0x10, /* Report Count (16), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x15, /* Report ID (21), */ + 0x09, 0x21, /* Usage (21h), */ + 0x95, 0x2C, /* Report Count (44), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ + 0x85, 0x80, /* Report ID (128), */ + 0x09, 0x20, /* Usage (20h), */ + 0x95, 0x06, /* Report Count (6), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x81, /* Report ID (129), */ + 0x09, 0x21, /* Usage (21h), */ + 0x95, 0x06, /* Report Count (6), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x82, /* Report ID (130), */ + 0x09, 0x22, /* Usage (22h), */ + 0x95, 0x05, /* Report Count (5), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x83, /* Report ID (131), */ + 0x09, 0x23, /* Usage (23h), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x84, /* Report ID (132), */ + 0x09, 0x24, /* Usage (24h), */ + 0x95, 0x04, /* Report Count (4), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x85, /* Report ID (133), */ + 0x09, 0x25, /* Usage (25h), */ + 0x95, 0x06, /* Report Count (6), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x86, /* Report ID (134), */ + 0x09, 0x26, /* Usage (26h), */ + 0x95, 0x06, /* Report Count (6), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x87, /* Report ID (135), */ + 0x09, 0x27, /* Usage (27h), */ + 0x95, 0x23, /* Report Count (35), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x88, /* Report ID (136), */ + 0x09, 0x28, /* Usage (28h), */ + 0x95, 0x22, /* Report Count (34), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x89, /* Report ID (137), */ + 0x09, 0x29, /* Usage (29h), */ + 0x95, 0x02, /* Report Count (2), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x90, /* Report ID (144), */ + 0x09, 0x30, /* Usage (30h), */ + 0x95, 0x05, /* Report Count (5), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x91, /* Report ID (145), */ + 0x09, 0x31, /* Usage (31h), */ + 0x95, 0x03, /* Report Count (3), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x92, /* Report ID (146), */ + 0x09, 0x32, /* Usage (32h), */ + 0x95, 0x03, /* Report Count (3), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0x93, /* Report ID (147), */ + 0x09, 0x33, /* Usage (33h), */ + 0x95, 0x0C, /* Report Count (12), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA0, /* Report ID (160), */ + 0x09, 0x40, /* Usage (40h), */ + 0x95, 0x06, /* Report Count (6), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA1, /* Report ID (161), */ + 0x09, 0x41, /* Usage (41h), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA2, /* Report ID (162), */ + 0x09, 0x42, /* Usage (42h), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA3, /* Report ID (163), */ + 0x09, 0x43, /* Usage (43h), */ + 0x95, 0x30, /* Report Count (48), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA4, /* Report ID (164), */ + 0x09, 0x44, /* Usage (44h), */ + 0x95, 0x0D, /* Report Count (13), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA5, /* Report ID (165), */ + 0x09, 0x45, /* Usage (45h), */ + 0x95, 0x15, /* Report Count (21), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA6, /* Report ID (166), */ + 0x09, 0x46, /* Usage (46h), */ + 0x95, 0x15, /* Report Count (21), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xF0, /* Report ID (240), */ + 0x09, 0x47, /* Usage (47h), */ + 0x95, 0x3F, /* Report Count (63), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xF1, /* Report ID (241), */ + 0x09, 0x48, /* Usage (48h), */ + 0x95, 0x3F, /* Report Count (63), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xF2, /* Report ID (242), */ + 0x09, 0x49, /* Usage (49h), */ + 0x95, 0x0F, /* Report Count (15), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA7, /* Report ID (167), */ + 0x09, 0x4A, /* Usage (4Ah), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA8, /* Report ID (168), */ + 0x09, 0x4B, /* Usage (4Bh), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xA9, /* Report ID (169), */ + 0x09, 0x4C, /* Usage (4Ch), */ + 0x95, 0x08, /* Report Count (8), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xAA, /* Report ID (170), */ + 0x09, 0x4E, /* Usage (4Eh), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xAB, /* Report ID (171), */ + 0x09, 0x4F, /* Usage (4Fh), */ + 0x95, 0x39, /* Report Count (57), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xAC, /* Report ID (172), */ + 0x09, 0x50, /* Usage (50h), */ + 0x95, 0x39, /* Report Count (57), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xAD, /* Report ID (173), */ + 0x09, 0x51, /* Usage (51h), */ + 0x95, 0x0B, /* Report Count (11), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xAE, /* Report ID (174), */ + 0x09, 0x52, /* Usage (52h), */ + 0x95, 0x01, /* Report Count (1), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xAF, /* Report ID (175), */ + 0x09, 0x53, /* Usage (53h), */ + 0x95, 0x02, /* Report Count (2), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0x85, 0xB0, /* Report ID (176), */ + 0x09, 0x54, /* Usage (54h), */ + 0x95, 0x3F, /* Report Count (63), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0 /* End Collection */ }; static __u8 ps3remote_rdesc[] = { -- cgit v1.2.3 From 61ebca937f2609e66fe6749f8f5df57ff387e2eb Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 20 Jan 2014 12:27:02 -0500 Subject: HID: sony: Use colors for the Dualshock 4 LED names Use the naming scheme 'devicename:colour' for the Dualshock 4 LED lightbar controls as specified in Documentation/leds/leds-class.txt Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 62765c76c56a..12354055d474 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -834,33 +834,39 @@ static int sony_leds_init(struct hid_device *hdev) struct sony_sc *drv_data; int n, ret = 0; int max_brightness; + int use_colors; struct led_classdev *led; size_t name_sz; char *name; size_t name_len; const char *name_fmt; + static const char * const color_str[] = { "red", "green", "blue" }; static const __u8 initial_values[MAX_LEDS] = { 0x00, 0x00, 0x00, 0x00 }; drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); if (drv_data->quirks & BUZZ_CONTROLLER) { + drv_data->led_count = 4; + max_brightness = 1; + use_colors = 0; name_len = strlen("::buzz#"); name_fmt = "%s::buzz%d"; /* Validate expected report characteristics. */ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) return -ENODEV; - } else { - name_len = strlen("::sony#"); - name_fmt = "%s::sony%d"; - } - - if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) { + } else if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) { drv_data->led_count = 3; max_brightness = 255; + use_colors = 1; + name_len = 0; + name_fmt = "%s:%s"; } else { drv_data->led_count = 4; max_brightness = 1; + use_colors = 0; + name_len = strlen("::sony#"); + name_fmt = "%s::sony%d"; } /* Clear LEDs as we have no way of reading their initial state. This is @@ -871,6 +877,10 @@ static int sony_leds_init(struct hid_device *hdev) name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; for (n = 0; n < drv_data->led_count; n++) { + + if (use_colors) + name_sz = strlen(dev_name(&hdev->dev)) + strlen(color_str[n]) + 2; + led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); if (!led) { hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); @@ -879,7 +889,10 @@ static int sony_leds_init(struct hid_device *hdev) } name = (void *)(&led[1]); - snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); + if (use_colors) + snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), color_str[n]); + else + snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); led->name = name; led->brightness = 0; led->max_brightness = max_brightness; -- cgit v1.2.3