Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: - appoint Benjamin Tissoires as co-maintainer / designated reviewer - sysfs report_descriptor visibility fix for unclaimed devices, from Andy Lutomirski - suspend/resume fixes for Sony driver from Frank Praznik - IRQ deadlock fix from Ioan-Adrian Ratiu - hid-i2c fixes affecting (at least) Yoga 900 from Mika Westerberg and Srinivas Pandruvada - a lot of new device support (especially, but not limited to, Wacom) and assorted small misc fixes - almost complete G920 support; the only bit that is missing is switching the device to HID mode automatically; Simon Wood and Michal Maly are working on it. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (46 commits) Revert "INPUT: xpad: switch Logitech G920 Wheel into HID mode" HID: sensor-hub: Add quirk for Lenovo Yoga 900 with ITE Chips HID: Add new PID for Microchip Pick16F1454 HID: wacom: Use correct report to query pen ID from INTUOSHT2 devices HID: i2c-hid: Prevent sending reports from racing with device reset HID: use kobj_to_dev() HID: wiimote: use dev_to_wii() HID: add a new helper to_hid_driver() HID: use to_hid_device() HID: move to_hid_device() to hid.h HID: usbhid: use to_usb_device HID: corsair: Convert to use module_hid_driver HID: input: ignore the battery in OKLICK Laser BTmouse HID: wacom: Fix pad button range for CINTIQ_COMPANION_2 HID: wacom: Fix touchring value reporting HID: wacom: Report 'strip2' values in ABS_RY HID: wacom: Limit touchstrip data to 13 bits HID: wacom: bitwise vs logical ORs HID: wacom: Apply lowres quirk to BAMBOO_TOUCH devices HID: enable hid device to suspend/resume asynchronously ...
This commit is contained in:
commit
c2848f2eef
@ -4984,6 +4984,7 @@ F: arch/*/include/asm/suspend*.h
|
||||
|
||||
HID CORE LAYER
|
||||
M: Jiri Kosina <jikos@kernel.org>
|
||||
R: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
|
||||
S: Maintained
|
||||
@ -11162,6 +11163,7 @@ F: include/linux/usb/gadget*
|
||||
|
||||
USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
|
||||
M: Jiri Kosina <jikos@kernel.org>
|
||||
R: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
|
||||
S: Maintained
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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]) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) },
|
||||
{ }
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
@ -1353,8 +1353,7 @@ static void wacom_clean_inputs(struct wacom *wacom)
|
||||
else
|
||||
input_free_device(wacom->wacom_wac.pad_input);
|
||||
}
|
||||
if (wacom->remote_dir)
|
||||
kobject_put(wacom->remote_dir);
|
||||
kobject_put(wacom->remote_dir);
|
||||
wacom->wacom_wac.pen_input = NULL;
|
||||
wacom->wacom_wac.touch_input = NULL;
|
||||
wacom->wacom_wac.pad_input = NULL;
|
||||
|
@ -34,6 +34,9 @@
|
||||
*/
|
||||
#define WACOM_CONTACT_AREA_SCALE 2607
|
||||
|
||||
static void wacom_report_numbered_buttons(struct input_dev *input_dev,
|
||||
int button_count, int mask);
|
||||
|
||||
/*
|
||||
* Percent of battery capacity for Graphire.
|
||||
* 8th value means AC online and show 100% capacity.
|
||||
@ -436,16 +439,142 @@ exit:
|
||||
static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
|
||||
{
|
||||
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
struct hid_report *r;
|
||||
struct hid_report_enum *re;
|
||||
|
||||
re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
|
||||
r = re->report_id_hash[WACOM_REPORT_INTUOSREAD];
|
||||
if (features->type == INTUOSHT2)
|
||||
r = re->report_id_hash[WACOM_REPORT_INTUOSHT2_ID];
|
||||
else
|
||||
r = re->report_id_hash[WACOM_REPORT_INTUOS_ID1];
|
||||
if (r) {
|
||||
hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
|
||||
}
|
||||
}
|
||||
|
||||
static int wacom_intuos_pad(struct wacom_wac *wacom)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
struct input_dev *input = wacom->pad_input;
|
||||
int i;
|
||||
int buttons = 0, nbuttons = features->numbered_buttons;
|
||||
int keys = 0, nkeys = 0;
|
||||
int ring1 = 0, ring2 = 0;
|
||||
int strip1 = 0, strip2 = 0;
|
||||
bool prox = false;
|
||||
|
||||
/* pad packets. Works as a second tool and is always in prox */
|
||||
if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
|
||||
data[0] == WACOM_REPORT_CINTIQPAD))
|
||||
return 0;
|
||||
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
||||
buttons = (data[3] << 1) | (data[2] & 0x01);
|
||||
ring1 = data[1];
|
||||
} else if (features->type == DTK) {
|
||||
buttons = data[6];
|
||||
} else if (features->type == WACOM_13HD) {
|
||||
buttons = (data[4] << 1) | (data[3] & 0x01);
|
||||
} else if (features->type == WACOM_24HD) {
|
||||
buttons = (data[8] << 8) | data[6];
|
||||
ring1 = data[1];
|
||||
ring2 = data[2];
|
||||
|
||||
/*
|
||||
* Three "buttons" are available on the 24HD which are
|
||||
* physically implemented as a touchstrip. Each button
|
||||
* is approximately 3 bits wide with a 2 bit spacing.
|
||||
* The raw touchstrip bits are stored at:
|
||||
* ((data[3] & 0x1f) << 8) | data[4])
|
||||
*/
|
||||
nkeys = 3;
|
||||
keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
|
||||
((data[4] & 0xE0) ? 1<<1 : 0) |
|
||||
((data[4] & 0x07) ? 1<<0 : 0);
|
||||
} else if (features->type == WACOM_27QHD) {
|
||||
nkeys = 3;
|
||||
keys = data[2] & 0x07;
|
||||
|
||||
input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
|
||||
input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
|
||||
input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
|
||||
} else if (features->type == CINTIQ_HYBRID) {
|
||||
/*
|
||||
* Do not send hardware buttons under Android. They
|
||||
* are already sent to the system through GPIO (and
|
||||
* have different meaning).
|
||||
*
|
||||
* d-pad right -> data[4] & 0x10
|
||||
* d-pad up -> data[4] & 0x20
|
||||
* d-pad left -> data[4] & 0x40
|
||||
* d-pad down -> data[4] & 0x80
|
||||
* d-pad center -> data[3] & 0x01
|
||||
*/
|
||||
buttons = (data[4] << 1) | (data[3] & 0x01);
|
||||
} else if (features->type == CINTIQ_COMPANION_2) {
|
||||
/* d-pad right -> data[4] & 0x10
|
||||
* d-pad up -> data[4] & 0x20
|
||||
* d-pad left -> data[4] & 0x40
|
||||
* d-pad down -> data[4] & 0x80
|
||||
* d-pad center -> data[3] & 0x01
|
||||
*/
|
||||
buttons = ((data[2] >> 4) << 7) |
|
||||
((data[1] & 0x04) << 6) |
|
||||
((data[2] & 0x0F) << 2) |
|
||||
(data[1] & 0x03);
|
||||
} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
|
||||
/*
|
||||
* ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
|
||||
* addition to the mechanical switch. Switch data is
|
||||
* stored in data[4], capacitive data in data[5].
|
||||
*
|
||||
* Touch ring mode switch (data[3]) has no capacitive sensor
|
||||
*/
|
||||
buttons = (data[4] << 1) | (data[3] & 0x01);
|
||||
ring1 = data[2];
|
||||
} else {
|
||||
if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
|
||||
buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
|
||||
(data[6] << 1) | (data[5] & 0x01);
|
||||
|
||||
if (features->type == WACOM_22HD) {
|
||||
nkeys = 3;
|
||||
keys = data[9] & 0x07;
|
||||
}
|
||||
} else {
|
||||
buttons = ((data[6] & 0x10) << 10) |
|
||||
((data[5] & 0x10) << 9) |
|
||||
((data[6] & 0x0F) << 4) |
|
||||
(data[5] & 0x0F);
|
||||
}
|
||||
strip1 = ((data[1] & 0x1f) << 8) | data[2];
|
||||
strip2 = ((data[3] & 0x1f) << 8) | data[4];
|
||||
}
|
||||
|
||||
prox = (buttons & ~(~0 << nbuttons)) | (keys & ~(~0 << nkeys)) |
|
||||
(ring1 & 0x80) | (ring2 & 0x80) | strip1 | strip2;
|
||||
|
||||
wacom_report_numbered_buttons(input, nbuttons, buttons);
|
||||
|
||||
for (i = 0; i < nkeys; i++)
|
||||
input_report_key(input, KEY_PROG1 + i, keys & (1 << i));
|
||||
|
||||
input_report_abs(input, ABS_RX, strip1);
|
||||
input_report_abs(input, ABS_RY, strip2);
|
||||
|
||||
input_report_abs(input, ABS_WHEEL, (ring1 & 0x80) ? (ring1 & 0x7f) : 0);
|
||||
input_report_abs(input, ABS_THROTTLE, (ring2 & 0x80) ? (ring2 & 0x7f) : 0);
|
||||
|
||||
input_report_key(input, wacom->tool[1], prox ? 1 : 0);
|
||||
input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);
|
||||
|
||||
input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wacom_intuos_inout(struct wacom_wac *wacom)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
@ -755,19 +884,40 @@ static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wacom_intuos_general(struct wacom_wac *wacom)
|
||||
static int wacom_intuos_general(struct wacom_wac *wacom)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
struct input_dev *input = wacom->pen_input;
|
||||
unsigned int t;
|
||||
int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
|
||||
unsigned char type = (data[1] >> 1) & 0x0F;
|
||||
unsigned int x, y, distance, t;
|
||||
|
||||
/* general pen packet */
|
||||
if ((data[1] & 0xb8) == 0xa0) {
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
if (features->pressure_max == 2047) {
|
||||
t = (t << 1) | (data[1] & 1);
|
||||
}
|
||||
if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_CINTIQ &&
|
||||
data[0] != WACOM_REPORT_INTUOS_PEN)
|
||||
return 0;
|
||||
|
||||
x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1);
|
||||
y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1);
|
||||
distance = data[9] >> 2;
|
||||
if (features->type < INTUOS3S) {
|
||||
x >>= 1;
|
||||
y >>= 1;
|
||||
distance >>= 1;
|
||||
}
|
||||
input_report_abs(input, ABS_X, x);
|
||||
input_report_abs(input, ABS_Y, y);
|
||||
input_report_abs(input, ABS_DISTANCE, distance);
|
||||
|
||||
switch (type) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
/* general pen packet */
|
||||
t = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | (data[1] & 1);
|
||||
if (features->pressure_max < 2047)
|
||||
t >>= 1;
|
||||
input_report_abs(input, ABS_PRESSURE, t);
|
||||
if (features->type != INTUOSHT2) {
|
||||
input_report_abs(input, ABS_TILT_X,
|
||||
@ -777,29 +927,112 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
|
||||
input_report_key(input, BTN_STYLUS, data[1] & 2);
|
||||
input_report_key(input, BTN_STYLUS2, data[1] & 4);
|
||||
input_report_key(input, BTN_TOUCH, t > 10);
|
||||
}
|
||||
break;
|
||||
|
||||
/* airbrush second packet */
|
||||
if ((data[1] & 0xbc) == 0xb4) {
|
||||
case 0x0a:
|
||||
/* airbrush second packet */
|
||||
input_report_abs(input, ABS_WHEEL,
|
||||
(data[6] << 2) | ((data[7] >> 6) & 3));
|
||||
input_report_abs(input, ABS_TILT_X,
|
||||
(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
|
||||
input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
/* Rotation packet */
|
||||
if (features->type >= INTUOS3S) {
|
||||
/* I3 marker pen rotation */
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
|
||||
((t-1) / 2 + 450)) : (450 - t / 2) ;
|
||||
input_report_abs(input, ABS_Z, t);
|
||||
} else {
|
||||
/* 4D mouse 2nd packet */
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
|
||||
((t - 1) / 2) : -t / 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
/* 4D mouse 1st packet */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
||||
|
||||
input_report_key(input, BTN_SIDE, data[8] & 0x20);
|
||||
input_report_key(input, BTN_EXTRA, data[8] & 0x10);
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
/* I4 mouse */
|
||||
input_report_key(input, BTN_LEFT, data[6] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[6] & 0x04);
|
||||
input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
|
||||
- ((data[7] & 0x40) >> 6));
|
||||
input_report_key(input, BTN_SIDE, data[6] & 0x08);
|
||||
input_report_key(input, BTN_EXTRA, data[6] & 0x10);
|
||||
|
||||
input_report_abs(input, ABS_TILT_X,
|
||||
(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
|
||||
input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
||||
/* 2D mouse packet */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x04);
|
||||
input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
|
||||
input_report_key(input, BTN_RIGHT, data[8] & 0x10);
|
||||
input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
|
||||
- ((data[8] & 0x02) >> 1));
|
||||
|
||||
/* I3 2D mouse side buttons */
|
||||
if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
|
||||
input_report_key(input, BTN_SIDE, data[8] & 0x40);
|
||||
input_report_key(input, BTN_EXTRA, data[8] & 0x20);
|
||||
}
|
||||
}
|
||||
else if (wacom->tool[idx] == BTN_TOOL_LENS) {
|
||||
/* Lens cursor packets */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
||||
input_report_key(input, BTN_SIDE, data[8] & 0x10);
|
||||
input_report_key(input, BTN_EXTRA, data[8] & 0x08);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
case 0x09:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
/* unhandled */
|
||||
break;
|
||||
}
|
||||
|
||||
input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
|
||||
input_report_key(input, wacom->tool[idx], 1);
|
||||
input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
|
||||
wacom->reporting_data = true;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
struct input_dev *input = wacom->pen_input;
|
||||
unsigned int t;
|
||||
int idx = 0, result;
|
||||
int result;
|
||||
|
||||
if (data[0] != WACOM_REPORT_PENABLED &&
|
||||
data[0] != WACOM_REPORT_INTUOSREAD &&
|
||||
data[0] != WACOM_REPORT_INTUOSWRITE &&
|
||||
data[0] != WACOM_REPORT_INTUOS_ID1 &&
|
||||
data[0] != WACOM_REPORT_INTUOS_ID2 &&
|
||||
data[0] != WACOM_REPORT_INTUOSPAD &&
|
||||
data[0] != WACOM_REPORT_INTUOS_PEN &&
|
||||
data[0] != WACOM_REPORT_CINTIQ &&
|
||||
@ -810,339 +1043,22 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* tool number */
|
||||
if (features->type == INTUOS)
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* pad packets. Works as a second tool and is always in prox */
|
||||
if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
|
||||
data[0] == WACOM_REPORT_CINTIQPAD) {
|
||||
input = wacom->pad_input;
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
||||
input_report_key(input, BTN_0, (data[2] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[3] & 0x01));
|
||||
input_report_key(input, BTN_2, (data[3] & 0x02));
|
||||
input_report_key(input, BTN_3, (data[3] & 0x04));
|
||||
input_report_key(input, BTN_4, (data[3] & 0x08));
|
||||
input_report_key(input, BTN_5, (data[3] & 0x10));
|
||||
input_report_key(input, BTN_6, (data[3] & 0x20));
|
||||
if (data[1] & 0x80) {
|
||||
input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
|
||||
} else {
|
||||
/* Out of proximity, clear wheel value. */
|
||||
input_report_abs(input, ABS_WHEEL, 0);
|
||||
}
|
||||
if (features->type != INTUOS4S) {
|
||||
input_report_key(input, BTN_7, (data[3] & 0x40));
|
||||
input_report_key(input, BTN_8, (data[3] & 0x80));
|
||||
}
|
||||
if (data[1] | (data[2] & 0x01) | data[3]) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
} else if (features->type == DTK) {
|
||||
input_report_key(input, BTN_0, (data[6] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[6] & 0x02));
|
||||
input_report_key(input, BTN_2, (data[6] & 0x04));
|
||||
input_report_key(input, BTN_3, (data[6] & 0x08));
|
||||
input_report_key(input, BTN_4, (data[6] & 0x10));
|
||||
input_report_key(input, BTN_5, (data[6] & 0x20));
|
||||
if (data[6] & 0x3f) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
} else if (features->type == WACOM_13HD) {
|
||||
input_report_key(input, BTN_0, (data[3] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[4] & 0x01));
|
||||
input_report_key(input, BTN_2, (data[4] & 0x02));
|
||||
input_report_key(input, BTN_3, (data[4] & 0x04));
|
||||
input_report_key(input, BTN_4, (data[4] & 0x08));
|
||||
input_report_key(input, BTN_5, (data[4] & 0x10));
|
||||
input_report_key(input, BTN_6, (data[4] & 0x20));
|
||||
input_report_key(input, BTN_7, (data[4] & 0x40));
|
||||
input_report_key(input, BTN_8, (data[4] & 0x80));
|
||||
if ((data[3] & 0x01) | data[4]) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
} else if (features->type == WACOM_24HD) {
|
||||
input_report_key(input, BTN_0, (data[6] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[6] & 0x02));
|
||||
input_report_key(input, BTN_2, (data[6] & 0x04));
|
||||
input_report_key(input, BTN_3, (data[6] & 0x08));
|
||||
input_report_key(input, BTN_4, (data[6] & 0x10));
|
||||
input_report_key(input, BTN_5, (data[6] & 0x20));
|
||||
input_report_key(input, BTN_6, (data[6] & 0x40));
|
||||
input_report_key(input, BTN_7, (data[6] & 0x80));
|
||||
input_report_key(input, BTN_8, (data[8] & 0x01));
|
||||
input_report_key(input, BTN_9, (data[8] & 0x02));
|
||||
input_report_key(input, BTN_A, (data[8] & 0x04));
|
||||
input_report_key(input, BTN_B, (data[8] & 0x08));
|
||||
input_report_key(input, BTN_C, (data[8] & 0x10));
|
||||
input_report_key(input, BTN_X, (data[8] & 0x20));
|
||||
input_report_key(input, BTN_Y, (data[8] & 0x40));
|
||||
input_report_key(input, BTN_Z, (data[8] & 0x80));
|
||||
|
||||
/*
|
||||
* Three "buttons" are available on the 24HD which are
|
||||
* physically implemented as a touchstrip. Each button
|
||||
* is approximately 3 bits wide with a 2 bit spacing.
|
||||
* The raw touchstrip bits are stored at:
|
||||
* ((data[3] & 0x1f) << 8) | data[4])
|
||||
*/
|
||||
input_report_key(input, KEY_PROG1, data[4] & 0x07);
|
||||
input_report_key(input, KEY_PROG2, data[4] & 0xE0);
|
||||
input_report_key(input, KEY_PROG3, data[3] & 0x1C);
|
||||
|
||||
if (data[1] & 0x80) {
|
||||
input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
|
||||
} else {
|
||||
/* Out of proximity, clear wheel value. */
|
||||
input_report_abs(input, ABS_WHEEL, 0);
|
||||
}
|
||||
|
||||
if (data[2] & 0x80) {
|
||||
input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
|
||||
} else {
|
||||
/* Out of proximity, clear second wheel value. */
|
||||
input_report_abs(input, ABS_THROTTLE, 0);
|
||||
}
|
||||
|
||||
if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
} else if (features->type == WACOM_27QHD) {
|
||||
input_report_key(input, KEY_PROG1, data[2] & 0x01);
|
||||
input_report_key(input, KEY_PROG2, data[2] & 0x02);
|
||||
input_report_key(input, KEY_PROG3, data[2] & 0x04);
|
||||
|
||||
input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
|
||||
input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
|
||||
input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
|
||||
if ((data[2] & 0x07) | data[4] | data[5] | data[6] | data[7] | data[8] | data[9]) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
} else if (features->type == CINTIQ_HYBRID) {
|
||||
/*
|
||||
* Do not send hardware buttons under Android. They
|
||||
* are already sent to the system through GPIO (and
|
||||
* have different meaning).
|
||||
*/
|
||||
input_report_key(input, BTN_1, (data[4] & 0x01));
|
||||
input_report_key(input, BTN_2, (data[4] & 0x02));
|
||||
input_report_key(input, BTN_3, (data[4] & 0x04));
|
||||
input_report_key(input, BTN_4, (data[4] & 0x08));
|
||||
|
||||
input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right */
|
||||
input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up */
|
||||
input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */
|
||||
input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */
|
||||
input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */
|
||||
|
||||
if (data[4] | (data[3] & 0x01)) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
|
||||
} else if (features->type == CINTIQ_COMPANION_2) {
|
||||
input_report_key(input, BTN_1, (data[1] & 0x02));
|
||||
input_report_key(input, BTN_2, (data[2] & 0x01));
|
||||
input_report_key(input, BTN_3, (data[2] & 0x02));
|
||||
input_report_key(input, BTN_4, (data[2] & 0x04));
|
||||
input_report_key(input, BTN_5, (data[2] & 0x08));
|
||||
input_report_key(input, BTN_6, (data[1] & 0x04));
|
||||
|
||||
input_report_key(input, BTN_7, (data[2] & 0x10)); /* Right */
|
||||
input_report_key(input, BTN_8, (data[2] & 0x20)); /* Up */
|
||||
input_report_key(input, BTN_9, (data[2] & 0x40)); /* Left */
|
||||
input_report_key(input, BTN_A, (data[2] & 0x80)); /* Down */
|
||||
input_report_key(input, BTN_0, (data[1] & 0x01)); /* Center */
|
||||
|
||||
if (data[2] | (data[1] & 0x07)) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
|
||||
} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
|
||||
int i;
|
||||
|
||||
/* Touch ring mode switch has no capacitive sensor */
|
||||
input_report_key(input, BTN_0, (data[3] & 0x01));
|
||||
|
||||
/*
|
||||
* ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
|
||||
* addition to the mechanical switch. Switch data is
|
||||
* stored in data[4], capacitive data in data[5].
|
||||
*/
|
||||
for (i = 0; i < 8; i++)
|
||||
input_report_key(input, BTN_1 + i, data[4] & (1 << i));
|
||||
|
||||
if (data[2] & 0x80) {
|
||||
input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f));
|
||||
} else {
|
||||
/* Out of proximity, clear wheel value. */
|
||||
input_report_abs(input, ABS_WHEEL, 0);
|
||||
}
|
||||
|
||||
if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
} else {
|
||||
if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
|
||||
input_report_key(input, BTN_0, (data[5] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[6] & 0x01));
|
||||
input_report_key(input, BTN_2, (data[6] & 0x02));
|
||||
input_report_key(input, BTN_3, (data[6] & 0x04));
|
||||
input_report_key(input, BTN_4, (data[6] & 0x08));
|
||||
input_report_key(input, BTN_5, (data[6] & 0x10));
|
||||
input_report_key(input, BTN_6, (data[6] & 0x20));
|
||||
input_report_key(input, BTN_7, (data[6] & 0x40));
|
||||
input_report_key(input, BTN_8, (data[6] & 0x80));
|
||||
input_report_key(input, BTN_9, (data[7] & 0x01));
|
||||
input_report_key(input, BTN_A, (data[8] & 0x01));
|
||||
input_report_key(input, BTN_B, (data[8] & 0x02));
|
||||
input_report_key(input, BTN_C, (data[8] & 0x04));
|
||||
input_report_key(input, BTN_X, (data[8] & 0x08));
|
||||
input_report_key(input, BTN_Y, (data[8] & 0x10));
|
||||
input_report_key(input, BTN_Z, (data[8] & 0x20));
|
||||
input_report_key(input, BTN_BASE, (data[8] & 0x40));
|
||||
input_report_key(input, BTN_BASE2, (data[8] & 0x80));
|
||||
|
||||
if (features->type == WACOM_22HD) {
|
||||
input_report_key(input, KEY_PROG1, data[9] & 0x01);
|
||||
input_report_key(input, KEY_PROG2, data[9] & 0x02);
|
||||
input_report_key(input, KEY_PROG3, data[9] & 0x04);
|
||||
}
|
||||
} else {
|
||||
input_report_key(input, BTN_0, (data[5] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[5] & 0x02));
|
||||
input_report_key(input, BTN_2, (data[5] & 0x04));
|
||||
input_report_key(input, BTN_3, (data[5] & 0x08));
|
||||
input_report_key(input, BTN_4, (data[6] & 0x01));
|
||||
input_report_key(input, BTN_5, (data[6] & 0x02));
|
||||
input_report_key(input, BTN_6, (data[6] & 0x04));
|
||||
input_report_key(input, BTN_7, (data[6] & 0x08));
|
||||
input_report_key(input, BTN_8, (data[5] & 0x10));
|
||||
input_report_key(input, BTN_9, (data[6] & 0x10));
|
||||
}
|
||||
input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
|
||||
input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
|
||||
|
||||
if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
|
||||
data[2] | (data[3] & 0x1f) | data[4] | data[8] |
|
||||
(data[7] & 0x01)) {
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
} else {
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* process pad events */
|
||||
result = wacom_intuos_pad(wacom);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/* process in/out prox events */
|
||||
result = wacom_intuos_inout(wacom);
|
||||
if (result)
|
||||
return result - 1;
|
||||
|
||||
if (features->type >= INTUOS3S) {
|
||||
input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
|
||||
input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
|
||||
input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
|
||||
} else {
|
||||
input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2]));
|
||||
input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
|
||||
input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
|
||||
}
|
||||
return result - 1;
|
||||
|
||||
/* process general packets */
|
||||
wacom_intuos_general(wacom);
|
||||
result = wacom_intuos_general(wacom);
|
||||
if (result)
|
||||
return result - 1;
|
||||
|
||||
/* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
|
||||
if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
|
||||
|
||||
if (data[1] & 0x02) {
|
||||
/* Rotation packet */
|
||||
if (features->type >= INTUOS3S) {
|
||||
/* I3 marker pen rotation */
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
|
||||
((t-1) / 2 + 450)) : (450 - t / 2) ;
|
||||
input_report_abs(input, ABS_Z, t);
|
||||
} else {
|
||||
/* 4D mouse rotation packet */
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
|
||||
((t - 1) / 2) : -t / 2);
|
||||
}
|
||||
|
||||
} else if (!(data[1] & 0x10) && features->type < INTUOS3S) {
|
||||
/* 4D mouse packet */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
||||
|
||||
input_report_key(input, BTN_SIDE, data[8] & 0x20);
|
||||
input_report_key(input, BTN_EXTRA, data[8] & 0x10);
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
|
||||
|
||||
} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
||||
/* I4 mouse */
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOSPL) {
|
||||
input_report_key(input, BTN_LEFT, data[6] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[6] & 0x04);
|
||||
input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
|
||||
- ((data[7] & 0x40) >> 6));
|
||||
input_report_key(input, BTN_SIDE, data[6] & 0x08);
|
||||
input_report_key(input, BTN_EXTRA, data[6] & 0x10);
|
||||
|
||||
input_report_abs(input, ABS_TILT_X,
|
||||
(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
|
||||
input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
|
||||
} else {
|
||||
/* 2D mouse packet */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x04);
|
||||
input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
|
||||
input_report_key(input, BTN_RIGHT, data[8] & 0x10);
|
||||
input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
|
||||
- ((data[8] & 0x02) >> 1));
|
||||
|
||||
/* I3 2D mouse side buttons */
|
||||
if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
|
||||
input_report_key(input, BTN_SIDE, data[8] & 0x40);
|
||||
input_report_key(input, BTN_EXTRA, data[8] & 0x20);
|
||||
}
|
||||
}
|
||||
} else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
|
||||
features->type == INTUOS4L || features->type == INTUOS5L ||
|
||||
features->type == INTUOSPL) &&
|
||||
wacom->tool[idx] == BTN_TOOL_LENS) {
|
||||
/* Lens cursor packets */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
||||
input_report_key(input, BTN_SIDE, data[8] & 0x10);
|
||||
input_report_key(input, BTN_EXTRA, data[8] & 0x08);
|
||||
}
|
||||
}
|
||||
|
||||
input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
|
||||
input_report_key(input, wacom->tool[idx], 1);
|
||||
input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
|
||||
wacom->reporting_data = true;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int_dist(int x1, int y1, int x2, int y2)
|
||||
@ -2509,7 +2425,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
|
||||
/* quirk for bamboo touch with 2 low res touches */
|
||||
if (features->type == BAMBOO_PT &&
|
||||
if ((features->type == BAMBOO_PT || features->type == BAMBOO_TOUCH) &&
|
||||
features->pktlen == WACOM_PKGLEN_BBTOUCH) {
|
||||
features->x_max <<= 5;
|
||||
features->y_max <<= 5;
|
||||
@ -2806,6 +2722,19 @@ static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
|
||||
__set_bit(BTN_BASE + (i-16), input_dev->keybit);
|
||||
}
|
||||
|
||||
static void wacom_report_numbered_buttons(struct input_dev *input_dev,
|
||||
int button_count, int mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < button_count && i < 10; i++)
|
||||
input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
|
||||
for (i = 10; i < button_count && i < 16; i++)
|
||||
input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
|
||||
for (i = 16; i < button_count && i < 18; i++)
|
||||
input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
|
||||
}
|
||||
|
||||
int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
||||
struct wacom_wac *wacom_wac)
|
||||
{
|
||||
|
@ -47,8 +47,8 @@
|
||||
/* wacom data packet report IDs */
|
||||
#define WACOM_REPORT_PENABLED 2
|
||||
#define WACOM_REPORT_PENABLED_BT 3
|
||||
#define WACOM_REPORT_INTUOSREAD 5
|
||||
#define WACOM_REPORT_INTUOSWRITE 6
|
||||
#define WACOM_REPORT_INTUOS_ID1 5
|
||||
#define WACOM_REPORT_INTUOS_ID2 6
|
||||
#define WACOM_REPORT_INTUOSPAD 12
|
||||
#define WACOM_REPORT_INTUOS5PAD 3
|
||||
#define WACOM_REPORT_DTUSPAD 21
|
||||
@ -70,6 +70,7 @@
|
||||
#define WACOM_REPORT_DEVICE_LIST 16
|
||||
#define WACOM_REPORT_INTUOS_PEN 16
|
||||
#define WACOM_REPORT_REMOTE 17
|
||||
#define WACOM_REPORT_INTUOSHT2_ID 8
|
||||
|
||||
/* device quirks */
|
||||
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001
|
||||
|
@ -168,6 +168,8 @@ struct hid_item {
|
||||
#define HID_UP_MSVENDOR 0xff000000
|
||||
#define HID_UP_CUSTOM 0x00ff0000
|
||||
#define HID_UP_LOGIVENDOR 0xffbc0000
|
||||
#define HID_UP_LOGIVENDOR2 0xff090000
|
||||
#define HID_UP_LOGIVENDOR3 0xff430000
|
||||
#define HID_UP_LNVENDOR 0xffa00000
|
||||
#define HID_UP_SENSOR 0x00200000
|
||||
|
||||
@ -563,6 +565,9 @@ struct hid_device { /* device report descriptor */
|
||||
wait_queue_head_t debug_wait;
|
||||
};
|
||||
|
||||
#define to_hid_device(pdev) \
|
||||
container_of(pdev, struct hid_device, dev)
|
||||
|
||||
static inline void *hid_get_drvdata(struct hid_device *hdev)
|
||||
{
|
||||
return dev_get_drvdata(&hdev->dev);
|
||||
@ -712,6 +717,9 @@ struct hid_driver {
|
||||
struct device_driver driver;
|
||||
};
|
||||
|
||||
#define to_hid_driver(pdrv) \
|
||||
container_of(pdrv, struct hid_driver, driver)
|
||||
|
||||
/**
|
||||
* hid_ll_driver - low level driver callbacks
|
||||
* @start: called on probe to start the device
|
||||
|
Loading…
Reference in New Issue
Block a user