Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: - 3rd generation Wacom Intuos BT device support from Aaron Armstrong Skomra - support for NSG-MR5U and NSG-MR7U devices from Todd Kelner - multitouch Razer Blade Stealth support from Benjamin Tissoires - Elantech touchpad support from Alexandrov Stansilav - a few other scattered-around fixes and cleanups to drivers and generic code * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (31 commits) HID: google: Enable PM Full On mode when adjusting backlight HID: google: add google hammer HID driver HID: core: reset the quirks before calling probe again HID: multitouch: do not set HID_QUIRK_NO_INIT_REPORTS HID: core: remove the need for HID_QUIRK_NO_EMPTY_INPUT HID: use BIT() macro for quirks too HID: use BIT macro instead of plain integers for flags HID: multitouch: remove dead zones of Razer Blade Stealth HID: multitouch: export a quirk for the button handling of touchpads HID: usbhid: extend the polling interval configuration to keyboards HID: ntrig: document sysfs interface HID: wacom: wacom_wac_collection() is local to wacom_wac.c HID: wacom: generic: add the "Report Valid" usage HID: wacom: generic: Support multiple tools per report HID: wacom: Add support for 3rd generation Intuos BT HID: core: rewrite the hid-generic automatic unbind HID: sony: Add touchpad support for NSG-MR5U and NSG-MR7U remotes HID: hid-multitouch: Use true and false for boolean values HID: hid-ntrig: use true and false for boolean values HID: logitech-hidpp: document sysfs interface ...
This commit is contained in:
commit
e8403b493f
|
@ -0,0 +1,19 @@
|
|||
What: /sys/bus/hid/drivers/logitech-hidpp-device/<dev>/range
|
||||
Date: Jan, 2016
|
||||
KernelVersion: 4.6
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
(RW) This attribute controls the amount of 'turn' permitted in
|
||||
Logitech G920 wheel. Reading from the file shows the current
|
||||
range of the steering wheel. Writing a value within the min and
|
||||
max boundary sets the range of the wheel.
|
||||
|
||||
What: /sys/bus/hid/drivers/logitech-hidpp-device/<dev>/builtin_power_supply
|
||||
Date: Apr, 2017
|
||||
KernelVersion: 4.12
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
Presence of this file indicates that HID++ driver is capable of
|
||||
handling battery properties in the kernel. This way, upower can
|
||||
add a udev rule to decide whether or not it should use the
|
||||
internal unifying support or the generic kernel one.
|
|
@ -0,0 +1,70 @@
|
|||
What: /sys/bus/hid/drivers/ntrig/<dev>/activate_slack
|
||||
Date: May, 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
(RW) Number of contact frames ignored before acknowledging the
|
||||
start of activity (activating touch).
|
||||
|
||||
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/decativate_slack
|
||||
Date: May, 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
(RW) Number of empty (no contact) frames ignored before
|
||||
acknowledging the end of activity (deactivating touch).
|
||||
|
||||
When the last finger is removed from the device, it sends a
|
||||
number of empty frames. By holding off on deactivation for a few
|
||||
frames false erroneous disconnects can be tolerated, where the
|
||||
sensor may mistakenly not detect a finger that is still present.
|
||||
|
||||
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/activation_width
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/activation_height
|
||||
Date: May, 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
Threholds to override activation slack.
|
||||
|
||||
activation_width: (RW) Width threshold to immediately
|
||||
start processing touch events.
|
||||
|
||||
activation_height: (RW) Height threshold to immediately
|
||||
start processing touch events.
|
||||
|
||||
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/min_width
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/min_height
|
||||
Date: May, 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
Minimum size contact accepted.
|
||||
|
||||
min_width: (RW) Minimum touch contact width to decide
|
||||
activation and activity.
|
||||
|
||||
min_height: (RW) Minimum touch contact height to decide
|
||||
activation and activity.
|
||||
|
||||
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/sensor_physical_width
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/sensor_physical_height
|
||||
Date: May, 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
(RO) These are internal ranges not used for normal events but
|
||||
useful for tuning.
|
||||
|
||||
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/sensor_logical_width
|
||||
What: /sys/bus/hid/drivers/ntrig/<dev>/sensor_logical_height
|
||||
Date: May, 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
(RO) The range for positions reported during activity.
|
|
@ -4456,6 +4456,9 @@
|
|||
usbhid.jspoll=
|
||||
[USBHID] The interval which joysticks are to be polled at.
|
||||
|
||||
usbhid.kbpoll=
|
||||
[USBHID] The interval which keyboards are to be polled at.
|
||||
|
||||
usb-storage.delay_use=
|
||||
[UMS] The delay in seconds before a new device is
|
||||
scanned for Logical Units (default 1).
|
||||
|
|
|
@ -274,15 +274,23 @@ config HID_EMS_FF
|
|||
Currently the following devices are known to be supported:
|
||||
- Trio Linker Plus II
|
||||
|
||||
config HID_ELAN
|
||||
tristate "ELAN USB Touchpad Support"
|
||||
depends on LEDS_CLASS && USB_HID
|
||||
---help---
|
||||
Say Y to enable support for the USB ELAN touchpad
|
||||
Currently the following devices are known to be supported:
|
||||
- HP Pavilion X2 10-p0XX.
|
||||
|
||||
config HID_ELECOM
|
||||
tristate "ELECOM HID devices"
|
||||
depends on HID
|
||||
---help---
|
||||
Support for ELECOM devices:
|
||||
- BM084 Bluetooth Mouse
|
||||
- EX-G Trackball (Wired and wireless)
|
||||
- DEFT Trackball (Wired and wireless)
|
||||
- HUGE Trackball (Wired and wireless)
|
||||
- EX-G Trackballs (M-XT3DRBK, M-XT3URBK)
|
||||
- DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
|
||||
- HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
|
||||
|
||||
config HID_ELO
|
||||
tristate "ELO USB 4000/4500 touchscreen"
|
||||
|
@ -331,6 +339,12 @@ config HOLTEK_FF
|
|||
Say Y here if you have a Holtek On Line Grip based game controller
|
||||
and want to have force feedback support for it.
|
||||
|
||||
config HID_GOOGLE_HAMMER
|
||||
tristate "Google Hammer Keyboard"
|
||||
depends on USB_HID && LEDS_CLASS
|
||||
---help---
|
||||
Say Y here if you have a Google Hammer device.
|
||||
|
||||
config HID_GT683R
|
||||
tristate "MSI GT68xR LED support"
|
||||
depends on LEDS_CLASS && USB_HID
|
||||
|
|
|
@ -39,11 +39,13 @@ obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
|
|||
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
||||
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
|
||||
obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
|
||||
obj-$(CONFIG_HID_ELAN) += hid-elan.o
|
||||
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
|
||||
obj-$(CONFIG_HID_ELO) += hid-elo.o
|
||||
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
||||
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
|
||||
obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
|
||||
obj-$(CONFIG_HID_GOOGLE_HAMMER) += hid-google-hammer.o
|
||||
obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
|
||||
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
||||
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
|
||||
|
|
|
@ -570,7 +570,9 @@ static int asus_input_mapping(struct hid_device *hdev,
|
|||
static int asus_start_multitouch(struct hid_device *hdev)
|
||||
{
|
||||
int ret;
|
||||
const unsigned char buf[] = { FEATURE_REPORT_ID, 0x00, 0x03, 0x01, 0x00 };
|
||||
static const unsigned char buf[] = {
|
||||
FEATURE_REPORT_ID, 0x00, 0x03, 0x01, 0x00
|
||||
};
|
||||
unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
|
||||
|
||||
if (!dmabuf) {
|
||||
|
@ -644,8 +646,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
* All functionality is on a single HID interface and for
|
||||
* userspace the touchpad must be a separate input_dev.
|
||||
*/
|
||||
hdev->quirks |= HID_QUIRK_MULTI_INPUT |
|
||||
HID_QUIRK_NO_EMPTY_INPUT;
|
||||
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
|
||||
drvdata->tp = &asus_t100chi_tp;
|
||||
}
|
||||
|
||||
|
|
|
@ -1365,7 +1365,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
|
|||
* of implement() working on 8 byte chunks
|
||||
*/
|
||||
|
||||
int len = hid_report_len(report) + 7;
|
||||
u32 len = hid_report_len(report) + 7;
|
||||
|
||||
return kmalloc(len, flags);
|
||||
}
|
||||
|
@ -1430,7 +1430,7 @@ void __hid_request(struct hid_device *hid, struct hid_report *report,
|
|||
{
|
||||
char *buf;
|
||||
int ret;
|
||||
int len;
|
||||
u32 len;
|
||||
|
||||
buf = hid_alloc_report_buf(report, GFP_KERNEL);
|
||||
if (!buf)
|
||||
|
@ -1456,14 +1456,14 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__hid_request);
|
||||
|
||||
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
|
||||
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
|
||||
int interrupt)
|
||||
{
|
||||
struct hid_report_enum *report_enum = hid->report_enum + type;
|
||||
struct hid_report *report;
|
||||
struct hid_driver *hdrv;
|
||||
unsigned int a;
|
||||
int rsize, csize = size;
|
||||
u32 rsize, csize = size;
|
||||
u8 *cdata = data;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -1521,7 +1521,7 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
|
|||
*
|
||||
* This is data entry for lower layers.
|
||||
*/
|
||||
int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
|
||||
int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int interrupt)
|
||||
{
|
||||
struct hid_report_enum *report_enum;
|
||||
struct hid_driver *hdrv;
|
||||
|
@ -1966,6 +1966,8 @@ static int hid_device_probe(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
/* reset the quirks that has been previously set */
|
||||
hdev->quirks = hid_lookup_quirk(hdev);
|
||||
hdev->driver = hdrv;
|
||||
if (hdrv->probe) {
|
||||
ret = hdrv->probe(hdev, id);
|
||||
|
@ -2197,31 +2199,40 @@ void hid_destroy_device(struct hid_device *hdev)
|
|||
EXPORT_SYMBOL_GPL(hid_destroy_device);
|
||||
|
||||
|
||||
static int __bus_add_driver(struct device_driver *drv, void *data)
|
||||
static int __hid_bus_reprobe_drivers(struct device *dev, void *data)
|
||||
{
|
||||
struct hid_driver *hdrv = data;
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
|
||||
if (hdev->driver == hdrv &&
|
||||
!hdrv->match(hdev, hid_ignore_special_drivers))
|
||||
return device_reprobe(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __hid_bus_driver_added(struct device_driver *drv, void *data)
|
||||
{
|
||||
struct hid_driver *added_hdrv = data;
|
||||
struct hid_driver *hdrv = to_hid_driver(drv);
|
||||
|
||||
if (hdrv->bus_add_driver)
|
||||
hdrv->bus_add_driver(added_hdrv);
|
||||
if (hdrv->match) {
|
||||
bus_for_each_dev(&hid_bus_type, NULL, hdrv,
|
||||
__hid_bus_reprobe_drivers);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __bus_removed_driver(struct device_driver *drv, void *data)
|
||||
{
|
||||
struct hid_driver *removed_hdrv = data;
|
||||
struct hid_driver *hdrv = to_hid_driver(drv);
|
||||
|
||||
if (hdrv->bus_removed_driver)
|
||||
hdrv->bus_removed_driver(removed_hdrv);
|
||||
|
||||
return 0;
|
||||
return bus_rescan_devices(&hid_bus_type);
|
||||
}
|
||||
|
||||
int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
|
||||
const char *mod_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hdrv->driver.name = hdrv->name;
|
||||
hdrv->driver.bus = &hid_bus_type;
|
||||
hdrv->driver.owner = owner;
|
||||
|
@ -2230,9 +2241,13 @@ int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
|
|||
INIT_LIST_HEAD(&hdrv->dyn_list);
|
||||
spin_lock_init(&hdrv->dyn_lock);
|
||||
|
||||
bus_for_each_drv(&hid_bus_type, NULL, hdrv, __bus_add_driver);
|
||||
ret = driver_register(&hdrv->driver);
|
||||
|
||||
return driver_register(&hdrv->driver);
|
||||
if (ret == 0)
|
||||
bus_for_each_drv(&hid_bus_type, NULL, NULL,
|
||||
__hid_bus_driver_added);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__hid_register_driver);
|
||||
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
* HID driver for Corsair devices
|
||||
*
|
||||
* Supported devices:
|
||||
* - Vengeance K70 Keyboard
|
||||
* - K70 RAPIDFIRE Keyboard
|
||||
* - Vengeance K90 Keyboard
|
||||
* - Scimitar PRO RGB Gaming Mouse
|
||||
*
|
||||
* Copyright (c) 2015 Clement Vuchener
|
||||
* Copyright (c) 2017 Oscar Campos
|
||||
* Copyright (c) 2017 Aaron Bottegal
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -673,7 +676,7 @@ static int corsair_input_mapping(struct hid_device *dev,
|
|||
}
|
||||
|
||||
/*
|
||||
* The report descriptor of Corsair Scimitar RGB Pro gaming mouse is
|
||||
* The report descriptor of some of the Corsair gaming mice is
|
||||
* non parseable as they define two consecutive Logical Minimum for
|
||||
* the Usage Page (Consumer) in rdescs bytes 75 and 77 being 77 0x16
|
||||
* that should be obviousy 0x26 for Logical Magimum of 16 bits. This
|
||||
|
@ -681,7 +684,8 @@ static int corsair_input_mapping(struct hid_device *dev,
|
|||
* Minimum being larger than Logical Maximum.
|
||||
*
|
||||
* This driver fixes the report descriptor for:
|
||||
* - USB ID b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse
|
||||
* - USB ID 1b1c:1b34, sold as GLAIVE RGB Gaming mouse
|
||||
* - USB ID 1b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse
|
||||
*/
|
||||
|
||||
static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
|
@ -691,13 +695,14 @@ static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
|
||||
/*
|
||||
* Corsair Scimitar RGB Pro report descriptor is broken and
|
||||
* defines two different Logical Minimum for the Consumer
|
||||
* Application. The byte 77 should be a 0x26 defining a 16
|
||||
* bits integer for the Logical Maximum but it is a 0x16
|
||||
* Corsair GLAIVE RGB and Scimitar RGB Pro report descriptor is
|
||||
* broken and defines two different Logical Minimum for the
|
||||
* Consumer Application. The byte 77 should be a 0x26 defining
|
||||
* a 16 bits integer for the Logical Maximum but it is a 0x16
|
||||
* instead (Logical Minimum)
|
||||
*/
|
||||
switch (hdev->product) {
|
||||
case USB_DEVICE_ID_CORSAIR_GLAIVE_RGB:
|
||||
case USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB:
|
||||
if (*rsize >= 172 && rdesc[75] == 0x15 && rdesc[77] == 0x16
|
||||
&& rdesc[78] == 0xff && rdesc[79] == 0x0f) {
|
||||
|
@ -715,8 +720,15 @@ static const struct hid_device_id corsair_devices[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
|
||||
.driver_data = CORSAIR_USE_K90_MACRO |
|
||||
CORSAIR_USE_K90_BACKLIGHT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
|
||||
USB_DEVICE_ID_CORSAIR_GLAIVE_RGB) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
|
||||
USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
|
||||
/*
|
||||
* Vengeance K70 and K70 RAPIDFIRE share product IDs.
|
||||
*/
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
|
||||
USB_DEVICE_ID_CORSAIR_K70R) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* HID Driver for ELAN Touchpad
|
||||
*
|
||||
* Currently only supports touchpad found on HP Pavilion X2 10
|
||||
*
|
||||
* Copyright (c) 2016 Alexandrov Stanislav <neko@nya.ai>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define ELAN_SINGLE_FINGER 0x81
|
||||
#define ELAN_MT_FIRST_FINGER 0x82
|
||||
#define ELAN_MT_SECOND_FINGER 0x83
|
||||
#define ELAN_INPUT_REPORT_SIZE 8
|
||||
|
||||
#define ELAN_MUTE_LED_REPORT 0xBC
|
||||
#define ELAN_LED_REPORT_SIZE 8
|
||||
|
||||
struct elan_touchpad_settings {
|
||||
u8 max_fingers;
|
||||
u16 max_x;
|
||||
u16 max_y;
|
||||
u8 max_area_x;
|
||||
u8 max_area_y;
|
||||
u8 max_w;
|
||||
int usb_bInterfaceNumber;
|
||||
};
|
||||
|
||||
struct elan_drvdata {
|
||||
struct input_dev *input;
|
||||
u8 prev_report[ELAN_INPUT_REPORT_SIZE];
|
||||
struct led_classdev mute_led;
|
||||
u8 mute_led_state;
|
||||
struct elan_touchpad_settings *settings;
|
||||
};
|
||||
|
||||
static int is_not_elan_touchpad(struct hid_device *hdev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
|
||||
return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber);
|
||||
}
|
||||
|
||||
static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (is_not_elan_touchpad(hdev))
|
||||
return 0;
|
||||
|
||||
if (field->report->id == ELAN_SINGLE_FINGER ||
|
||||
field->report->id == ELAN_MT_FIRST_FINGER ||
|
||||
field->report->id == ELAN_MT_SECOND_FINGER)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
||||
{
|
||||
int ret;
|
||||
struct input_dev *input;
|
||||
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
|
||||
if (is_not_elan_touchpad(hdev))
|
||||
return 0;
|
||||
|
||||
input = devm_input_allocate_device(&hdev->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
input->name = "Elan Touchpad";
|
||||
input->phys = hdev->phys;
|
||||
input->uniq = hdev->uniq;
|
||||
input->id.bustype = hdev->bus;
|
||||
input->id.vendor = hdev->vendor;
|
||||
input->id.product = hdev->product;
|
||||
input->id.version = hdev->version;
|
||||
input->dev.parent = &hdev->dev;
|
||||
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0,
|
||||
drvdata->settings->max_x, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
|
||||
drvdata->settings->max_y, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
|
||||
drvdata->settings->max_fingers, 0, 0);
|
||||
input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
|
||||
drvdata->settings->max_w, 0, 0);
|
||||
|
||||
__set_bit(BTN_LEFT, input->keybit);
|
||||
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
|
||||
|
||||
ret = input_mt_init_slots(input, drvdata->settings->max_fingers,
|
||||
INPUT_MT_POINTER);
|
||||
if (ret) {
|
||||
hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = input_register_device(input);
|
||||
if (ret) {
|
||||
hid_err(hdev, "Failed to register elan input device: %d\n",
|
||||
ret);
|
||||
input_free_device(input);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drvdata->input = input;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
|
||||
unsigned int slot_num)
|
||||
{
|
||||
struct input_dev *input = drvdata->input;
|
||||
int x, y, w;
|
||||
|
||||
bool active = !!data;
|
||||
|
||||
input_mt_slot(input, slot_num);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
|
||||
if (active) {
|
||||
x = ((data[0] & 0xF0) << 4) | data[1];
|
||||
y = drvdata->settings->max_y -
|
||||
(((data[0] & 0x07) << 8) | data[2]);
|
||||
w = data[4];
|
||||
|
||||
input_report_abs(input, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(input, ABS_MT_POSITION_Y, y);
|
||||
input_report_abs(input, ABS_TOOL_WIDTH, w);
|
||||
}
|
||||
}
|
||||
|
||||
static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
|
||||
{
|
||||
int i;
|
||||
struct input_dev *input = drvdata->input;
|
||||
|
||||
/*
|
||||
* There is 3 types of reports: for single touch,
|
||||
* for multitouch - first finger and for multitouch - second finger
|
||||
*
|
||||
* packet structure for ELAN_SINGLE_FINGER and ELAN_MT_FIRST_FINGER:
|
||||
*
|
||||
* byte 1: 1 0 0 0 0 0 0 1 // 0x81 or 0x82
|
||||
* byte 2: 0 0 0 0 0 0 0 0 // looks like unused
|
||||
* byte 3: f5 f4 f3 f2 f1 0 0 L
|
||||
* byte 4: x12 x11 x10 x9 0? y11 y10 y9
|
||||
* byte 5: x8 x7 x6 x5 x4 x3 x2 x1
|
||||
* byte 6: y8 y7 y6 y5 y4 y3 y2 y1
|
||||
* byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
|
||||
* byte 8: w8 w7 w6 w5 w4 w3 w2 w1
|
||||
*
|
||||
* packet structure for ELAN_MT_SECOND_FINGER:
|
||||
*
|
||||
* byte 1: 1 0 0 0 0 0 1 1 // 0x83
|
||||
* byte 2: x12 x11 x10 x9 0 y11 y10 y9
|
||||
* byte 3: x8 x7 x6 x5 x4 x3 x2 x1
|
||||
* byte 4: y8 y7 y6 y5 y4 y3 y2 y1
|
||||
* byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
|
||||
* byte 6: w8 w7 w6 w5 w4 w3 w2 w1
|
||||
* byte 7: 0 0 0 0 0 0 0 0
|
||||
* byte 8: 0 0 0 0 0 0 0 0
|
||||
*
|
||||
* f5-f1: finger touch bits
|
||||
* L: clickpad button
|
||||
* sy / sx: not sure yet, but this looks like rectangular
|
||||
* area for finger
|
||||
* w: looks like finger width
|
||||
*/
|
||||
|
||||
if (data[0] == ELAN_SINGLE_FINGER) {
|
||||
for (i = 0; i < drvdata->settings->max_fingers; i++) {
|
||||
if (data[2] & BIT(i + 3))
|
||||
elan_report_mt_slot(drvdata, data + 3, i);
|
||||
else
|
||||
elan_report_mt_slot(drvdata, NULL, i);
|
||||
}
|
||||
input_report_key(input, BTN_LEFT, data[2] & 0x01);
|
||||
}
|
||||
/*
|
||||
* When touched with two fingers Elan touchpad will emit two HID reports
|
||||
* first is ELAN_MT_FIRST_FINGER and second is ELAN_MT_SECOND_FINGER
|
||||
* we will save ELAN_MT_FIRST_FINGER report and wait for
|
||||
* ELAN_MT_SECOND_FINGER to finish multitouch
|
||||
*/
|
||||
if (data[0] == ELAN_MT_FIRST_FINGER) {
|
||||
memcpy(drvdata->prev_report, data,
|
||||
sizeof(drvdata->prev_report));
|
||||
return;
|
||||
}
|
||||
|
||||
if (data[0] == ELAN_MT_SECOND_FINGER) {
|
||||
int first = 0;
|
||||
u8 *prev_report = drvdata->prev_report;
|
||||
|
||||
if (prev_report[0] != ELAN_MT_FIRST_FINGER)
|
||||
return;
|
||||
|
||||
for (i = 0; i < drvdata->settings->max_fingers; i++) {
|
||||
if (prev_report[2] & BIT(i + 3)) {
|
||||
if (!first) {
|
||||
first = 1;
|
||||
elan_report_mt_slot(drvdata, prev_report + 3, i);
|
||||
} else {
|
||||
elan_report_mt_slot(drvdata, data + 1, i);
|
||||
}
|
||||
} else {
|
||||
elan_report_mt_slot(drvdata, NULL, i);
|
||||
}
|
||||
}
|
||||
input_report_key(input, BTN_LEFT, prev_report[2] & 0x01);
|
||||
}
|
||||
|
||||
input_mt_sync_frame(input);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static int elan_raw_event(struct hid_device *hdev,
|
||||
struct hid_report *report, u8 *data, int size)
|
||||
{
|
||||
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
|
||||
if (is_not_elan_touchpad(hdev))
|
||||
return 0;
|
||||
|
||||
if (data[0] == ELAN_SINGLE_FINGER ||
|
||||
data[0] == ELAN_MT_FIRST_FINGER ||
|
||||
data[0] == ELAN_MT_SECOND_FINGER) {
|
||||
if (size == ELAN_INPUT_REPORT_SIZE) {
|
||||
elan_report_input(drvdata, data);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_start_multitouch(struct hid_device *hdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* This byte sequence will enable multitouch mode and disable
|
||||
* mouse emulation
|
||||
*/
|
||||
const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 };
|
||||
unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
|
||||
|
||||
if (!dmabuf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
|
||||
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||||
|
||||
kfree(dmabuf);
|
||||
|
||||
if (ret != sizeof(buf)) {
|
||||
hid_err(hdev, "Failed to start multitouch: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum led_brightness elan_mute_led_get_brigtness(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct device *dev = led_cdev->dev->parent;
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
|
||||
return drvdata->mute_led_state;
|
||||
}
|
||||
|
||||
static int elan_mute_led_set_brigtness(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
int ret;
|
||||
u8 led_state;
|
||||
struct device *dev = led_cdev->dev->parent;
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
|
||||
unsigned char *dmabuf = kzalloc(ELAN_LED_REPORT_SIZE, GFP_KERNEL);
|
||||
|
||||
if (!dmabuf)
|
||||
return -ENOMEM;
|
||||
|
||||
led_state = !!value;
|
||||
|
||||
dmabuf[0] = ELAN_MUTE_LED_REPORT;
|
||||
dmabuf[1] = 0x02;
|
||||
dmabuf[2] = led_state;
|
||||
|
||||
ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, ELAN_LED_REPORT_SIZE,
|
||||
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||||
|
||||
kfree(dmabuf);
|
||||
|
||||
if (ret != ELAN_LED_REPORT_SIZE) {
|
||||
hid_err(hdev, "Failed to set mute led brightness: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drvdata->mute_led_state = led_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_init_mute_led(struct hid_device *hdev)
|
||||
{
|
||||
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
struct led_classdev *mute_led = &drvdata->mute_led;
|
||||
|
||||
mute_led->name = "elan:red:mute";
|
||||
mute_led->brightness_get = elan_mute_led_get_brigtness;
|
||||
mute_led->brightness_set_blocking = elan_mute_led_set_brigtness;
|
||||
mute_led->max_brightness = LED_ON;
|
||||
mute_led->dev = &hdev->dev;
|
||||
|
||||
return devm_led_classdev_register(&hdev->dev, mute_led);
|
||||
}
|
||||
|
||||
static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct elan_drvdata *drvdata;
|
||||
|
||||
drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
|
||||
hid_set_drvdata(hdev, drvdata);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
hid_err(hdev, "Hid Parse failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
hid_err(hdev, "Hid hw start failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_not_elan_touchpad(hdev))
|
||||
return 0;
|
||||
|
||||
if (!drvdata->input) {
|
||||
hid_err(hdev, "Input device is not registred\n");
|
||||
ret = -ENAVAIL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = elan_start_multitouch(hdev);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = elan_init_mute_led(hdev);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
hid_hw_stop(hdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void elan_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
}
|
||||
|
||||
static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
|
||||
.max_fingers = 5,
|
||||
.max_x = 2930,
|
||||
.max_y = 1250,
|
||||
.max_area_x = 15,
|
||||
.max_area_y = 15,
|
||||
.max_w = 255,
|
||||
.usb_bInterfaceNumber = 1,
|
||||
};
|
||||
|
||||
static const struct hid_device_id elan_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
|
||||
(kernel_ulong_t)&hp_x2_10_touchpad_data},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(hid, elan_devices);
|
||||
|
||||
static struct hid_driver elan_driver = {
|
||||
.name = "elan",
|
||||
.id_table = elan_devices,
|
||||
.input_mapping = elan_input_mapping,
|
||||
.input_configured = elan_input_configured,
|
||||
.raw_event = elan_raw_event,
|
||||
.probe = elan_probe,
|
||||
.remove = elan_remove,
|
||||
};
|
||||
|
||||
module_hid_driver(elan_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Alexandrov Stanislav");
|
||||
MODULE_DESCRIPTION("Driver for HID ELAN Touchpads");
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* HID driver for ELECOM devices:
|
||||
* - BM084 Bluetooth Mouse
|
||||
* - EX-G Trackball (Wired and wireless)
|
||||
* - DEFT Trackball (Wired and wireless)
|
||||
* - HUGE Trackball (Wired and wireless)
|
||||
* - EX-G Trackballs (M-XT3DRBK, M-XT3URBK, M-XT4DRBK)
|
||||
* - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
|
||||
* - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
|
||||
*
|
||||
* Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
|
||||
* Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
|
||||
|
@ -65,14 +65,15 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
rdesc[47] = 0x00;
|
||||
}
|
||||
break;
|
||||
case USB_DEVICE_ID_ELECOM_EX_G_WIRED:
|
||||
case USB_DEVICE_ID_ELECOM_EX_G_WIRELESS:
|
||||
case USB_DEVICE_ID_ELECOM_M_XT3URBK:
|
||||
case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
|
||||
case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
|
||||
mouse_button_fixup(hdev, rdesc, *rsize, 6);
|
||||
break;
|
||||
case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
|
||||
case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
|
||||
case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
|
||||
case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
|
||||
case USB_DEVICE_ID_ELECOM_M_DT1URBK:
|
||||
case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
|
||||
case USB_DEVICE_ID_ELECOM_M_HT1URBK:
|
||||
case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
|
||||
mouse_button_fixup(hdev, rdesc, *rsize, 8);
|
||||
break;
|
||||
}
|
||||
|
@ -81,12 +82,13 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
|
||||
static const struct hid_device_id elecom_devices[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, elecom_devices);
|
||||
|
|
|
@ -26,37 +26,6 @@
|
|||
|
||||
static struct hid_driver hid_generic;
|
||||
|
||||
static int __unmap_hid_generic(struct device *dev, void *data)
|
||||
{
|
||||
struct hid_driver *hdrv = data;
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
|
||||
/* only unbind matching devices already bound to hid-generic */
|
||||
if (hdev->driver != &hid_generic ||
|
||||
hid_match_device(hdev, hdrv) == NULL)
|
||||
return 0;
|
||||
|
||||
if (dev->parent) /* Needed for USB */
|
||||
device_lock(dev->parent);
|
||||
device_release_driver(dev);
|
||||
if (dev->parent)
|
||||
device_unlock(dev->parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hid_generic_add_driver(struct hid_driver *hdrv)
|
||||
{
|
||||
bus_for_each_dev(&hid_bus_type, NULL, hdrv, __unmap_hid_generic);
|
||||
}
|
||||
|
||||
static void hid_generic_removed_driver(struct hid_driver *hdrv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = driver_attach(&hid_generic.driver);
|
||||
}
|
||||
|
||||
static int __check_hid_generic(struct device_driver *drv, void *data)
|
||||
{
|
||||
struct hid_driver *hdrv = to_hid_driver(drv);
|
||||
|
@ -97,8 +66,6 @@ static struct hid_driver hid_generic = {
|
|||
.name = "hid-generic",
|
||||
.id_table = hid_table,
|
||||
.match = hid_generic_match,
|
||||
.bus_add_driver = hid_generic_add_driver,
|
||||
.bus_removed_driver = hid_generic_removed_driver,
|
||||
};
|
||||
module_hid_driver(hid_generic);
|
||||
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* HID driver for Google Hammer device.
|
||||
*
|
||||
* Copyright (c) 2017 Google Inc.
|
||||
* Author: Wei-Ning Huang <wnhuang@google.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define MAX_BRIGHTNESS 100
|
||||
|
||||
/* HID usage for keyboard backlight (Alphanumeric display brightness) */
|
||||
#define HID_AD_BRIGHTNESS 0x00140046
|
||||
|
||||
struct hammer_kbd_leds {
|
||||
struct led_classdev cdev;
|
||||
struct hid_device *hdev;
|
||||
u8 buf[2] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
static int hammer_kbd_brightness_set_blocking(struct led_classdev *cdev,
|
||||
enum led_brightness br)
|
||||
{
|
||||
struct hammer_kbd_leds *led = container_of(cdev,
|
||||
struct hammer_kbd_leds,
|
||||
cdev);
|
||||
int ret;
|
||||
|
||||
led->buf[0] = 0;
|
||||
led->buf[1] = br;
|
||||
|
||||
/*
|
||||
* Request USB HID device to be in Full On mode, so that sending
|
||||
* hardware output report and hardware raw request won't fail.
|
||||
*/
|
||||
ret = hid_hw_power(led->hdev, PM_HINT_FULLON);
|
||||
if (ret < 0) {
|
||||
hid_err(led->hdev, "failed: device not resumed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hid_hw_output_report(led->hdev, led->buf, sizeof(led->buf));
|
||||
if (ret == -ENOSYS)
|
||||
ret = hid_hw_raw_request(led->hdev, 0, led->buf,
|
||||
sizeof(led->buf),
|
||||
HID_OUTPUT_REPORT,
|
||||
HID_REQ_SET_REPORT);
|
||||
if (ret < 0)
|
||||
hid_err(led->hdev, "failed to set keyboard backlight: %d\n",
|
||||
ret);
|
||||
|
||||
/* Request USB HID device back to Normal Mode. */
|
||||
hid_hw_power(led->hdev, PM_HINT_NORMAL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hammer_register_leds(struct hid_device *hdev)
|
||||
{
|
||||
struct hammer_kbd_leds *kbd_backlight;
|
||||
|
||||
kbd_backlight = devm_kzalloc(&hdev->dev,
|
||||
sizeof(*kbd_backlight),
|
||||
GFP_KERNEL);
|
||||
if (!kbd_backlight)
|
||||
return -ENOMEM;
|
||||
|
||||
kbd_backlight->hdev = hdev;
|
||||
kbd_backlight->cdev.name = "hammer::kbd_backlight";
|
||||
kbd_backlight->cdev.max_brightness = MAX_BRIGHTNESS;
|
||||
kbd_backlight->cdev.brightness_set_blocking =
|
||||
hammer_kbd_brightness_set_blocking;
|
||||
kbd_backlight->cdev.flags = LED_HW_PLUGGABLE;
|
||||
|
||||
/* Set backlight to 0% initially. */
|
||||
hammer_kbd_brightness_set_blocking(&kbd_backlight->cdev, 0);
|
||||
|
||||
return devm_led_classdev_register(&hdev->dev, &kbd_backlight->cdev);
|
||||
}
|
||||
|
||||
static int hammer_input_configured(struct hid_device *hdev,
|
||||
struct hid_input *hi)
|
||||
{
|
||||
struct list_head *report_list =
|
||||
&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
|
||||
struct hid_report *report;
|
||||
|
||||
if (list_empty(report_list))
|
||||
return 0;
|
||||
|
||||
report = list_first_entry(report_list, struct hid_report, list);
|
||||
|
||||
if (report->maxfield == 1 &&
|
||||
report->field[0]->application == HID_GD_KEYBOARD &&
|
||||
report->field[0]->maxusage == 1 &&
|
||||
report->field[0]->usage[0].hid == HID_AD_BRIGHTNESS) {
|
||||
int err = hammer_register_leds(hdev);
|
||||
|
||||
if (err)
|
||||
hid_warn(hdev,
|
||||
"Failed to register keyboard backlight: %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hid_device_id hammer_devices[] = {
|
||||
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
|
||||
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
|
||||
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
|
||||
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
|
||||
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
|
||||
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WAND) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, hammer_devices);
|
||||
|
||||
static struct hid_driver hammer_driver = {
|
||||
.name = "hammer",
|
||||
.id_table = hammer_devices,
|
||||
.input_configured = hammer_input_configured,
|
||||
};
|
||||
module_hid_driver(hammer_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -291,6 +291,7 @@
|
|||
#define USB_DEVICE_ID_CORSAIR_K70RGB 0x1b13
|
||||
#define USB_DEVICE_ID_CORSAIR_STRAFE 0x1b15
|
||||
#define USB_DEVICE_ID_CORSAIR_K65RGB 0x1b17
|
||||
#define USB_DEVICE_ID_CORSAIR_GLAIVE_RGB 0x1b34
|
||||
#define USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE 0x1b38
|
||||
#define USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE 0x1b39
|
||||
#define USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB 0x1b3e
|
||||
|
@ -368,15 +369,17 @@
|
|||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001
|
||||
|
||||
#define USB_VENDOR_ID_ELAN 0x04f3
|
||||
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
|
||||
|
||||
#define USB_VENDOR_ID_ELECOM 0x056e
|
||||
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
|
||||
#define USB_DEVICE_ID_ELECOM_EX_G_WIRED 0x00fb
|
||||
#define USB_DEVICE_ID_ELECOM_EX_G_WIRELESS 0x00fc
|
||||
#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe
|
||||
#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff
|
||||
#define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c
|
||||
#define USB_DEVICE_ID_ELECOM_HUGE_WIRELESS 0x010d
|
||||
#define USB_DEVICE_ID_ELECOM_M_XT3URBK 0x00fb
|
||||
#define USB_DEVICE_ID_ELECOM_M_XT3DRBK 0x00fc
|
||||
#define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd
|
||||
#define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe
|
||||
#define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff
|
||||
#define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c
|
||||
#define USB_DEVICE_ID_ELECOM_M_HT1DRBK 0x010d
|
||||
|
||||
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
|
||||
#define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004
|
||||
|
@ -445,7 +448,10 @@
|
|||
#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f
|
||||
|
||||
#define USB_VENDOR_ID_GOOGLE 0x18d1
|
||||
#define USB_DEVICE_ID_GOOGLE_HAMMER 0x5022
|
||||
#define USB_DEVICE_ID_GOOGLE_TOUCH_ROSE 0x5028
|
||||
#define USB_DEVICE_ID_GOOGLE_STAFF 0x502b
|
||||
#define USB_DEVICE_ID_GOOGLE_WAND 0x502d
|
||||
|
||||
#define USB_VENDOR_ID_GOTOP 0x08f2
|
||||
#define USB_DEVICE_ID_SUPER_Q2 0x007f
|
||||
|
@ -961,6 +967,9 @@
|
|||
|
||||
#define USB_VENDOR_ID_SMK 0x0609
|
||||
#define USB_DEVICE_ID_SMK_PS3_BDREMOTE 0x0306
|
||||
#define USB_DEVICE_ID_SMK_NSG_MR5U_REMOTE 0x0368
|
||||
#define USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE 0x0369
|
||||
|
||||
|
||||
#define USB_VENDOR_ID_SONY 0x054c
|
||||
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
|
||||
|
|
|
@ -1368,7 +1368,8 @@ static void hidinput_led_worker(struct work_struct *work)
|
|||
led_work);
|
||||
struct hid_field *field;
|
||||
struct hid_report *report;
|
||||
int len, ret;
|
||||
int ret;
|
||||
u32 len;
|
||||
__u8 *buf;
|
||||
|
||||
field = hidinput_get_led_field(hid);
|
||||
|
@ -1656,16 +1657,16 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
|||
}
|
||||
|
||||
list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
|
||||
if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
|
||||
!hidinput_has_been_populated(hidinput)) {
|
||||
if (drv->input_configured &&
|
||||
drv->input_configured(hid, hidinput))
|
||||
goto out_unwind;
|
||||
|
||||
if (!hidinput_has_been_populated(hidinput)) {
|
||||
/* no need to register an input device not populated */
|
||||
hidinput_cleanup_hidinput(hid, hidinput);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (drv->input_configured &&
|
||||
drv->input_configured(hid, hidinput))
|
||||
goto out_unwind;
|
||||
if (input_register_device(hidinput->input))
|
||||
goto out_unwind;
|
||||
hidinput->registered = true;
|
||||
|
|
|
@ -74,6 +74,7 @@ MODULE_LICENSE("GPL");
|
|||
#define MT_QUIRK_TOUCH_SIZE_SCALING BIT(15)
|
||||
#define MT_QUIRK_STICKY_FINGERS BIT(16)
|
||||
#define MT_QUIRK_ASUS_CUSTOM_UP BIT(17)
|
||||
#define MT_QUIRK_WIN8_PTP_BUTTONS BIT(18)
|
||||
|
||||
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
||||
#define MT_INPUTMODE_TOUCHPAD 0x03
|
||||
|
@ -126,7 +127,6 @@ struct mt_device {
|
|||
int left_button_state; /* left button state */
|
||||
unsigned last_slot_field; /* the last field of a slot */
|
||||
unsigned mt_report_id; /* the report ID of the multitouch device */
|
||||
unsigned long initial_quirks; /* initial quirks state */
|
||||
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
|
||||
__s16 inputmode_index; /* InputMode HID feature index in the report */
|
||||
__s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
|
||||
|
@ -183,6 +183,7 @@ static void mt_post_parse(struct mt_device *td);
|
|||
#define MT_CLS_ASUS 0x010b
|
||||
#define MT_CLS_VTL 0x0110
|
||||
#define MT_CLS_GOOGLE 0x0111
|
||||
#define MT_CLS_RAZER_BLADE_STEALTH 0x0112
|
||||
|
||||
#define MT_DEFAULT_MAXCONTACT 10
|
||||
#define MT_MAX_MAXCONTACT 250
|
||||
|
@ -241,7 +242,8 @@ static struct mt_class mt_classes[] = {
|
|||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_STICKY_FINGERS },
|
||||
MT_QUIRK_STICKY_FINGERS |
|
||||
MT_QUIRK_WIN8_PTP_BUTTONS },
|
||||
{ .name = MT_CLS_EXPORT_ALL_INPUTS,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE,
|
||||
|
@ -250,7 +252,8 @@ static struct mt_class mt_classes[] = {
|
|||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE,
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_WIN8_PTP_BUTTONS,
|
||||
.export_all_inputs = true },
|
||||
|
||||
/*
|
||||
|
@ -323,6 +326,13 @@ static struct mt_class mt_classes[] = {
|
|||
MT_QUIRK_SLOT_IS_CONTACTID |
|
||||
MT_QUIRK_HOVERING
|
||||
},
|
||||
{ .name = MT_CLS_RAZER_BLADE_STEALTH,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_WIN8_PTP_BUTTONS,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -369,15 +379,15 @@ static const struct attribute_group mt_attribute_group = {
|
|||
|
||||
static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
int ret, size = hid_report_len(report);
|
||||
int ret;
|
||||
u32 size = hid_report_len(report);
|
||||
u8 *buf;
|
||||
|
||||
/*
|
||||
* Do not fetch the feature report if the device has been explicitly
|
||||
* marked as non-capable.
|
||||
*/
|
||||
if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS)
|
||||
if (hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)
|
||||
return;
|
||||
|
||||
buf = hid_alloc_report_buf(report, GFP_KERNEL);
|
||||
|
@ -659,8 +669,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
* MS PTP spec says that external buttons left and right have
|
||||
* usages 2 and 3.
|
||||
*/
|
||||
if ((cls->name == MT_CLS_WIN_8 ||
|
||||
cls->name == MT_CLS_WIN_8_DUAL) &&
|
||||
if ((cls->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
|
||||
field->application == HID_DG_TOUCHPAD &&
|
||||
(usage->hid & HID_USAGE) > 1)
|
||||
code--;
|
||||
|
@ -722,7 +731,7 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
|||
}
|
||||
|
||||
if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
|
||||
s->confidence_state = 1;
|
||||
s->confidence_state = true;
|
||||
active = (s->touch_state || s->inrange_state) &&
|
||||
s->confidence_state;
|
||||
|
||||
|
@ -772,9 +781,7 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
|||
*/
|
||||
static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
|
||||
{
|
||||
__s32 cls = td->mtclass.name;
|
||||
|
||||
if (cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL)
|
||||
if (td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
|
||||
input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
|
||||
|
||||
input_mt_sync_frame(input);
|
||||
|
@ -826,7 +833,6 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
|||
bool first_packet)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
__s32 cls = td->mtclass.name;
|
||||
__s32 quirks = td->mtclass.quirks;
|
||||
struct input_dev *input = field->hidinput->input;
|
||||
|
||||
|
@ -904,7 +910,7 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
|||
* non finger/touch events in the first_packet of
|
||||
* a (possible) multi-packet frame.
|
||||
*/
|
||||
if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||
if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
|
||||
!first_packet)
|
||||
return;
|
||||
|
||||
|
@ -915,7 +921,7 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
|||
* BTN_LEFT if either is pressed, so we or all values
|
||||
* together and report the result in mt_sync_frame().
|
||||
*/
|
||||
if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||
if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
|
||||
usage->type == EV_KEY && usage->code == BTN_LEFT) {
|
||||
td->left_button_state |= value;
|
||||
return;
|
||||
|
@ -939,7 +945,6 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
|||
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
__s32 cls = td->mtclass.name;
|
||||
struct hid_field *field;
|
||||
bool first_packet;
|
||||
unsigned count;
|
||||
|
@ -968,7 +973,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
|||
* of a possible multi-packet frame be checking that the
|
||||
* timestamp has changed.
|
||||
*/
|
||||
if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||
if ((td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
|
||||
td->num_received == 0 && td->prev_scantime != scantime)
|
||||
td->num_expected = value;
|
||||
/* A non 0 contact count always indicates a first packet */
|
||||
|
@ -1183,7 +1188,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
|
|||
struct hid_report_enum *re;
|
||||
struct mt_class *cls = &td->mtclass;
|
||||
char *buf;
|
||||
int report_len;
|
||||
u32 report_len;
|
||||
|
||||
if (td->inputmode < 0)
|
||||
return;
|
||||
|
@ -1447,11 +1452,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
|
||||
td->serial_maybe = true;
|
||||
|
||||
/*
|
||||
* Store the initial quirk state
|
||||
*/
|
||||
td->initial_quirks = hdev->quirks;
|
||||
|
||||
/* This allows the driver to correctly support devices
|
||||
* that emit events over several HID messages.
|
||||
*/
|
||||
|
@ -1463,22 +1463,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
* device.
|
||||
*/
|
||||
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
|
||||
hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
|
||||
|
||||
/*
|
||||
* Some multitouch screens do not like to be polled for input
|
||||
* reports. Fortunately, the Win8 spec says that all touches
|
||||
* should be sent during each report, making the initialization
|
||||
* of input reports unnecessary. For Win7 devices, well, let's hope
|
||||
* they will still be happy (this is only be a problem if a touch
|
||||
* was already there while probing the device).
|
||||
*
|
||||
* In addition some touchpads do not behave well if we read
|
||||
* all feature reports from them. Instead we prevent
|
||||
* initial report fetching and then selectively fetch each
|
||||
* report we are interested in.
|
||||
*/
|
||||
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
|
||||
|
||||
timer_setup(&td->release_timer, mt_expired_timeout, 0);
|
||||
|
||||
|
@ -1537,7 +1521,6 @@ static void mt_remove(struct hid_device *hdev)
|
|||
|
||||
sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
|
||||
hid_hw_stop(hdev);
|
||||
hdev->quirks = td->initial_quirks;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1793,6 +1776,11 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
|
||||
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
|
||||
|
||||
/* Razer touchpads */
|
||||
{ .driver_data = MT_CLS_RAZER_BLADE_STEALTH,
|
||||
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
||||
USB_VENDOR_ID_SYNAPTICS, 0x8323) },
|
||||
|
||||
/* Stantum panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
|
||||
|
|
|
@ -591,8 +591,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|||
switch (usage->hid) {
|
||||
case 0xff000001:
|
||||
/* Tag indicating the start of a multitouch group */
|
||||
nd->reading_mt = 1;
|
||||
nd->first_contact_touch = 0;
|
||||
nd->reading_mt = true;
|
||||
nd->first_contact_touch = false;
|
||||
break;
|
||||
case HID_DG_TIPSWITCH:
|
||||
nd->tipswitch = value;
|
||||
|
@ -663,7 +663,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|||
* even if deactivation slack is turned off.
|
||||
*/
|
||||
nd->act_state = deactivate_slack - 1;
|
||||
nd->confidence = 0;
|
||||
nd->confidence = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -679,7 +679,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|||
*/
|
||||
if (nd->w < nd->min_width ||
|
||||
nd->h < nd->min_height)
|
||||
nd->confidence = 0;
|
||||
nd->confidence = false;
|
||||
} else
|
||||
break;
|
||||
|
||||
|
@ -758,7 +758,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
|||
if (!nd->reading_mt) /* Just to be sure */
|
||||
break;
|
||||
|
||||
nd->reading_mt = 0;
|
||||
nd->reading_mt = false;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -910,7 +910,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nd->reading_mt = 0;
|
||||
nd->reading_mt = false;
|
||||
nd->min_width = 0;
|
||||
nd->min_height = 0;
|
||||
nd->activate_slack = activate_slack;
|
||||
|
|
|
@ -62,6 +62,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_GLAIVE_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET },
|
||||
|
@ -317,6 +318,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_CORSAIR)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_GLAIVE_RGB) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_CP2112)
|
||||
|
@ -333,14 +335,18 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_ELAN)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_ELECOM)
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_ELO)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
|
||||
|
@ -608,6 +614,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
#if IS_ENABLED(CONFIG_HID_SONY)
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR5U_REMOTE) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) },
|
||||
|
|
|
@ -89,8 +89,8 @@ struct rmi_data {
|
|||
u8 *writeReport;
|
||||
u8 *readReport;
|
||||
|
||||
int input_report_size;
|
||||
int output_report_size;
|
||||
u32 input_report_size;
|
||||
u32 output_report_size;
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* Copyright (c) 2006-2013 Jiri Kosina
|
||||
* Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
|
||||
* Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>
|
||||
* Copyright (c) 2018 Todd Kelner
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -55,6 +56,8 @@
|
|||
#define NAVIGATION_CONTROLLER_BT BIT(11)
|
||||
#define SINO_LITE_CONTROLLER BIT(12)
|
||||
#define FUTUREMAX_DANCE_MAT BIT(13)
|
||||
#define NSG_MR5U_REMOTE_BT BIT(14)
|
||||
#define NSG_MR7U_REMOTE_BT BIT(15)
|
||||
|
||||
#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
|
||||
#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
|
||||
|
@ -72,8 +75,11 @@
|
|||
MOTION_CONTROLLER)
|
||||
#define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\
|
||||
MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT)
|
||||
#define NSG_MRXU_REMOTE (NSG_MR5U_REMOTE_BT | NSG_MR7U_REMOTE_BT)
|
||||
|
||||
#define MAX_LEDS 4
|
||||
#define NSG_MRXU_MAX_X 1667
|
||||
#define NSG_MRXU_MAX_Y 1868
|
||||
|
||||
|
||||
/* PS/3 Motion controller */
|
||||
|
@ -1098,6 +1104,80 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
|
|||
}
|
||||
}
|
||||
|
||||
static void nsg_mrxu_parse_report(struct sony_sc *sc, u8 *rd, int size)
|
||||
{
|
||||
int n, offset, relx, rely;
|
||||
u8 active;
|
||||
|
||||
/*
|
||||
* The NSG-MRxU multi-touch trackpad data starts at offset 1 and
|
||||
* the touch-related data starts at offset 2.
|
||||
* For the first byte, bit 0 is set when touchpad button is pressed.
|
||||
* Bit 2 is set when a touch is active and the drag (Fn) key is pressed.
|
||||
* This drag key is mapped to BTN_LEFT. It is operational only when a
|
||||
* touch point is active.
|
||||
* Bit 4 is set when only the first touch point is active.
|
||||
* Bit 6 is set when only the second touch point is active.
|
||||
* Bits 5 and 7 are set when both touch points are active.
|
||||
* The next 3 bytes are two 12 bit X/Y coordinates for the first touch.
|
||||
* The following byte, offset 5, has the touch width and length.
|
||||
* Bits 0-4=X (width), bits 5-7=Y (length).
|
||||
* A signed relative X coordinate is at offset 6.
|
||||
* The bytes at offset 7-9 are the second touch X/Y coordinates.
|
||||
* Offset 10 has the second touch width and length.
|
||||
* Offset 11 has the relative Y coordinate.
|
||||
*/
|
||||
offset = 1;
|
||||
|
||||
input_report_key(sc->touchpad, BTN_LEFT, rd[offset] & 0x0F);
|
||||
active = (rd[offset] >> 4);
|
||||
relx = (s8) rd[offset+5];
|
||||
rely = ((s8) rd[offset+10]) * -1;
|
||||
|
||||
offset++;
|
||||
|
||||
for (n = 0; n < 2; n++) {
|
||||
u16 x, y;
|
||||
u8 contactx, contacty;
|
||||
|
||||
x = rd[offset] | ((rd[offset+1] & 0x0F) << 8);
|
||||
y = ((rd[offset+1] & 0xF0) >> 4) | (rd[offset+2] << 4);
|
||||
|
||||
input_mt_slot(sc->touchpad, n);
|
||||
input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active & 0x03);
|
||||
|
||||
if (active & 0x03) {
|
||||
contactx = rd[offset+3] & 0x0F;
|
||||
contacty = rd[offset+3] >> 4;
|
||||
input_report_abs(sc->touchpad, ABS_MT_TOUCH_MAJOR,
|
||||
max(contactx, contacty));
|
||||
input_report_abs(sc->touchpad, ABS_MT_TOUCH_MINOR,
|
||||
min(contactx, contacty));
|
||||
input_report_abs(sc->touchpad, ABS_MT_ORIENTATION,
|
||||
(bool) (contactx > contacty));
|
||||
input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(sc->touchpad, ABS_MT_POSITION_Y,
|
||||
NSG_MRXU_MAX_Y - y);
|
||||
/*
|
||||
* The relative coordinates belong to the first touch
|
||||
* point, when present, or to the second touch point
|
||||
* when the first is not active.
|
||||
*/
|
||||
if ((n == 0) || ((n == 1) && (active & 0x01))) {
|
||||
input_report_rel(sc->touchpad, REL_X, relx);
|
||||
input_report_rel(sc->touchpad, REL_Y, rely);
|
||||
}
|
||||
}
|
||||
|
||||
offset += 5;
|
||||
active >>= 2;
|
||||
}
|
||||
|
||||
input_mt_sync_frame(sc->touchpad);
|
||||
|
||||
input_sync(sc->touchpad);
|
||||
}
|
||||
|
||||
static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
|
||||
u8 *rd, int size)
|
||||
{
|
||||
|
@ -1206,6 +1286,10 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
|
|||
}
|
||||
|
||||
dualshock4_parse_report(sc, rd, size);
|
||||
|
||||
} else if ((sc->quirks & NSG_MRXU_REMOTE) && rd[0] == 0x02) {
|
||||
nsg_mrxu_parse_report(sc, rd, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sc->defer_initialization) {
|
||||
|
@ -1263,7 +1347,7 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
}
|
||||
|
||||
static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
|
||||
int w, int h)
|
||||
int w, int h, int touch_major, int touch_minor, int orientation)
|
||||
{
|
||||
size_t name_sz;
|
||||
char *name;
|
||||
|
@ -1294,10 +1378,6 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
|
|||
snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name);
|
||||
sc->touchpad->name = name;
|
||||
|
||||
ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* We map the button underneath the touchpad to BTN_LEFT. */
|
||||
__set_bit(EV_KEY, sc->touchpad->evbit);
|
||||
__set_bit(BTN_LEFT, sc->touchpad->keybit);
|
||||
|
@ -1306,6 +1386,25 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
|
|||
input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0);
|
||||
input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0);
|
||||
|
||||
if (touch_major > 0) {
|
||||
input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MAJOR,
|
||||
0, touch_major, 0, 0);
|
||||
if (touch_minor > 0)
|
||||
input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MINOR,
|
||||
0, touch_minor, 0, 0);
|
||||
if (orientation > 0)
|
||||
input_set_abs_params(sc->touchpad, ABS_MT_ORIENTATION,
|
||||
0, orientation, 0, 0);
|
||||
}
|
||||
|
||||
if (sc->quirks & NSG_MRXU_REMOTE) {
|
||||
__set_bit(EV_REL, sc->touchpad->evbit);
|
||||
}
|
||||
|
||||
ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = input_register_device(sc->touchpad);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
@ -2690,7 +2789,7 @@ static int sony_input_configured(struct hid_device *hdev,
|
|||
* The Dualshock 4 touchpad supports 2 touches and has a
|
||||
* resolution of 1920x942 (44.86 dots/mm).
|
||||
*/
|
||||
ret = sony_register_touchpad(sc, 2, 1920, 942);
|
||||
ret = sony_register_touchpad(sc, 2, 1920, 942, 0, 0, 0);
|
||||
if (ret) {
|
||||
hid_err(sc->hdev,
|
||||
"Unable to initialize multi-touch slots: %d\n",
|
||||
|
@ -2721,6 +2820,20 @@ static int sony_input_configured(struct hid_device *hdev,
|
|||
}
|
||||
|
||||
sony_init_output_report(sc, dualshock4_send_output_report);
|
||||
} else if (sc->quirks & NSG_MRXU_REMOTE) {
|
||||
/*
|
||||
* The NSG-MRxU touchpad supports 2 touches and has a
|
||||
* resolution of 1667x1868
|
||||
*/
|
||||
ret = sony_register_touchpad(sc, 2,
|
||||
NSG_MRXU_MAX_X, NSG_MRXU_MAX_Y, 15, 15, 1);
|
||||
if (ret) {
|
||||
hid_err(sc->hdev,
|
||||
"Unable to initialize multi-touch slots: %d\n",
|
||||
ret);
|
||||
goto err_stop;
|
||||
}
|
||||
|
||||
} else if (sc->quirks & MOTION_CONTROLLER) {
|
||||
sony_init_output_report(sc, motion_send_output_report);
|
||||
} else {
|
||||
|
@ -2969,6 +3082,12 @@ static const struct hid_device_id sony_devices[] = {
|
|||
/* Nyko Core Controller for PS3 */
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
|
||||
.driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
|
||||
/* SMK-Link NSG-MR5U Remote Control */
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR5U_REMOTE),
|
||||
.driver_data = NSG_MR5U_REMOTE_BT },
|
||||
/* SMK-Link NSG-MR7U Remote Control */
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE),
|
||||
.driver_data = NSG_MR7U_REMOTE_BT },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, sony_devices);
|
||||
|
|
|
@ -946,7 +946,6 @@ static int uclogic_probe(struct hid_device *hdev,
|
|||
* than the pen, so use QUIRK_MULTI_INPUT for all tablets.
|
||||
*/
|
||||
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
|
||||
hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
|
||||
|
||||
/* Allocate and assign driver data */
|
||||
drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
|
|
|
@ -144,10 +144,10 @@ struct i2c_hid {
|
|||
* register of the HID
|
||||
* descriptor. */
|
||||
unsigned int bufsize; /* i2c buffer size */
|
||||
char *inbuf; /* Input buffer */
|
||||
char *rawbuf; /* Raw Input buffer */
|
||||
char *cmdbuf; /* Command buffer */
|
||||
char *argsbuf; /* Command arguments buffer */
|
||||
u8 *inbuf; /* Input buffer */
|
||||
u8 *rawbuf; /* Raw Input buffer */
|
||||
u8 *cmdbuf; /* Command buffer */
|
||||
u8 *argsbuf; /* Command arguments buffer */
|
||||
|
||||
unsigned long flags; /* device flags */
|
||||
unsigned long quirks; /* Various quirks */
|
||||
|
@ -455,7 +455,8 @@ out_unlock:
|
|||
|
||||
static void i2c_hid_get_input(struct i2c_hid *ihid)
|
||||
{
|
||||
int ret, ret_size;
|
||||
int ret;
|
||||
u32 ret_size;
|
||||
int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
|
||||
|
||||
if (size > ihid->bufsize)
|
||||
|
@ -480,7 +481,7 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ret_size > size) {
|
||||
if ((ret_size > size) || (ret_size <= 2)) {
|
||||
dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
|
||||
__func__, size, ret_size);
|
||||
return;
|
||||
|
@ -891,10 +892,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
|
|||
|
||||
static void i2c_hid_acpi_fix_up_power(struct device *dev)
|
||||
{
|
||||
acpi_handle handle = ACPI_HANDLE(dev);
|
||||
struct acpi_device *adev;
|
||||
|
||||
if (handle && acpi_bus_get_device(handle, &adev) == 0)
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (adev)
|
||||
acpi_device_fix_up_power(adev);
|
||||
}
|
||||
|
||||
|
|
|
@ -496,12 +496,12 @@ static int uhid_dev_create2(struct uhid_device *uhid,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1;
|
||||
strncpy(hid->name, ev->u.create2.name, len);
|
||||
len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1;
|
||||
strncpy(hid->phys, ev->u.create2.phys, len);
|
||||
len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1;
|
||||
strncpy(hid->uniq, ev->u.create2.uniq, len);
|
||||
len = min(sizeof(hid->name), sizeof(ev->u.create2.name));
|
||||
strlcpy(hid->name, ev->u.create2.name, len);
|
||||
len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys));
|
||||
strlcpy(hid->phys, ev->u.create2.phys, len);
|
||||
len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq));
|
||||
strlcpy(hid->uniq, ev->u.create2.uniq, len);
|
||||
|
||||
hid->ll_driver = &uhid_hid_driver;
|
||||
hid->bus = ev->u.create2.bus;
|
||||
|
|
|
@ -56,6 +56,10 @@ static unsigned int hid_jspoll_interval;
|
|||
module_param_named(jspoll, hid_jspoll_interval, uint, 0644);
|
||||
MODULE_PARM_DESC(jspoll, "Polling interval of joysticks");
|
||||
|
||||
static unsigned int hid_kbpoll_interval;
|
||||
module_param_named(kbpoll, hid_kbpoll_interval, uint, 0644);
|
||||
MODULE_PARM_DESC(kbpoll, "Polling interval of keyboards");
|
||||
|
||||
static unsigned int ignoreled;
|
||||
module_param_named(ignoreled, ignoreled, uint, 0644);
|
||||
MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds");
|
||||
|
@ -1094,7 +1098,9 @@ static int usbhid_start(struct hid_device *hid)
|
|||
hid->name, endpoint->bInterval, interval);
|
||||
}
|
||||
|
||||
/* Change the polling interval of mice and joysticks. */
|
||||
/* Change the polling interval of mice, joysticks
|
||||
* and keyboards.
|
||||
*/
|
||||
switch (hid->collection->usage) {
|
||||
case HID_GD_MOUSE:
|
||||
if (hid_mousepoll_interval > 0)
|
||||
|
@ -1104,6 +1110,10 @@ static int usbhid_start(struct hid_device *hid)
|
|||
if (hid_jspoll_interval > 0)
|
||||
interval = hid_jspoll_interval;
|
||||
break;
|
||||
case HID_GD_KEYBOARD:
|
||||
if (hid_kbpoll_interval > 0)
|
||||
interval = hid_kbpoll_interval;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
|
|
|
@ -219,7 +219,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
|
|||
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
u8 *data;
|
||||
int ret;
|
||||
int n;
|
||||
u32 n;
|
||||
|
||||
switch (equivalent_usage) {
|
||||
case HID_DG_CONTACTMAX:
|
||||
|
@ -519,7 +519,7 @@ static int wacom_set_device_mode(struct hid_device *hdev,
|
|||
u8 *rep_data;
|
||||
struct hid_report *r;
|
||||
struct hid_report_enum *re;
|
||||
int length;
|
||||
u32 length;
|
||||
int error = -ENOMEM, limit = 0;
|
||||
|
||||
if (wacom_wac->mode_report < 0)
|
||||
|
|
|
@ -1202,15 +1202,24 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom)
|
|||
|
||||
static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
|
||||
{
|
||||
const int pen_frame_len = 14;
|
||||
const int pen_frames = 7;
|
||||
int pen_frame_len, pen_frames;
|
||||
|
||||
struct input_dev *pen_input = wacom->pen_input;
|
||||
unsigned char *data = wacom->data;
|
||||
int i;
|
||||
|
||||
wacom->serial[0] = get_unaligned_le64(&data[99]);
|
||||
wacom->id[0] = get_unaligned_le16(&data[107]);
|
||||
if (wacom->features.type == INTUOSP2_BT) {
|
||||
wacom->serial[0] = get_unaligned_le64(&data[99]);
|
||||
wacom->id[0] = get_unaligned_le16(&data[107]);
|
||||
pen_frame_len = 14;
|
||||
pen_frames = 7;
|
||||
} else {
|
||||
wacom->serial[0] = get_unaligned_le64(&data[33]);
|
||||
wacom->id[0] = get_unaligned_le16(&data[41]);
|
||||
pen_frame_len = 8;
|
||||
pen_frames = 4;
|
||||
}
|
||||
|
||||
if (wacom->serial[0] >> 52 == 1) {
|
||||
/* Add back in missing bits of ID for non-USI pens */
|
||||
wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF;
|
||||
|
@ -1227,21 +1236,35 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
|
|||
continue;
|
||||
|
||||
if (range) {
|
||||
/* Fix rotation alignment: userspace expects zero at left */
|
||||
int16_t rotation = (int16_t)get_unaligned_le16(&frame[9]);
|
||||
rotation += 1800/4;
|
||||
if (rotation > 899)
|
||||
rotation -= 1800;
|
||||
|
||||
input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
|
||||
input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
|
||||
input_report_abs(pen_input, ABS_TILT_X, (char)frame[7]);
|
||||
input_report_abs(pen_input, ABS_TILT_Y, (char)frame[8]);
|
||||
input_report_abs(pen_input, ABS_Z, rotation);
|
||||
input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11]));
|
||||
|
||||
if (wacom->features.type == INTUOSP2_BT) {
|
||||
/* Fix rotation alignment: userspace expects zero at left */
|
||||
int16_t rotation =
|
||||
(int16_t)get_unaligned_le16(&frame[9]);
|
||||
rotation += 1800/4;
|
||||
|
||||
if (rotation > 899)
|
||||
rotation -= 1800;
|
||||
|
||||
input_report_abs(pen_input, ABS_TILT_X,
|
||||
(char)frame[7]);
|
||||
input_report_abs(pen_input, ABS_TILT_Y,
|
||||
(char)frame[8]);
|
||||
input_report_abs(pen_input, ABS_Z, rotation);
|
||||
input_report_abs(pen_input, ABS_WHEEL,
|
||||
get_unaligned_le16(&frame[11]));
|
||||
}
|
||||
}
|
||||
input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
|
||||
input_report_abs(pen_input, ABS_DISTANCE, range ? frame[13] : wacom->features.distance_max);
|
||||
if (wacom->features.type == INTUOSP2_BT) {
|
||||
input_report_abs(pen_input, ABS_DISTANCE,
|
||||
range ? frame[13] : wacom->features.distance_max);
|
||||
} else {
|
||||
input_report_abs(pen_input, ABS_DISTANCE,
|
||||
range ? frame[7] : wacom->features.distance_max);
|
||||
}
|
||||
|
||||
input_report_key(pen_input, BTN_TOUCH, frame[0] & 0x01);
|
||||
input_report_key(pen_input, BTN_STYLUS, frame[0] & 0x02);
|
||||
|
@ -1357,20 +1380,52 @@ static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom)
|
|||
battery_status, chg, 1, chg);
|
||||
}
|
||||
|
||||
static void wacom_intuos_gen3_bt_pad(struct wacom_wac *wacom)
|
||||
{
|
||||
struct input_dev *pad_input = wacom->pad_input;
|
||||
unsigned char *data = wacom->data;
|
||||
|
||||
int buttons = data[44];
|
||||
|
||||
wacom_report_numbered_buttons(pad_input, 4, buttons);
|
||||
|
||||
input_report_key(pad_input, wacom->tool[1], buttons ? 1 : 0);
|
||||
input_report_abs(pad_input, ABS_MISC, buttons ? PAD_DEVICE_ID : 0);
|
||||
input_event(pad_input, EV_MSC, MSC_SERIAL, 0xffffffff);
|
||||
|
||||
input_sync(pad_input);
|
||||
}
|
||||
|
||||
static void wacom_intuos_gen3_bt_battery(struct wacom_wac *wacom)
|
||||
{
|
||||
unsigned char *data = wacom->data;
|
||||
|
||||
bool chg = data[45] & 0x80;
|
||||
int battery_status = data[45] & 0x7F;
|
||||
|
||||
wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
|
||||
battery_status, chg, 1, chg);
|
||||
}
|
||||
|
||||
static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len)
|
||||
{
|
||||
unsigned char *data = wacom->data;
|
||||
|
||||
if (data[0] != 0x80) {
|
||||
if (data[0] != 0x80 && data[0] != 0x81) {
|
||||
dev_dbg(wacom->pen_input->dev.parent,
|
||||
"%s: received unknown report #%d\n", __func__, data[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wacom_intuos_pro2_bt_pen(wacom);
|
||||
wacom_intuos_pro2_bt_touch(wacom);
|
||||
wacom_intuos_pro2_bt_pad(wacom);
|
||||
wacom_intuos_pro2_bt_battery(wacom);
|
||||
if (wacom->features.type == INTUOSP2_BT) {
|
||||
wacom_intuos_pro2_bt_touch(wacom);
|
||||
wacom_intuos_pro2_bt_pad(wacom);
|
||||
wacom_intuos_pro2_bt_battery(wacom);
|
||||
} else {
|
||||
wacom_intuos_gen3_bt_pad(wacom);
|
||||
wacom_intuos_gen3_bt_battery(wacom);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1660,7 +1715,8 @@ int wacom_equivalent_usage(int usage)
|
|||
usage == WACOM_HID_WD_TOUCHSTRIP ||
|
||||
usage == WACOM_HID_WD_TOUCHSTRIP2 ||
|
||||
usage == WACOM_HID_WD_TOUCHRING ||
|
||||
usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
|
||||
usage == WACOM_HID_WD_TOUCHRINGSTATUS ||
|
||||
usage == WACOM_HID_WD_REPORT_VALID) {
|
||||
return usage;
|
||||
}
|
||||
|
||||
|
@ -2017,7 +2073,7 @@ static void wacom_wac_pad_pre_report(struct hid_device *hdev,
|
|||
}
|
||||
|
||||
static void wacom_wac_pad_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
struct hid_report *report, struct hid_field *field)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
|
@ -2025,7 +2081,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
|
|||
bool active = wacom_wac->hid_data.inrange_state != 0;
|
||||
|
||||
/* report prox for expresskey events */
|
||||
if ((wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) &&
|
||||
if ((wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) &&
|
||||
wacom_wac->hid_data.pad_input_event_flag) {
|
||||
input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
|
||||
input_sync(input);
|
||||
|
@ -2144,6 +2200,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
|
|||
struct input_dev *input = wacom_wac->pen_input;
|
||||
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
|
||||
if (wacom_wac->is_invalid_bt_frame)
|
||||
return;
|
||||
|
||||
switch (equivalent_usage) {
|
||||
case HID_GD_Z:
|
||||
/*
|
||||
|
@ -2240,6 +2299,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
|
|||
features->offset_bottom);
|
||||
features->offset_bottom = value;
|
||||
return;
|
||||
case WACOM_HID_WD_REPORT_VALID:
|
||||
wacom_wac->is_invalid_bt_frame = !value;
|
||||
return;
|
||||
}
|
||||
|
||||
/* send pen events only when touch is up or forced out
|
||||
|
@ -2258,6 +2320,10 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
|
|||
static void wacom_wac_pen_pre_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
|
||||
wacom_wac->is_invalid_bt_frame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2270,6 +2336,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
|
|||
bool range = wacom_wac->hid_data.inrange_state;
|
||||
bool sense = wacom_wac->hid_data.sense_state;
|
||||
|
||||
if (wacom_wac->is_invalid_bt_frame)
|
||||
return;
|
||||
|
||||
if (!wacom_wac->tool[0] && range) { /* first in range */
|
||||
/* Going into range select tool */
|
||||
if (wacom_wac->hid_data.invert_state)
|
||||
|
@ -2572,11 +2641,13 @@ void wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
|
|||
wacom_wac_finger_event(hdev, field, usage, value);
|
||||
}
|
||||
|
||||
static void wacom_report_events(struct hid_device *hdev, struct hid_report *report)
|
||||
static void wacom_report_events(struct hid_device *hdev,
|
||||
struct hid_report *report, int collection_index,
|
||||
int field_index)
|
||||
{
|
||||
int r;
|
||||
|
||||
for (r = 0; r < report->maxfield; r++) {
|
||||
for (r = field_index; r < report->maxfield; r++) {
|
||||
struct hid_field *field;
|
||||
unsigned count, n;
|
||||
|
||||
|
@ -2586,30 +2657,23 @@ static void wacom_report_events(struct hid_device *hdev, struct hid_report *repo
|
|||
if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
|
||||
continue;
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
wacom_wac_event(hdev, field, &field->usage[n], field->value[n]);
|
||||
for (n = 0 ; n < count; n++) {
|
||||
if (field->usage[n].collection_index == collection_index)
|
||||
wacom_wac_event(hdev, field, &field->usage[n],
|
||||
field->value[n]);
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
||||
static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
|
||||
int collection_index, struct hid_field *field,
|
||||
int field_index)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct hid_field *field = report->field[0];
|
||||
|
||||
if (wacom_wac->features.type != HID_GENERIC)
|
||||
return;
|
||||
|
||||
wacom_wac_battery_pre_report(hdev, report);
|
||||
|
||||
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_pre_report(hdev, report);
|
||||
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
wacom_wac_pen_pre_report(hdev, report);
|
||||
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
|
||||
wacom_wac_finger_pre_report(hdev, report);
|
||||
|
||||
wacom_report_events(hdev, report);
|
||||
wacom_report_events(hdev, report, collection_index, field_index);
|
||||
|
||||
/*
|
||||
* Non-input reports may be sent prior to the device being
|
||||
|
@ -2619,16 +2683,63 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
|||
* processing functions.
|
||||
*/
|
||||
if (report->type != HID_INPUT_REPORT)
|
||||
return;
|
||||
|
||||
wacom_wac_battery_report(hdev, report);
|
||||
return -1;
|
||||
|
||||
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_report(hdev, report);
|
||||
wacom_wac_pad_report(hdev, report, field);
|
||||
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
wacom_wac_pen_report(hdev, report);
|
||||
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
|
||||
wacom_wac_finger_report(hdev, report);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct hid_field *field;
|
||||
bool pad_in_hid_field = false, pen_in_hid_field = false,
|
||||
finger_in_hid_field = false;
|
||||
int r;
|
||||
int prev_collection = -1;
|
||||
|
||||
if (wacom_wac->features.type != HID_GENERIC)
|
||||
return;
|
||||
|
||||
for (r = 0; r < report->maxfield; r++) {
|
||||
field = report->field[r];
|
||||
|
||||
if (WACOM_PAD_FIELD(field))
|
||||
pad_in_hid_field = true;
|
||||
if (WACOM_PEN_FIELD(field))
|
||||
pen_in_hid_field = true;
|
||||
if (WACOM_FINGER_FIELD(field))
|
||||
finger_in_hid_field = true;
|
||||
}
|
||||
|
||||
wacom_wac_battery_pre_report(hdev, report);
|
||||
|
||||
if (pad_in_hid_field && wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_pre_report(hdev, report);
|
||||
if (pen_in_hid_field && wacom->wacom_wac.pen_input)
|
||||
wacom_wac_pen_pre_report(hdev, report);
|
||||
if (finger_in_hid_field && wacom->wacom_wac.touch_input)
|
||||
wacom_wac_finger_pre_report(hdev, report);
|
||||
|
||||
for (r = 0; r < report->maxfield; r++) {
|
||||
field = report->field[r];
|
||||
|
||||
if (field->usage[0].collection_index != prev_collection) {
|
||||
if (wacom_wac_collection(hdev, report,
|
||||
field->usage[0].collection_index, field, r) < 0)
|
||||
return;
|
||||
prev_collection = field->usage[0].collection_index;
|
||||
}
|
||||
}
|
||||
|
||||
wacom_wac_battery_report(hdev, report);
|
||||
}
|
||||
|
||||
static int wacom_bpt_touch(struct wacom_wac *wacom)
|
||||
|
@ -3093,6 +3204,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
|||
break;
|
||||
|
||||
case INTUOSP2_BT:
|
||||
case INTUOSHT3_BT:
|
||||
sync = wacom_intuos_pro2_bt_irq(wacom_wac, len);
|
||||
break;
|
||||
|
||||
|
@ -3272,6 +3384,12 @@ void wacom_setup_device_quirks(struct wacom *wacom)
|
|||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
}
|
||||
|
||||
if (features->type == INTUOSHT3_BT) {
|
||||
features->device_type |= WACOM_DEVICETYPE_PEN |
|
||||
WACOM_DEVICETYPE_PAD;
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
}
|
||||
|
||||
switch (features->type) {
|
||||
case PL:
|
||||
case DTU:
|
||||
|
@ -3466,7 +3584,9 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
|
|||
case BAMBOO_PT:
|
||||
case BAMBOO_PEN:
|
||||
case INTUOSHT2:
|
||||
if (features->type == INTUOSHT2) {
|
||||
case INTUOSHT3_BT:
|
||||
if (features->type == INTUOSHT2 ||
|
||||
features->type == INTUOSHT3_BT) {
|
||||
wacom_setup_basic_pro_pen(wacom_wac);
|
||||
} else {
|
||||
__clear_bit(ABS_MISC, input_dev->absbit);
|
||||
|
@ -3887,6 +4007,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
|
||||
break;
|
||||
|
||||
case INTUOSHT3_BT:
|
||||
case HID_GENERIC:
|
||||
break;
|
||||
|
||||
|
@ -4415,6 +4536,12 @@ static const struct wacom_features wacom_features_0x360 =
|
|||
static const struct wacom_features wacom_features_0x361 =
|
||||
{ "Wacom Intuos Pro L", 62200, 43200, 8191, 63,
|
||||
INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
|
||||
static const struct wacom_features wacom_features_0x377 =
|
||||
{ "Wacom Intuos BT S", 15200, 9500, 4095, 63,
|
||||
INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
|
||||
static const struct wacom_features wacom_features_0x379 =
|
||||
{ "Wacom Intuos BT M", 21600, 13500, 4095, 63,
|
||||
INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
|
||||
static const struct wacom_features wacom_features_0x37A =
|
||||
{ "Wacom One by Wacom S", 15200, 9500, 2047, 63,
|
||||
BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
|
@ -4589,6 +4716,8 @@ const struct hid_device_id wacom_ids[] = {
|
|||
{ USB_DEVICE_WACOM(0x343) },
|
||||
{ BT_DEVICE_WACOM(0x360) },
|
||||
{ BT_DEVICE_WACOM(0x361) },
|
||||
{ BT_DEVICE_WACOM(0x377) },
|
||||
{ BT_DEVICE_WACOM(0x379) },
|
||||
{ USB_DEVICE_WACOM(0x37A) },
|
||||
{ USB_DEVICE_WACOM(0x37B) },
|
||||
{ USB_DEVICE_WACOM(0x4001) },
|
||||
|
|
|
@ -118,6 +118,7 @@
|
|||
#define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)
|
||||
#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
|
||||
#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
|
||||
#define WACOM_HID_WD_REPORT_VALID (WACOM_HID_UP_WACOMDIGITIZER | 0x01d0)
|
||||
#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
|
||||
#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
|
||||
#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
|
||||
|
@ -213,6 +214,7 @@ enum {
|
|||
INTUOSPM,
|
||||
INTUOSPL,
|
||||
INTUOSP2_BT,
|
||||
INTUOSHT3_BT,
|
||||
WACOM_21UX2,
|
||||
WACOM_22HD,
|
||||
DTK,
|
||||
|
@ -352,7 +354,7 @@ struct wacom_wac {
|
|||
bool has_mute_touch_switch;
|
||||
bool has_mode_change;
|
||||
bool is_direct_mode;
|
||||
|
||||
bool is_invalid_bt_frame;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define __HID_H
|
||||
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
|
@ -310,13 +311,13 @@ struct hid_item {
|
|||
* HID connect requests
|
||||
*/
|
||||
|
||||
#define HID_CONNECT_HIDINPUT 0x01
|
||||
#define HID_CONNECT_HIDINPUT_FORCE 0x02
|
||||
#define HID_CONNECT_HIDRAW 0x04
|
||||
#define HID_CONNECT_HIDDEV 0x08
|
||||
#define HID_CONNECT_HIDDEV_FORCE 0x10
|
||||
#define HID_CONNECT_FF 0x20
|
||||
#define HID_CONNECT_DRIVER 0x40
|
||||
#define HID_CONNECT_HIDINPUT BIT(0)
|
||||
#define HID_CONNECT_HIDINPUT_FORCE BIT(1)
|
||||
#define HID_CONNECT_HIDRAW BIT(2)
|
||||
#define HID_CONNECT_HIDDEV BIT(3)
|
||||
#define HID_CONNECT_HIDDEV_FORCE BIT(4)
|
||||
#define HID_CONNECT_FF BIT(5)
|
||||
#define HID_CONNECT_DRIVER BIT(6)
|
||||
#define HID_CONNECT_DEFAULT (HID_CONNECT_HIDINPUT|HID_CONNECT_HIDRAW| \
|
||||
HID_CONNECT_HIDDEV|HID_CONNECT_FF)
|
||||
|
||||
|
@ -329,25 +330,25 @@ struct hid_item {
|
|||
*/
|
||||
#define MAX_USBHID_BOOT_QUIRKS 4
|
||||
|
||||
#define HID_QUIRK_INVERT 0x00000001
|
||||
#define HID_QUIRK_NOTOUCH 0x00000002
|
||||
#define HID_QUIRK_IGNORE 0x00000004
|
||||
#define HID_QUIRK_NOGET 0x00000008
|
||||
#define HID_QUIRK_HIDDEV_FORCE 0x00000010
|
||||
#define HID_QUIRK_BADPAD 0x00000020
|
||||
#define HID_QUIRK_MULTI_INPUT 0x00000040
|
||||
#define HID_QUIRK_HIDINPUT_FORCE 0x00000080
|
||||
#define HID_QUIRK_NO_EMPTY_INPUT 0x00000100
|
||||
/* 0x00000200 reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */
|
||||
#define HID_QUIRK_ALWAYS_POLL 0x00000400
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000
|
||||
#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP 0x00040000
|
||||
#define HID_QUIRK_HAVE_SPECIAL_DRIVER 0x00080000
|
||||
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
|
||||
#define HID_QUIRK_NO_INIT_REPORTS 0x20000000
|
||||
#define HID_QUIRK_NO_IGNORE 0x40000000
|
||||
#define HID_QUIRK_NO_INPUT_SYNC 0x80000000
|
||||
#define HID_QUIRK_INVERT BIT(0)
|
||||
#define HID_QUIRK_NOTOUCH BIT(1)
|
||||
#define HID_QUIRK_IGNORE BIT(2)
|
||||
#define HID_QUIRK_NOGET BIT(3)
|
||||
#define HID_QUIRK_HIDDEV_FORCE BIT(4)
|
||||
#define HID_QUIRK_BADPAD BIT(5)
|
||||
#define HID_QUIRK_MULTI_INPUT BIT(6)
|
||||
#define HID_QUIRK_HIDINPUT_FORCE BIT(7)
|
||||
/* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT */
|
||||
/* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */
|
||||
#define HID_QUIRK_ALWAYS_POLL BIT(10)
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16)
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17)
|
||||
#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18)
|
||||
#define HID_QUIRK_HAVE_SPECIAL_DRIVER BIT(19)
|
||||
#define HID_QUIRK_FULLSPEED_INTERVAL BIT(28)
|
||||
#define HID_QUIRK_NO_INIT_REPORTS BIT(29)
|
||||
#define HID_QUIRK_NO_IGNORE BIT(30)
|
||||
#define HID_QUIRK_NO_INPUT_SYNC BIT(31)
|
||||
|
||||
/*
|
||||
* HID device groups
|
||||
|
@ -494,13 +495,13 @@ struct hid_output_fifo {
|
|||
char *raw_report;
|
||||
};
|
||||
|
||||
#define HID_CLAIMED_INPUT 1
|
||||
#define HID_CLAIMED_HIDDEV 2
|
||||
#define HID_CLAIMED_HIDRAW 4
|
||||
#define HID_CLAIMED_DRIVER 8
|
||||
#define HID_CLAIMED_INPUT BIT(0)
|
||||
#define HID_CLAIMED_HIDDEV BIT(1)
|
||||
#define HID_CLAIMED_HIDRAW BIT(2)
|
||||
#define HID_CLAIMED_DRIVER BIT(3)
|
||||
|
||||
#define HID_STAT_ADDED 1
|
||||
#define HID_STAT_PARSED 2
|
||||
#define HID_STAT_ADDED BIT(0)
|
||||
#define HID_STAT_PARSED BIT(1)
|
||||
|
||||
struct hid_input {
|
||||
struct list_head list;
|
||||
|
@ -686,8 +687,6 @@ struct hid_usage_id {
|
|||
* @input_mapped: invoked on input registering after mapping an usage
|
||||
* @input_configured: invoked just before the device is registered
|
||||
* @feature_mapping: invoked on feature registering
|
||||
* @bus_add_driver: invoked when a HID driver is about to be added
|
||||
* @bus_removed_driver: invoked when a HID driver has been removed
|
||||
* @suspend: invoked on suspend (NULL means nop)
|
||||
* @resume: invoked on resume if device was not reset (NULL means nop)
|
||||
* @reset_resume: invoked on resume if device was reset (NULL means nop)
|
||||
|
@ -742,8 +741,6 @@ struct hid_driver {
|
|||
void (*feature_mapping)(struct hid_device *hdev,
|
||||
struct hid_field *field,
|
||||
struct hid_usage *usage);
|
||||
void (*bus_add_driver)(struct hid_driver *driver);
|
||||
void (*bus_removed_driver)(struct hid_driver *driver);
|
||||
#ifdef CONFIG_PM
|
||||
int (*suspend)(struct hid_device *hdev, pm_message_t message);
|
||||
int (*resume)(struct hid_device *hdev);
|
||||
|
@ -851,7 +848,7 @@ extern int hidinput_connect(struct hid_device *hid, unsigned int force);
|
|||
extern void hidinput_disconnect(struct hid_device *);
|
||||
|
||||
int hid_set_field(struct hid_field *, unsigned, __s32);
|
||||
int hid_input_report(struct hid_device *, int type, u8 *, int, int);
|
||||
int hid_input_report(struct hid_device *, int type, u8 *, u32, int);
|
||||
int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
|
||||
struct hid_field *hidinput_get_led_field(struct hid_device *hid);
|
||||
unsigned int hidinput_count_leds(struct hid_device *hid);
|
||||
|
@ -1102,13 +1099,13 @@ static inline void hid_hw_wait(struct hid_device *hdev)
|
|||
*
|
||||
* @report: the report we want to know the length
|
||||
*/
|
||||
static inline int hid_report_len(struct hid_report *report)
|
||||
static inline u32 hid_report_len(struct hid_report *report)
|
||||
{
|
||||
/* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
|
||||
return ((report->size - 1) >> 3) + 1 + (report->id > 0);
|
||||
}
|
||||
|
||||
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
|
||||
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
|
||||
int interrupt);
|
||||
|
||||
/* HID quirks API */
|
||||
|
|
Loading…
Reference in New Issue