diff options
Diffstat (limited to 'drivers/hid')
34 files changed, 540 insertions, 230 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c6f7a69..7e89288 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -625,7 +625,7 @@ static void hid_close_report(struct hid_device *device) static void hid_device_release(struct device *dev) { - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); hid_close_report(hid); kfree(hid->dev_rdesc); @@ -1571,8 +1571,8 @@ read_report_descriptor(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct device *dev = kobj_to_dev(kobj); + struct hid_device *hdev = to_hid_device(dev); if (off >= hdev->rsize) return 0; @@ -1589,7 +1589,7 @@ static ssize_t show_country(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); return sprintf(buf, "%02x\n", hdev->country & 0xff); } @@ -1691,11 +1691,6 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) hid_warn(hdev, "can't create sysfs country code attribute err: %d\n", ret); - ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc); - if (ret) - hid_warn(hdev, - "can't create sysfs report descriptor attribute err: %d\n", ret); - hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n", buf, bus, hdev->version >> 8, hdev->version & 0xff, type, hdev->name, hdev->phys); @@ -1707,7 +1702,6 @@ EXPORT_SYMBOL_GPL(hid_connect); void hid_disconnect(struct hid_device *hdev) { device_remove_file(&hdev->dev, &dev_attr_country); - device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc); if (hdev->claimed & HID_CLAIMED_INPUT) hidinput_disconnect(hdev); if (hdev->claimed & HID_CLAIMED_HIDDEV) @@ -1902,6 +1896,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, @@ -2076,7 +2071,7 @@ struct hid_dynid { static ssize_t store_new_id(struct device_driver *drv, const char *buf, size_t count) { - struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); + struct hid_driver *hdrv = to_hid_driver(drv); struct hid_dynid *dynid; __u32 bus, vendor, product; unsigned long driver_data = 0; @@ -2138,17 +2133,16 @@ static const struct hid_device_id *hid_match_device(struct hid_device *hdev, static int hid_bus_match(struct device *dev, struct device_driver *drv) { - struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_driver *hdrv = to_hid_driver(drv); + struct hid_device *hdev = to_hid_device(dev); return hid_match_device(hdev, hdrv) != NULL; } static int hid_device_probe(struct device *dev) { - struct hid_driver *hdrv = container_of(dev->driver, - struct hid_driver, driver); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_driver *hdrv = to_hid_driver(dev->driver); + struct hid_device *hdev = to_hid_device(dev); const struct hid_device_id *id; int ret = 0; @@ -2190,7 +2184,7 @@ unlock_driver_lock: static int hid_device_remove(struct device *dev) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct hid_driver *hdrv; int ret = 0; @@ -2223,12 +2217,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, char *buf) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - int len; - - len = snprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n", - hdev->bus, hdev->group, hdev->vendor, hdev->product); - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; + return scnprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n", + hdev->bus, hdev->group, hdev->vendor, hdev->product); } static DEVICE_ATTR_RO(modalias); @@ -2236,11 +2227,19 @@ static struct attribute *hid_dev_attrs[] = { &dev_attr_modalias.attr, NULL, }; -ATTRIBUTE_GROUPS(hid_dev); +static struct bin_attribute *hid_dev_bin_attrs[] = { + &dev_bin_attr_report_desc, + NULL +}; +static const struct attribute_group hid_dev_group = { + .attrs = hid_dev_attrs, + .bin_attrs = hid_dev_bin_attrs, +}; +__ATTRIBUTE_GROUPS(hid_dev); static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X", hdev->bus, hdev->vendor, hdev->product)) @@ -2408,6 +2407,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454_V2) }, { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) }, { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) }, { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) }, @@ -2660,6 +2660,7 @@ struct hid_device *hid_allocate_device(void) device_initialize(&hdev->dev); hdev->dev.release = hid_device_release; hdev->dev.bus = &hid_bus_type; + device_enable_async_suspend(&hdev->dev); hid_close_report(hdev); diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c index bcefb9e..5855196 100644 --- a/drivers/hid/hid-corsair.c +++ b/drivers/hid/hid-corsair.c @@ -655,18 +655,7 @@ static struct hid_driver corsair_driver = { .input_mapping = corsair_input_mapping, }; -static int __init corsair_init(void) -{ - return hid_register_driver(&corsair_driver); -} - -static void corsair_exit(void) -{ - hid_unregister_driver(&corsair_driver); -} - -module_init(corsair_init); -module_exit(corsair_exit); +module_hid_driver(corsair_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Clement Vuchener"); diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 7afc3fc..7c38bfa 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -807,7 +807,7 @@ static ssize_t name##_store(struct device *kdev, \ struct device_attribute *attr, const char *buf, \ size_t count) \ { \ - struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \ + struct hid_device *hdev = to_hid_device(kdev); \ struct cp2112_usb_config_report cfg; \ int ret = cp2112_get_usb_config(hdev, &cfg); \ if (ret) \ @@ -822,7 +822,7 @@ static ssize_t name##_store(struct device *kdev, \ static ssize_t name##_show(struct device *kdev, \ struct device_attribute *attr, char *buf) \ { \ - struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \ + struct hid_device *hdev = to_hid_device(kdev); \ struct cp2112_usb_config_report cfg; \ int ret = cp2112_get_usb_config(hdev, &cfg); \ if (ret) \ @@ -887,7 +887,7 @@ static ssize_t pstr_store(struct device *kdev, struct device_attribute *kattr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(kdev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(kdev); struct cp2112_pstring_attribute *attr = container_of(kattr, struct cp2112_pstring_attribute, attr); struct cp2112_string_report report; @@ -918,7 +918,7 @@ static ssize_t pstr_store(struct device *kdev, static ssize_t pstr_show(struct device *kdev, struct device_attribute *kattr, char *buf) { - struct hid_device *hdev = container_of(kdev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(kdev); struct cp2112_pstring_attribute *attr = container_of(kattr, struct cp2112_pstring_attribute, attr); struct cp2112_string_report report; diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 2886b64..acfb522 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -659,13 +659,13 @@ EXPORT_SYMBOL_GPL(hid_dump_device); /* enqueue string to 'events' ring buffer */ void hid_debug_event(struct hid_device *hdev, char *buf) { - int i; + unsigned i; struct hid_debug_list *list; unsigned long flags; spin_lock_irqsave(&hdev->debug_list_lock, flags); list_for_each_entry(list, &hdev->debug_list, node) { - for (i = 0; i < strlen(buf); i++) + for (i = 0; buf[i]; i++) list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = buf[i]; list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; diff --git a/drivers/hid/hid-gt683r.c b/drivers/hid/hid-gt683r.c index 0d6f135..a298fbd 100644 --- a/drivers/hid/hid-gt683r.c +++ b/drivers/hid/hid-gt683r.c @@ -70,7 +70,7 @@ static void gt683r_brightness_set(struct led_classdev *led_cdev, { int i; struct device *dev = led_cdev->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct gt683r_led *led = hid_get_drvdata(hdev); for (i = 0; i < GT683R_LED_COUNT; i++) { @@ -89,8 +89,7 @@ static ssize_t mode_show(struct device *dev, char *buf) { u8 sysfs_mode; - struct hid_device *hdev = container_of(dev->parent, - struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev->parent); struct gt683r_led *led = hid_get_drvdata(hdev); if (led->mode == GT683R_LED_NORMAL) @@ -108,8 +107,7 @@ static ssize_t mode_store(struct device *dev, const char *buf, size_t count) { u8 sysfs_mode; - struct hid_device *hdev = container_of(dev->parent, - struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev->parent); struct gt683r_led *led = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index ac1feea..242ec4f 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -515,6 +515,7 @@ #define USB_VENDOR_ID_ITE 0x048d #define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350 +#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396 #define USB_VENDOR_ID_JABRA 0x0b0e #define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 @@ -609,6 +610,7 @@ #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f #define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306 +#define USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS 0xc24d #define USB_DEVICE_ID_LOGITECH_MOUSE_C01A 0xc01a #define USB_DEVICE_ID_LOGITECH_MOUSE_C05A 0xc05a #define USB_DEVICE_ID_LOGITECH_MOUSE_C06A 0xc06a @@ -619,6 +621,7 @@ #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 #define USB_DEVICE_ID_LOGITECH_G29_WHEEL 0xc24f +#define USB_DEVICE_ID_LOGITECH_G920_WHEEL 0xc262 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287 @@ -668,6 +671,7 @@ #define USB_DEVICE_ID_PICOLCD 0xc002 #define USB_DEVICE_ID_PICOLCD_BOOTLOADER 0xf002 #define USB_DEVICE_ID_PICK16F1454 0x0042 +#define USB_DEVICE_ID_PICK16F1454_V2 0xf2f7 #define USB_VENDOR_ID_MICROSOFT 0x045e #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 2ba6bf6..bcfaf32 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -303,6 +303,7 @@ static enum power_supply_property hidinput_battery_props[] = { #define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */ #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ +#define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, @@ -320,6 +321,9 @@ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, + USB_DEVICE_ID_ELECOM_BM084), + HID_BATTERY_QUIRK_IGNORE }, {} }; @@ -408,6 +412,14 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, if (dev->battery != NULL) goto out; /* already initialized? */ + quirks = find_battery_quirk(dev); + + hid_dbg(dev, "device %x:%x:%x %d quirks %d\n", + dev->bus, dev->vendor, dev->product, dev->version, quirks); + + if (quirks & HID_BATTERY_QUIRK_IGNORE) + goto out; + psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL); if (psy_desc == NULL) goto out; @@ -424,11 +436,6 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, psy_desc->use_for_apm = 0; psy_desc->get_property = hidinput_get_battery_property; - quirks = find_battery_quirk(dev); - - hid_dbg(dev, "device %x:%x:%x %d quirks %d\n", - dev->bus, dev->vendor, dev->product, dev->version, quirks); - min = field->logical_minimum; max = field->logical_maximum; @@ -960,6 +967,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel goto ignore; case HID_UP_LOGIVENDOR: + /* intentional fallback */ + case HID_UP_LOGIVENDOR2: + /* intentional fallback */ + case HID_UP_LOGIVENDOR3: goto ignore; case HID_UP_PID: diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index 8979f1f..0125e35 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -220,7 +220,7 @@ static ssize_t attr_fn_lock_show_cptkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock); @@ -231,7 +231,7 @@ static ssize_t attr_fn_lock_store_cptkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); int value; @@ -250,7 +250,7 @@ static ssize_t attr_sensitivity_show_cptkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", @@ -262,7 +262,7 @@ static ssize_t attr_sensitivity_store_cptkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); int value; @@ -387,7 +387,7 @@ static ssize_t attr_press_to_select_show_tpkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); @@ -398,7 +398,7 @@ static ssize_t attr_press_to_select_store_tpkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int value; @@ -417,7 +417,7 @@ static ssize_t attr_dragging_show_tpkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); @@ -428,7 +428,7 @@ static ssize_t attr_dragging_store_tpkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int value; @@ -447,7 +447,7 @@ static ssize_t attr_release_to_select_show_tpkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); @@ -458,7 +458,7 @@ static ssize_t attr_release_to_select_store_tpkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int value; @@ -477,7 +477,7 @@ static ssize_t attr_select_right_show_tpkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); @@ -488,7 +488,7 @@ static ssize_t attr_select_right_store_tpkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int value; @@ -507,7 +507,7 @@ static ssize_t attr_sensitivity_show_tpkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", @@ -519,7 +519,7 @@ static ssize_t attr_sensitivity_store_tpkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int value; @@ -536,7 +536,7 @@ static ssize_t attr_press_speed_show_tpkbd(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%u\n", @@ -548,7 +548,7 @@ static ssize_t attr_press_speed_store_tpkbd(struct device *dev, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int value; @@ -609,7 +609,7 @@ static enum led_brightness lenovo_led_brightness_get_tpkbd( struct led_classdev *led_cdev) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); int led_nr = 0; @@ -625,7 +625,7 @@ static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev, enum led_brightness value) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); struct hid_report *report; int led_nr = 0; diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index c20ac76..c690fae 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -665,8 +665,9 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) struct lg_drv_data *drv_data; int ret; - /* Only work with the 1st interface (G29 presents multiple) */ - if (iface_num != 0) { + /* G29 only work with the 1st interface */ + if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) && + (iface_num != 0)) { dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num); return -ENODEV; } diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index fbddcb3..af3a8ec 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -33,8 +33,6 @@ #include "hid-lg4ff.h" #include "hid-ids.h" -#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev) - #define LG4FF_MMODE_IS_MULTIMODE 0 #define LG4FF_MMODE_SWITCHED 1 #define LG4FF_MMODE_NOT_MULTIMODE 2 @@ -1020,7 +1018,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, enum led_brightness value) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); struct lg_drv_data *drv_data = hid_get_drvdata(hid); struct lg4ff_device_entry *entry; int i, state = 0; @@ -1055,7 +1053,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); struct lg_drv_data *drv_data = hid_get_drvdata(hid); struct lg4ff_device_entry *entry; int i, value = 0; diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 5fd9786..bd2ab476 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -40,18 +40,22 @@ MODULE_PARM_DESC(disable_tap_to_click, #define REPORT_ID_HIDPP_SHORT 0x10 #define REPORT_ID_HIDPP_LONG 0x11 +#define REPORT_ID_HIDPP_VERY_LONG 0x12 #define HIDPP_REPORT_SHORT_LENGTH 7 #define HIDPP_REPORT_LONG_LENGTH 20 +#define HIDPP_REPORT_VERY_LONG_LENGTH 64 #define HIDPP_QUIRK_CLASS_WTP BIT(0) #define HIDPP_QUIRK_CLASS_M560 BIT(1) #define HIDPP_QUIRK_CLASS_K400 BIT(2) +#define HIDPP_QUIRK_CLASS_G920 BIT(3) /* bits 2..20 are reserved for classes */ #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) #define HIDPP_QUIRK_NO_HIDINPUT BIT(23) +#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24) #define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \ HIDPP_QUIRK_CONNECT_EVENTS) @@ -81,13 +85,13 @@ MODULE_PARM_DESC(disable_tap_to_click, struct fap { u8 feature_index; u8 funcindex_clientid; - u8 params[HIDPP_REPORT_LONG_LENGTH - 4U]; + u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U]; }; struct rap { u8 sub_id; u8 reg_address; - u8 params[HIDPP_REPORT_LONG_LENGTH - 4U]; + u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U]; }; struct hidpp_report { @@ -144,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device *hidpp_dev); static int __hidpp_send_report(struct hid_device *hdev, struct hidpp_report *hidpp_report) { + struct hidpp_device *hidpp = hid_get_drvdata(hdev); int fields_count, ret; + hidpp = hid_get_drvdata(hdev); + switch (hidpp_report->report_id) { case REPORT_ID_HIDPP_SHORT: fields_count = HIDPP_REPORT_SHORT_LENGTH; @@ -153,6 +160,9 @@ static int __hidpp_send_report(struct hid_device *hdev, case REPORT_ID_HIDPP_LONG: fields_count = HIDPP_REPORT_LONG_LENGTH; break; + case REPORT_ID_HIDPP_VERY_LONG: + fields_count = HIDPP_REPORT_VERY_LONG_LENGTH; + break; default: return -ENODEV; } @@ -163,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev, */ hidpp_report->device_index = 0xff; - ret = hid_hw_raw_request(hdev, hidpp_report->report_id, - (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT, - HID_REQ_SET_REPORT); + if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) { + ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, fields_count); + } else { + ret = hid_hw_raw_request(hdev, hidpp_report->report_id, + (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT, + HID_REQ_SET_REPORT); + } return ret == fields_count ? 0 : -1; } @@ -217,8 +231,9 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, goto exit; } - if (response->report_id == REPORT_ID_HIDPP_LONG && - response->fap.feature_index == HIDPP20_ERROR) { + if ((response->report_id == REPORT_ID_HIDPP_LONG || + response->report_id == REPORT_ID_HIDPP_VERY_LONG) && + response->fap.feature_index == HIDPP20_ERROR) { ret = response->fap.params[1]; dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret); goto exit; @@ -243,7 +258,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp, message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL); if (!message) return -ENOMEM; - message->report_id = REPORT_ID_HIDPP_LONG; + + if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4)) + message->report_id = REPORT_ID_HIDPP_VERY_LONG; + else + message->report_id = REPORT_ID_HIDPP_LONG; message->fap.feature_index = feat_index; message->fap.funcindex_clientid = funcindex_clientid; memcpy(&message->fap.params, params, param_count); @@ -258,13 +277,23 @@ static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev, struct hidpp_report *response) { struct hidpp_report *message; - int ret; + int ret, max_count; - if ((report_id != REPORT_ID_HIDPP_SHORT) && - (report_id != REPORT_ID_HIDPP_LONG)) + switch (report_id) { + case REPORT_ID_HIDPP_SHORT: + max_count = HIDPP_REPORT_SHORT_LENGTH - 4; + break; + case REPORT_ID_HIDPP_LONG: + max_count = HIDPP_REPORT_LONG_LENGTH - 4; + break; + case REPORT_ID_HIDPP_VERY_LONG: + max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4; + break; + default: return -EINVAL; + } - if (param_count > sizeof(message->rap.params)) + if (param_count > max_count) return -EINVAL; message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL); @@ -508,10 +537,19 @@ static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp, if (ret) return ret; - if (response.report_id == REPORT_ID_HIDPP_LONG) + switch (response.report_id) { + case REPORT_ID_HIDPP_VERY_LONG: + count = HIDPP_REPORT_VERY_LONG_LENGTH - 4; + break; + case REPORT_ID_HIDPP_LONG: count = HIDPP_REPORT_LONG_LENGTH - 4; - else + break; + case REPORT_ID_HIDPP_SHORT: count = HIDPP_REPORT_SHORT_LENGTH - 4; + break; + default: + return -EPROTO; + } if (len_buf < count) count = len_buf; @@ -1257,6 +1295,131 @@ static int k400_connect(struct hid_device *hdev, bool connected) return k400_disable_tap_to_click(hidpp); } +/* ------------------------------------------------------------------------- */ +/* Logitech G920 Driving Force Racing Wheel for Xbox One */ +/* ------------------------------------------------------------------------- */ + +#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123 + +/* Using session ID = 1 */ +#define CMD_G920_FORCE_GET_APERTURE 0x51 +#define CMD_G920_FORCE_SET_APERTURE 0x61 + +struct g920_private_data { + u8 force_feature; + u16 range; +}; + +static ssize_t g920_range_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hid_device *hid = to_hid_device(dev); + struct hidpp_device *hidpp = hid_get_drvdata(hid); + struct g920_private_data *pdata; + + pdata = hidpp->private_data; + if (!pdata) { + hid_err(hid, "Private driver data not found!\n"); + return -EINVAL; + } + + return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range); +} + +static ssize_t g920_range_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct hid_device *hid = to_hid_device(dev); + struct hidpp_device *hidpp = hid_get_drvdata(hid); + struct g920_private_data *pdata; + struct hidpp_report response; + u8 params[2]; + int ret; + u16 range = simple_strtoul(buf, NULL, 10); + + pdata = hidpp->private_data; + if (!pdata) { + hid_err(hid, "Private driver data not found!\n"); + return -EINVAL; + } + + if (range < 180) + range = 180; + else if (range > 900) + range = 900; + + params[0] = range >> 8; + params[1] = range & 0x00FF; + + ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature, + CMD_G920_FORCE_SET_APERTURE, params, 2, &response); + if (ret) + return ret; + + pdata->range = range; + return count; +} + +static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, g920_range_show, g920_range_store); + +static int g920_allocate(struct hid_device *hdev) +{ + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + struct g920_private_data *pdata; + + pdata = devm_kzalloc(&hdev->dev, sizeof(struct g920_private_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + hidpp->private_data = pdata; + + return 0; +} + +static int g920_get_config(struct hidpp_device *hidpp) +{ + struct g920_private_data *pdata = hidpp->private_data; + struct hidpp_report response; + u8 feature_type; + u8 feature_index; + int ret; + + pdata = hidpp->private_data; + if (!pdata) { + hid_err(hidpp->hid_dev, "Private driver data not found!\n"); + return -EINVAL; + } + + /* Find feature and store for later use */ + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK, + &feature_index, &feature_type); + if (ret) + return ret; + + pdata->force_feature = feature_index; + + /* Read current Range */ + ret = hidpp_send_fap_command_sync(hidpp, feature_index, + CMD_G920_FORCE_GET_APERTURE, NULL, 0, &response); + if (ret > 0) { + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", + __func__, ret); + return -EPROTO; + } + if (ret) + return ret; + + pdata->range = get_unaligned_be16(&response.fap.params[0]); + + /* Create sysfs interface */ + ret = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range); + if (ret) + hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d\n", ret); + + return 0; +} + /* -------------------------------------------------------------------------- */ /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ @@ -1276,6 +1439,25 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 0; } +static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + + /* Ensure that Logitech G920 is not given a default fuzz/flat value */ + if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + if (usage->type == EV_ABS && (usage->code == ABS_X || + usage->code == ABS_Y || usage->code == ABS_Z || + usage->code == ABS_RZ)) { + field->application = HID_GD_MULTIAXIS; + } + } + + return 0; +} + + static void hidpp_populate_input(struct hidpp_device *hidpp, struct input_dev *input, bool origin_is_hid_core) { @@ -1347,6 +1529,14 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, /* Generic HID++ processing. */ switch (data[0]) { + case REPORT_ID_HIDPP_VERY_LONG: + if (size != HIDPP_REPORT_VERY_LONG_LENGTH) { + hid_err(hdev, "received hid++ report of bad size (%d)", + size); + return 1; + } + ret = hidpp_raw_hidpp_event(hidpp, data, size); + break; case REPORT_ID_HIDPP_LONG: if (size != HIDPP_REPORT_LONG_LENGTH) { hid_err(hdev, "received hid++ report of bad size (%d)", @@ -1393,10 +1583,12 @@ static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying) else name = hidpp_get_device_name(hidpp); - if (!name) + if (!name) { hid_err(hdev, "unable to retrieve the name of the device"); - else + } else { + dbg_hid("HID++: Got name: %s\n", name); snprintf(hdev->name, sizeof(hdev->name), "%s", name); + } kfree(name); } @@ -1547,6 +1739,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = k400_allocate(hdev); if (ret) goto allocate_fail; + } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + ret = g920_allocate(hdev); + if (ret) + goto allocate_fail; } INIT_WORK(&hidpp->work, delayed_work_cb); @@ -1559,6 +1755,25 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) goto hid_parse_fail; } + if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) + connect_mask &= ~HID_CONNECT_HIDINPUT; + + if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + ret = hid_hw_start(hdev, connect_mask); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto hid_hw_start_fail; + } + ret = hid_hw_open(hdev); + if (ret < 0) { + dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n", + __func__, ret); + hid_hw_stop(hdev); + goto hid_hw_start_fail; + } + } + + /* Allow incoming packets */ hid_device_io_start(hdev); @@ -1567,8 +1782,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (!connected) { ret = -ENODEV; hid_err(hdev, "Device not connected"); - hid_device_io_stop(hdev); - goto hid_parse_fail; + goto hid_hw_open_failed; } hid_info(hdev, "HID++ %u.%u device connected.\n", @@ -1581,19 +1795,22 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) { ret = wtp_get_config(hidpp); if (ret) - goto hid_parse_fail; + goto hid_hw_open_failed; + } else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) { + ret = g920_get_config(hidpp); + if (ret) + goto hid_hw_open_failed; } /* Block incoming packets */ hid_device_io_stop(hdev); - if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) - connect_mask &= ~HID_CONNECT_HIDINPUT; - - ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "%s:hid_hw_start returned error\n", __func__); - goto hid_hw_start_fail; + if (!(hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) { + ret = hid_hw_start(hdev, connect_mask); + if (ret) { + hid_err(hdev, "%s:hid_hw_start returned error\n", __func__); + goto hid_hw_start_fail; + } } if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) { @@ -1605,6 +1822,13 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; +hid_hw_open_failed: + hid_device_io_stop(hdev); + if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + device_remove_file(&hdev->dev, &dev_attr_range); + hid_hw_close(hdev); + hid_hw_stop(hdev); + } hid_hw_start_fail: hid_parse_fail: cancel_work_sync(&hidpp->work); @@ -1618,9 +1842,13 @@ static void hidpp_remove(struct hid_device *hdev) { struct hidpp_device *hidpp = hid_get_drvdata(hdev); + if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + device_remove_file(&hdev->dev, &dev_attr_range); + hid_hw_close(hdev); + } + hid_hw_stop(hdev); cancel_work_sync(&hidpp->work); mutex_destroy(&hidpp->send_mutex); - hid_hw_stop(hdev); } static const struct hid_device_id hidpp_devices[] = { @@ -1648,6 +1876,9 @@ static const struct hid_device_id hidpp_devices[] = { { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, + + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL), + .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS}, {} }; @@ -1661,6 +1892,7 @@ static struct hid_driver hidpp_driver = { .raw_event = hidpp_raw_event, .input_configured = hidpp_input_configured, .input_mapping = hidpp_input_mapping, + .input_mapped = hidpp_input_mapped, }; module_hid_driver(hidpp_driver); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3d664d0..296d499 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -272,7 +272,7 @@ static ssize_t mt_show_quirks(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct mt_device *td = hid_get_drvdata(hdev); return sprintf(buf, "%u\n", td->mtclass.quirks); @@ -282,7 +282,7 @@ static ssize_t mt_set_quirks(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct mt_device *td = hid_get_drvdata(hdev); unsigned long val; @@ -357,8 +357,19 @@ static void mt_feature_mapping(struct hid_device *hdev, break; } - td->inputmode = field->report->id; - td->inputmode_index = usage->usage_index; + if (td->inputmode < 0) { + td->inputmode = field->report->id; + td->inputmode_index = usage->usage_index; + } else { + /* + * Some elan panels wrongly declare 2 input mode + * features, and silently ignore when we set the + * value in the second field. Skip the second feature + * and hope for the best. + */ + dev_info(&hdev->dev, + "Ignoring the extra HID_DG_INPUTMODE\n"); + } break; case HID_DG_CONTACTMAX: @@ -486,6 +497,11 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, mt_store_field(usage, td, hi); return 1; case HID_DG_CONFIDENCE: + if (cls->name == MT_CLS_WIN_8 && + field->application == HID_DG_TOUCHPAD) { + cls->quirks &= ~MT_QUIRK_ALWAYS_VALID; + cls->quirks |= MT_QUIRK_VALID_IS_CONFIDENCE; + } mt_store_field(usage, td, hi); return 1; case HID_DG_TIPSWITCH: diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 756d1ef..1b0084d 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -173,7 +173,7 @@ static ssize_t show_phys_width(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->sensor_physical_width); @@ -185,7 +185,7 @@ static ssize_t show_phys_height(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->sensor_physical_height); @@ -197,7 +197,7 @@ static ssize_t show_log_width(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->sensor_logical_width); @@ -209,7 +209,7 @@ static ssize_t show_log_height(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->sensor_logical_height); @@ -221,7 +221,7 @@ static ssize_t show_min_width(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->min_width * @@ -233,7 +233,7 @@ static ssize_t set_min_width(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); unsigned long val; @@ -256,7 +256,7 @@ static ssize_t show_min_height(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->min_height * @@ -268,7 +268,7 @@ static ssize_t set_min_height(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); unsigned long val; @@ -292,7 +292,7 @@ static ssize_t show_activate_slack(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->activate_slack); @@ -302,7 +302,7 @@ static ssize_t set_activate_slack(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); unsigned long val; @@ -325,7 +325,7 @@ static ssize_t show_activation_width(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->activation_width * @@ -337,7 +337,7 @@ static ssize_t set_activation_width(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); unsigned long val; @@ -361,7 +361,7 @@ static ssize_t show_activation_height(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", nd->activation_height * @@ -373,7 +373,7 @@ static ssize_t set_activation_height(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); unsigned long val; @@ -397,7 +397,7 @@ static ssize_t show_deactivate_slack(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); return sprintf(buf, "%d\n", -nd->deactivate_slack); @@ -407,7 +407,7 @@ static ssize_t set_deactivate_slack(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct ntrig_data *nd = hid_get_drvdata(hdev); unsigned long val; diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c index e994f9c..a802b4f 100644 --- a/drivers/hid/hid-picolcd_leds.c +++ b/drivers/hid/hid-picolcd_leds.c @@ -66,7 +66,7 @@ static void picolcd_led_set_brightness(struct led_classdev *led_cdev, int i, state = 0; dev = led_cdev->dev->parent; - hdev = container_of(dev, struct hid_device, dev); + hdev = to_hid_device(dev); data = hid_get_drvdata(hdev); if (!data) return; @@ -93,7 +93,7 @@ static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_c int i, value = 0; dev = led_cdev->dev->parent; - hdev = container_of(dev, struct hid_device, dev); + hdev = to_hid_device(dev); data = hid_get_drvdata(hdev); for (i = 0; i < 8; i++) if (led_cdev == data->led[i]) { diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 3a207c0..f095bf8 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -103,7 +103,7 @@ MODULE_PARM_DESC(enable, "Enable for the PC-MIDI virtual audio driver"); static ssize_t show_channel(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct pk_device *pk = hid_get_drvdata(hdev); dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel); @@ -116,7 +116,7 @@ static ssize_t show_channel(struct device *dev, static ssize_t store_channel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct pk_device *pk = hid_get_drvdata(hdev); unsigned channel = 0; @@ -140,7 +140,7 @@ static struct device_attribute *sysfs_device_attr_channel = { static ssize_t show_sustain(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct pk_device *pk = hid_get_drvdata(hdev); dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain); @@ -153,7 +153,7 @@ static ssize_t show_sustain(struct device *dev, static ssize_t store_sustain(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct pk_device *pk = hid_get_drvdata(hdev); unsigned sustain = 0; @@ -179,7 +179,7 @@ static struct device_attribute *sysfs_device_attr_sustain = { static ssize_t show_octave(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct pk_device *pk = hid_get_drvdata(hdev); dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave); @@ -192,7 +192,7 @@ static ssize_t show_octave(struct device *dev, static ssize_t store_octave(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct pk_device *pk = hid_get_drvdata(hdev); int octave = 0; diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c index 1948208..329c5d1 100644 --- a/drivers/hid/hid-roccat-arvo.c +++ b/drivers/hid/hid-roccat-arvo.c @@ -191,8 +191,7 @@ static ssize_t arvo_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -211,8 +210,7 @@ static ssize_t arvo_sysfs_read(struct file *fp, struct kobject *kobj, void *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index 02e28e9..8155ac5 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c @@ -134,8 +134,7 @@ ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj, char *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -158,8 +157,7 @@ ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c index bc62ed9..02db537 100644 --- a/drivers/hid/hid-roccat-isku.c +++ b/drivers/hid/hid-roccat-isku.c @@ -121,8 +121,7 @@ static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, char *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -144,8 +143,7 @@ static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index c292650..bf4675a 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -269,8 +269,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct kone_settings)) @@ -294,8 +293,7 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0, difference, old_profile; @@ -332,8 +330,7 @@ static BIN_ATTR(settings, 0660, kone_sysfs_read_settings, static ssize_t kone_sysfs_read_profilex(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct kone_profile)) @@ -353,8 +350,7 @@ static ssize_t kone_sysfs_read_profilex(struct file *fp, static ssize_t kone_sysfs_write_profilex(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); struct kone_profile *profile; diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index 5e99fcd..09e8fc7 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c @@ -87,8 +87,7 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, char *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -113,8 +112,7 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -193,8 +191,7 @@ static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ssize_t retval; @@ -212,8 +209,7 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ssize_t retval; diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 9660477..43617fb 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -128,8 +128,7 @@ static ssize_t kovaplus_sysfs_read(struct file *fp, struct kobject *kobj, char *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -154,8 +153,7 @@ static ssize_t kovaplus_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -221,8 +219,7 @@ static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ssize_t retval; @@ -240,8 +237,7 @@ static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ssize_t retval; diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c index 65e2e76..ac1a731 100644 --- a/drivers/hid/hid-roccat-lua.c +++ b/drivers/hid/hid-roccat-lua.c @@ -30,7 +30,7 @@ static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj, char *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -52,7 +52,7 @@ static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 47d7e74..b30aa7b 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c @@ -90,8 +90,7 @@ static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj, char *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -116,8 +115,7 @@ static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj, void const *buf, loff_t off, size_t count, size_t real_size, uint command) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval; @@ -191,8 +189,7 @@ static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ssize_t retval; @@ -210,8 +207,7 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ssize_t retval; @@ -248,8 +244,7 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; + struct device *dev = kobj_to_dev(kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0; diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 92870cd..58ed8f2 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -794,6 +794,9 @@ static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE_LENOVO_YOGA2), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE, + USB_DEVICE_ID_ITE_LENOVO_YOGA900), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) }, { } diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 774cd22..9b8db0e 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1028,6 +1028,7 @@ struct sony_sc { struct led_classdev *leds[MAX_LEDS]; unsigned long quirks; struct work_struct state_worker; + void(*send_output_report)(struct sony_sc*); struct power_supply *battery; struct power_supply_desc battery_desc; int device_id; @@ -1044,6 +1045,7 @@ struct sony_sc { __u8 battery_charging; __u8 battery_capacity; __u8 led_state[MAX_LEDS]; + __u8 resume_led_state[MAX_LEDS]; __u8 led_delay_on[MAX_LEDS]; __u8 led_delay_off[MAX_LEDS]; __u8 led_count; @@ -1137,11 +1139,11 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, * the gyroscope values to corresponding axes so we need a * modified one. */ - if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) { + if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); rdesc = dualshock4_usb_rdesc; *rsize = sizeof(dualshock4_usb_rdesc); - } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) { + } else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n"); rdesc = dualshock4_bt_rdesc; *rsize = sizeof(dualshock4_bt_rdesc); @@ -1549,7 +1551,7 @@ static void sony_led_set_brightness(struct led_classdev *led, enum led_brightness value) { struct device *dev = led->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct sony_sc *drv_data; int n; @@ -1591,7 +1593,7 @@ static void sony_led_set_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); + struct hid_device *hdev = to_hid_device(dev); struct sony_sc *drv_data; int n; @@ -1614,7 +1616,7 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, unsigned long *delay_off) { struct device *dev = led->dev->parent; - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct sony_sc *drv_data = hid_get_drvdata(hdev); int n; __u8 new_on, new_off; @@ -1789,7 +1791,7 @@ error_leds: return ret; } -static void sixaxis_state_worker(struct work_struct *work) +static void sixaxis_send_output_report(struct sony_sc *sc) { static const union sixaxis_output_report_01 default_report = { .buf = { @@ -1803,7 +1805,6 @@ static void sixaxis_state_worker(struct work_struct *work) 0x00, 0x00, 0x00, 0x00, 0x00 } }; - struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); struct sixaxis_output_report *report = (struct sixaxis_output_report *)sc->output_report_dmabuf; int n; @@ -1846,9 +1847,8 @@ static void sixaxis_state_worker(struct work_struct *work) HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } -static void dualshock4_state_worker(struct work_struct *work) +static void dualshock4_send_output_report(struct sony_sc *sc) { - struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); struct hid_device *hdev = sc->hdev; __u8 *buf = sc->output_report_dmabuf; int offset; @@ -1893,9 +1893,8 @@ static void dualshock4_state_worker(struct work_struct *work) HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } -static void motion_state_worker(struct work_struct *work) +static void motion_send_output_report(struct sony_sc *sc) { - struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); struct hid_device *hdev = sc->hdev; struct motion_output_report_02 *report = (struct motion_output_report_02 *)sc->output_report_dmabuf; @@ -1914,6 +1913,18 @@ static void motion_state_worker(struct work_struct *work) hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); } +static inline void sony_send_output_report(struct sony_sc *sc) +{ + if (sc->send_output_report) + sc->send_output_report(sc); +} + +static void sony_state_worker(struct work_struct *work) +{ + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); + sc->send_output_report(sc); +} + static int sony_allocate_output_report(struct sony_sc *sc) { if ((sc->quirks & SIXAXIS_CONTROLLER) || @@ -2241,11 +2252,13 @@ static void sony_release_device_id(struct sony_sc *sc) } } -static inline void sony_init_work(struct sony_sc *sc, - void (*worker)(struct work_struct *)) +static inline void sony_init_output_report(struct sony_sc *sc, + void(*send_output_report)(struct sony_sc*)) { + sc->send_output_report = send_output_report; + if (!sc->worker_initialized) - INIT_WORK(&sc->state_worker, worker); + INIT_WORK(&sc->state_worker, sony_state_worker); sc->worker_initialized = 1; } @@ -2319,7 +2332,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; ret = sixaxis_set_operational_usb(hdev); - sony_init_work(sc, sixaxis_state_worker); + sony_init_output_report(sc, sixaxis_send_output_report); } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || (sc->quirks & NAVIGATION_CONTROLLER_BT)) { /* @@ -2328,7 +2341,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) */ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; ret = sixaxis_set_operational_bt(hdev); - sony_init_work(sc, sixaxis_state_worker); + sony_init_output_report(sc, sixaxis_send_output_report); } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { /* @@ -2343,9 +2356,9 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) } } - sony_init_work(sc, dualshock4_state_worker); + sony_init_output_report(sc, dualshock4_send_output_report); } else if (sc->quirks & MOTION_CONTROLLER) { - sony_init_work(sc, motion_state_worker); + sony_init_output_report(sc, motion_send_output_report); } else { ret = 0; } @@ -2421,6 +2434,56 @@ static void sony_remove(struct hid_device *hdev) hid_hw_stop(hdev); } +#ifdef CONFIG_PM + +static int sony_suspend(struct hid_device *hdev, pm_message_t message) +{ + /* + * On suspend save the current LED state, + * stop running force-feedback and blank the LEDS. + */ + if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) { + struct sony_sc *sc = hid_get_drvdata(hdev); + +#ifdef CONFIG_SONY_FF + sc->left = sc->right = 0; +#endif + + memcpy(sc->resume_led_state, sc->led_state, + sizeof(sc->resume_led_state)); + memset(sc->led_state, 0, sizeof(sc->led_state)); + + sony_send_output_report(sc); + } + + return 0; +} + +static int sony_resume(struct hid_device *hdev) +{ + /* Restore the state of controller LEDs on resume */ + if (SONY_LED_SUPPORT) { + struct sony_sc *sc = hid_get_drvdata(hdev); + + memcpy(sc->led_state, sc->resume_led_state, + sizeof(sc->led_state)); + + /* + * The Sixaxis and navigation controllers on USB need to be + * reinitialized on resume or they won't behave properly. + */ + if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || + (sc->quirks & NAVIGATION_CONTROLLER_USB)) + sixaxis_set_operational_usb(sc->hdev); + + sony_set_leds(sc); + } + + return 0; +} + +#endif + static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, @@ -2470,7 +2533,13 @@ static struct hid_driver sony_driver = { .probe = sony_probe, .remove = sony_remove, .report_fixup = sony_report_fixup, - .raw_event = sony_raw_event + .raw_event = sony_raw_event, + +#ifdef CONFIG_PM + .suspend = sony_suspend, + .resume = sony_resume, + .reset_resume = sony_resume, +#endif }; static int __init sony_init(void) diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index 3edd4ac..ec18768 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -141,7 +141,7 @@ static void steelseries_srws1_led_all_set_brightness(struct led_classdev *led_cd enum led_brightness value) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -160,7 +160,7 @@ static void steelseries_srws1_led_all_set_brightness(struct led_classdev *led_cd static enum led_brightness steelseries_srws1_led_all_get_brightness(struct led_classdev *led_cdev) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); struct steelseries_srws1_data *drv_data; drv_data = hid_get_drvdata(hid); @@ -177,7 +177,7 @@ static void steelseries_srws1_led_set_brightness(struct led_classdev *led_cdev, enum led_brightness value) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid); int i, state = 0; @@ -205,7 +205,7 @@ static void steelseries_srws1_led_set_brightness(struct led_classdev *led_cdev, static enum led_brightness steelseries_srws1_led_get_brightness(struct led_classdev *led_cdev) { struct device *dev = led_cdev->dev->parent; - struct hid_device *hid = container_of(dev, struct hid_device, dev); + struct hid_device *hid = to_hid_device(dev); struct steelseries_srws1_data *drv_data; int i, value = 0; diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 05e23c4..4390eee 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c @@ -296,14 +296,12 @@ static const struct wiimod_ops wiimod_battery = { static enum led_brightness wiimod_led_get(struct led_classdev *led_dev) { - struct wiimote_data *wdata; struct device *dev = led_dev->dev->parent; + struct wiimote_data *wdata = dev_to_wii(dev); int i; unsigned long flags; bool value = false; - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - for (i = 0; i < 4; ++i) { if (wdata->leds[i] == led_dev) { spin_lock_irqsave(&wdata->state.lock, flags); @@ -319,14 +317,12 @@ static enum led_brightness wiimod_led_get(struct led_classdev *led_dev) static void wiimod_led_set(struct led_classdev *led_dev, enum led_brightness value) { - struct wiimote_data *wdata; struct device *dev = led_dev->dev->parent; + struct wiimote_data *wdata = dev_to_wii(dev); int i; unsigned long flags; __u8 state, flag; - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - for (i = 0; i < 4; ++i) { if (wdata->leds[i] == led_dev) { flag = WIIPROTO_FLAG_LED(i + 1); diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 875694d..510ca77 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h @@ -256,8 +256,7 @@ enum wiiproto_reqs { WIIPROTO_REQ_MAX }; -#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ - dev)) +#define dev_to_wii(pdev) hid_get_drvdata(to_hid_device(pdev)) void __wiimote_schedule(struct wiimote_data *wdata); diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 10bd8e6..b921693 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -151,6 +151,7 @@ struct i2c_hid { struct i2c_hid_platform_data pdata; bool irq_wake_enabled; + struct mutex reset_lock; }; static int __i2c_hid_command(struct i2c_client *client, @@ -356,9 +357,16 @@ static int i2c_hid_hwreset(struct i2c_client *client) i2c_hid_dbg(ihid, "%s\n", __func__); + /* + * This prevents sending feature reports while the device is + * being reset. Otherwise we may lose the reset complete + * interrupt. + */ + mutex_lock(&ihid->reset_lock); + ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); if (ret) - return ret; + goto out_unlock; i2c_hid_dbg(ihid, "resetting...\n"); @@ -366,10 +374,11 @@ static int i2c_hid_hwreset(struct i2c_client *client) if (ret) { dev_err(&client->dev, "failed to reset device.\n"); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); - return ret; } - return 0; +out_unlock: + mutex_unlock(&ihid->reset_lock); + return ret; } static void i2c_hid_get_input(struct i2c_hid *ihid) @@ -587,12 +596,15 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, unsigned char report_type, bool use_data) { struct i2c_client *client = hid->driver_data; + struct i2c_hid *ihid = i2c_get_clientdata(client); int report_id = buf[0]; int ret; if (report_type == HID_INPUT_REPORT) return -EINVAL; + mutex_lock(&ihid->reset_lock); + if (report_id) { buf++; count--; @@ -605,6 +617,8 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, if (report_id && ret >= 0) ret++; /* add report_id to the number of transfered bytes */ + mutex_unlock(&ihid->reset_lock); + return ret; } @@ -990,6 +1004,7 @@ static int i2c_hid_probe(struct i2c_client *client, ihid->wHIDDescRegister = cpu_to_le16(hidRegister); init_waitqueue_head(&ihid->wait); + mutex_init(&ihid->reset_lock); /* we need to allocate the command buffer without knowing the maximum * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the @@ -1184,7 +1199,6 @@ MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table); static struct i2c_driver i2c_hid_driver = { .driver = { .name = "i2c_hid", - .owner = THIS_MODULE, .pm = &i2c_hid_pm, .acpi_match_table = ACPI_PTR(i2c_hid_acpi_match), .of_match_table = of_match_ptr(i2c_hid_of_match), diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 36712e9..ad71160 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -274,10 +274,10 @@ static void hid_irq_in(struct urb *urb) switch (urb->status) { case 0: /* success */ - usbhid_mark_busy(usbhid); usbhid->retry_delay = 0; if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) break; + usbhid_mark_busy(usbhid); if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { hid_input_report(urb->context, HID_INPUT_REPORT, urb->transfer_buffer, @@ -477,8 +477,6 @@ static void hid_ctrl(struct urb *urb) struct usbhid_device *usbhid = hid->driver_data; int unplug = 0, status = urb->status; - spin_lock(&usbhid->lock); - switch (status) { case 0: /* success */ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) @@ -498,6 +496,8 @@ static void hid_ctrl(struct urb *urb) hid_warn(urb->dev, "ctrl urb status %d received\n", status); } + spin_lock(&usbhid->lock); + if (unplug) { usbhid->ctrltail = usbhid->ctrlhead; } else { diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 94bb137..2324520 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -84,6 +84,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL }, diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 807922b..fa47d66 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -96,7 +96,7 @@ struct usbhid_device { }; #define hid_to_usb_dev(hid_dev) \ - container_of(hid_dev->dev.parent->parent, struct usb_device, dev) + to_usb_device(hid_dev->dev.parent->parent) #endif diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index c7a3b79..5cb21dd 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -686,7 +686,7 @@ out: static ssize_t wacom_led_select_store(struct device *dev, int set_id, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct wacom *wacom = hid_get_drvdata(hdev); unsigned int id; int err; @@ -714,7 +714,7 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \ static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ - struct hid_device *hdev = container_of(dev, struct hid_device, dev);\ + struct hid_device *hdev = to_hid_device(dev);\ struct wacom *wacom = hid_get_drvdata(hdev); \ return scnprintf(buf, PAGE_SIZE, "%d\n", \ wacom->led.select[SET_ID]); \ @@ -750,7 +750,7 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest, static ssize_t wacom_##name##_luminance_store(struct device *dev, \ struct device_attribute *attr, const char *buf, size_t count) \ { \ - struct hid_device *hdev = container_of(dev, struct hid_device, dev);\ + struct hid_device *hdev = to_hid_device(dev);\ struct wacom *wacom = hid_get_drvdata(hdev); \ \ return wacom_luminance_store(wacom, &wacom->led.field, \ @@ -773,7 +773,7 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum); static ssize_t wacom_button_image_store(struct device *dev, int button_id, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct wacom *wacom = hid_get_drvdata(hdev); int err; unsigned len; @@ -1097,7 +1097,7 @@ static ssize_t wacom_show_speed(struct device *dev, struct device_attribute *attr, char *buf) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct wacom *wacom = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%i\n", wacom->wacom_wac.bt_high_speed); @@ -1107,7 +1107,7 @@ static ssize_t wacom_store_speed(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct hid_device *hdev = to_hid_device(dev); struct wacom *wacom = hid_get_drvdata(hdev); u8 new_speed; @@ -1130,8 +1130,8 @@ static ssize_t wacom_show_remote_mode(struct kobject *kobj, struct kobj_attribute *kattr, char *buf, int index) { - struct device *dev = container_of(kobj->parent, struct device, kobj); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct device *dev = kobj_to_dev(kobj->parent); + struct hid_device *hdev = to_hid_device(dev); struct wacom *wacom = hid_get_drvdata(hdev); u8 mode; @@ -1241,8 +1241,8 @@ static ssize_t wacom_store_unpair_remote(struct kobject *kobj, const char *buf, size_t count) { unsigned char selector = 0; - struct device *dev = container_of(kobj->parent, struct device, kobj); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); + struct device *dev = kobj_to_dev(kobj->parent); + struct hid_device *hdev = to_hid_device(dev); struct wacom *wacom = hid_get_drvdata(hdev); int err; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 3aeddc2..99ef77f 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2397,7 +2397,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { if (features->touch_max) features->device_type |= WACOM_DEVICETYPE_TOUCH; - if (features->type >= INTUOSHT || features->type <= BAMBOO_PT) + if (features->type >= INTUOSHT && features->type <= BAMBOO_PT) features->device_type |= WACOM_DEVICETYPE_PAD; features->x_max = 4096; @@ -3142,7 +3142,8 @@ static const struct wacom_features wacom_features_0x32F = WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_0x336 = { "Wacom DTU1141", 23472, 13203, 1023, 0, - DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; + DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_0x57 = { "Wacom DTK2241", 95640, 54060, 2047, 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, |