diff options
Diffstat (limited to 'drivers')
33 files changed, 809 insertions, 574 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c6f7a694f67a..7e89288b1537 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 bcefb9ebb026..58551964ce86 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 7afc3fcc122c..7c38bfa05fac 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 2886b645ced7..acfb522a432a 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 0d6f135e266c..a298fbd8db6b 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 8b78a7f1f779..b6ff6e78ac54 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -510,6 +510,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 @@ -615,6 +616,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 @@ -664,6 +666,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 2ba6bf69b7d0..bcfaf32d9e5e 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 8979f1fd5208..0125e356bd8d 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-lg4ff.c b/drivers/hid/hid-lg4ff.c index fbddcb37ae98..af3a8ec8a746 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 5fd97860aec4..bd2ab476c65e 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) +{ |