Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - revert of the high-resolution scrolling feature, as it breaks certain hardware due to incompatibilities between Logitech and Microsoft worlds. Peter Hutterer is working on a fixed implementation. Until that is finished, revert by Benjamin Tissoires. - revert of incorrect strncpy->strlcpy conversion in uhid, from David Herrmann - fix for buggy sendfile() implementation on uhid device node, from Eric Biggers - a few assorted device-ID specific quirks * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: Revert "Input: Add the `REL_WHEEL_HI_RES` event code" Revert "HID: input: Create a utility class for counting scroll events" Revert "HID: logitech: Add function to enable HID++ 1.0 "scrolling acceleration"" Revert "HID: logitech: Enable high-resolution scrolling on Logitech mice" Revert "HID: logitech: Use LDJ_DEVICE macro for existing Logitech mice" Revert "HID: logitech: fix a used uninitialized GCC warning" Revert "HID: input: simplify/fix high-res scroll event handling" HID: Add quirk for Primax PIXART OEM mice HID: i2c-hid: Disable runtime PM for LG touchscreen HID: multitouch: Add pointstick support for Cirque Touchpad HID: steam: remove input device when a hid client is running. Revert "HID: uhid: use strlcpy() instead of strncpy()" HID: uhid: forbid UHID_CREATE under KERNEL_DS or elevated privileges HID: input: Ignore battery reported by Symbol DS4308 HID: Add quirk for Microsoft PIXART OEM mouse
This commit is contained in:
Коммит
e195ca6cb6
|
@ -190,16 +190,7 @@ A few EV_REL codes have special meanings:
|
|||
* REL_WHEEL, REL_HWHEEL:
|
||||
|
||||
- These codes are used for vertical and horizontal scroll wheels,
|
||||
respectively. The value is the number of "notches" moved on the wheel, the
|
||||
physical size of which varies by device. For high-resolution wheels (which
|
||||
report multiple events for each notch of movement, or do not have notches)
|
||||
this may be an approximation based on the high-resolution scroll events.
|
||||
|
||||
* REL_WHEEL_HI_RES:
|
||||
|
||||
- If a vertical scroll wheel supports high-resolution scrolling, this code
|
||||
will be emitted in addition to REL_WHEEL. The value is the (approximate)
|
||||
distance travelled by the user's finger, in microns.
|
||||
respectively.
|
||||
|
||||
EV_ABS
|
||||
------
|
||||
|
|
|
@ -275,6 +275,9 @@
|
|||
|
||||
#define USB_VENDOR_ID_CIDC 0x1677
|
||||
|
||||
#define I2C_VENDOR_ID_CIRQUE 0x0488
|
||||
#define I2C_PRODUCT_ID_CIRQUE_121F 0x121F
|
||||
|
||||
#define USB_VENDOR_ID_CJTOUCH 0x24b8
|
||||
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020
|
||||
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040 0x0040
|
||||
|
@ -707,6 +710,7 @@
|
|||
#define USB_VENDOR_ID_LG 0x1fd2
|
||||
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
||||
#define USB_DEVICE_ID_LG_MELFAS_MT 0x6007
|
||||
#define I2C_DEVICE_ID_LG_8001 0x8001
|
||||
|
||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
|
||||
|
@ -805,6 +809,7 @@
|
|||
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
|
||||
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
|
||||
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
|
||||
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
|
||||
|
||||
#define USB_VENDOR_ID_MOJO 0x8282
|
||||
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
|
||||
|
@ -1043,6 +1048,7 @@
|
|||
#define USB_VENDOR_ID_SYMBOL 0x05e0
|
||||
#define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800
|
||||
#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
|
||||
#define USB_DEVICE_ID_SYMBOL_SCANNER_3 0x1200
|
||||
|
||||
#define USB_VENDOR_ID_SYNAPTICS 0x06cb
|
||||
#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001
|
||||
|
@ -1204,6 +1210,8 @@
|
|||
#define USB_DEVICE_ID_PRIMAX_MOUSE_4D22 0x4d22
|
||||
#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
|
||||
#define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72
|
||||
#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F 0x4d0f
|
||||
#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22 0x4e22
|
||||
|
||||
|
||||
#define USB_VENDOR_ID_RISO_KAGAKU 0x1294 /* Riso Kagaku Corp. */
|
||||
|
|
|
@ -325,6 +325,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
|
|||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,
|
||||
USB_DEVICE_ID_ELECOM_BM084),
|
||||
HID_BATTERY_QUIRK_IGNORE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL,
|
||||
USB_DEVICE_ID_SYMBOL_SCANNER_3),
|
||||
HID_BATTERY_QUIRK_IGNORE },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -1838,47 +1841,3 @@ void hidinput_disconnect(struct hid_device *hid)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(hidinput_disconnect);
|
||||
|
||||
/**
|
||||
* hid_scroll_counter_handle_scroll() - Send high- and low-resolution scroll
|
||||
* events given a high-resolution wheel
|
||||
* movement.
|
||||
* @counter: a hid_scroll_counter struct describing the wheel.
|
||||
* @hi_res_value: the movement of the wheel, in the mouse's high-resolution
|
||||
* units.
|
||||
*
|
||||
* Given a high-resolution movement, this function converts the movement into
|
||||
* microns and emits high-resolution scroll events for the input device. It also
|
||||
* uses the multiplier from &struct hid_scroll_counter to emit low-resolution
|
||||
* scroll events when appropriate for backwards-compatibility with userspace
|
||||
* input libraries.
|
||||
*/
|
||||
void hid_scroll_counter_handle_scroll(struct hid_scroll_counter *counter,
|
||||
int hi_res_value)
|
||||
{
|
||||
int low_res_value, remainder, multiplier;
|
||||
|
||||
input_report_rel(counter->dev, REL_WHEEL_HI_RES,
|
||||
hi_res_value * counter->microns_per_hi_res_unit);
|
||||
|
||||
/*
|
||||
* Update the low-res remainder with the high-res value,
|
||||
* but reset if the direction has changed.
|
||||
*/
|
||||
remainder = counter->remainder;
|
||||
if ((remainder ^ hi_res_value) < 0)
|
||||
remainder = 0;
|
||||
remainder += hi_res_value;
|
||||
|
||||
/*
|
||||
* Then just use the resolution multiplier to see if
|
||||
* we should send a low-res (aka regular wheel) event.
|
||||
*/
|
||||
multiplier = counter->resolution_multiplier;
|
||||
low_res_value = remainder / multiplier;
|
||||
remainder -= low_res_value * multiplier;
|
||||
counter->remainder = remainder;
|
||||
|
||||
if (low_res_value)
|
||||
input_report_rel(counter->dev, REL_WHEEL, low_res_value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_scroll_counter_handle_scroll);
|
||||
|
|
|
@ -64,14 +64,6 @@ MODULE_PARM_DESC(disable_tap_to_click,
|
|||
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
|
||||
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
|
||||
#define HIDPP_QUIRK_UNIFYING BIT(25)
|
||||
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26)
|
||||
#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27)
|
||||
#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28)
|
||||
|
||||
/* Convenience constant to check for any high-res support. */
|
||||
#define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \
|
||||
HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \
|
||||
HIDPP_QUIRK_HI_RES_SCROLL_X2121)
|
||||
|
||||
#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
|
||||
|
||||
|
@ -157,7 +149,6 @@ struct hidpp_device {
|
|||
unsigned long capabilities;
|
||||
|
||||
struct hidpp_battery battery;
|
||||
struct hid_scroll_counter vertical_wheel_counter;
|
||||
};
|
||||
|
||||
/* HID++ 1.0 error codes */
|
||||
|
@ -409,15 +400,9 @@ static void hidpp_prefix_name(char **name, int name_length)
|
|||
#define HIDPP_SET_LONG_REGISTER 0x82
|
||||
#define HIDPP_GET_LONG_REGISTER 0x83
|
||||
|
||||
/**
|
||||
* hidpp10_set_register_bit() - Sets a single bit in a HID++ 1.0 register.
|
||||
* @hidpp_dev: the device to set the register on.
|
||||
* @register_address: the address of the register to modify.
|
||||
* @byte: the byte of the register to modify. Should be less than 3.
|
||||
* Return: 0 if successful, otherwise a negative error code.
|
||||
*/
|
||||
static int hidpp10_set_register_bit(struct hidpp_device *hidpp_dev,
|
||||
u8 register_address, u8 byte, u8 bit)
|
||||
#define HIDPP_REG_GENERAL 0x00
|
||||
|
||||
static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)
|
||||
{
|
||||
struct hidpp_report response;
|
||||
int ret;
|
||||
|
@ -426,38 +411,23 @@ static int hidpp10_set_register_bit(struct hidpp_device *hidpp_dev,
|
|||
ret = hidpp_send_rap_command_sync(hidpp_dev,
|
||||
REPORT_ID_HIDPP_SHORT,
|
||||
HIDPP_GET_REGISTER,
|
||||
register_address,
|
||||
HIDPP_REG_GENERAL,
|
||||
NULL, 0, &response);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(params, response.rap.params, 3);
|
||||
|
||||
params[byte] |= BIT(bit);
|
||||
/* Set the battery bit */
|
||||
params[0] |= BIT(4);
|
||||
|
||||
return hidpp_send_rap_command_sync(hidpp_dev,
|
||||
REPORT_ID_HIDPP_SHORT,
|
||||
HIDPP_SET_REGISTER,
|
||||
register_address,
|
||||
HIDPP_REG_GENERAL,
|
||||
params, 3, &response);
|
||||
}
|
||||
|
||||
|
||||
#define HIDPP_REG_GENERAL 0x00
|
||||
|
||||
static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)
|
||||
{
|
||||
return hidpp10_set_register_bit(hidpp_dev, HIDPP_REG_GENERAL, 0, 4);
|
||||
}
|
||||
|
||||
#define HIDPP_REG_FEATURES 0x01
|
||||
|
||||
/* On HID++ 1.0 devices, high-res scroll was called "scrolling acceleration". */
|
||||
static int hidpp10_enable_scrolling_acceleration(struct hidpp_device *hidpp_dev)
|
||||
{
|
||||
return hidpp10_set_register_bit(hidpp_dev, HIDPP_REG_FEATURES, 0, 6);
|
||||
}
|
||||
|
||||
#define HIDPP_REG_BATTERY_STATUS 0x07
|
||||
|
||||
static int hidpp10_battery_status_map_level(u8 param)
|
||||
|
@ -1166,100 +1136,6 @@ static int hidpp_battery_get_property(struct power_supply *psy,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x2120: Hi-resolution scrolling */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define HIDPP_PAGE_HI_RESOLUTION_SCROLLING 0x2120
|
||||
|
||||
#define CMD_HI_RESOLUTION_SCROLLING_SET_HIGHRES_SCROLLING_MODE 0x10
|
||||
|
||||
static int hidpp_hrs_set_highres_scrolling_mode(struct hidpp_device *hidpp,
|
||||
bool enabled, u8 *multiplier)
|
||||
{
|
||||
u8 feature_index;
|
||||
u8 feature_type;
|
||||
int ret;
|
||||
u8 params[1];
|
||||
struct hidpp_report response;
|
||||
|
||||
ret = hidpp_root_get_feature(hidpp,
|
||||
HIDPP_PAGE_HI_RESOLUTION_SCROLLING,
|
||||
&feature_index,
|
||||
&feature_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
params[0] = enabled ? BIT(0) : 0;
|
||||
ret = hidpp_send_fap_command_sync(hidpp, feature_index,
|
||||
CMD_HI_RESOLUTION_SCROLLING_SET_HIGHRES_SCROLLING_MODE,
|
||||
params, sizeof(params), &response);
|
||||
if (ret)
|
||||
return ret;
|
||||
*multiplier = response.fap.params[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x2121: HiRes Wheel */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define HIDPP_PAGE_HIRES_WHEEL 0x2121
|
||||
|
||||
#define CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY 0x00
|
||||
#define CMD_HIRES_WHEEL_SET_WHEEL_MODE 0x20
|
||||
|
||||
static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
|
||||
u8 *multiplier)
|
||||
{
|
||||
u8 feature_index;
|
||||
u8 feature_type;
|
||||
int ret;
|
||||
struct hidpp_report response;
|
||||
|
||||
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
|
||||
&feature_index, &feature_type);
|
||||
if (ret)
|
||||
goto return_default;
|
||||
|
||||
ret = hidpp_send_fap_command_sync(hidpp, feature_index,
|
||||
CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY,
|
||||
NULL, 0, &response);
|
||||
if (ret)
|
||||
goto return_default;
|
||||
|
||||
*multiplier = response.fap.params[0];
|
||||
return 0;
|
||||
return_default:
|
||||
hid_warn(hidpp->hid_dev,
|
||||
"Couldn't get wheel multiplier (error %d), assuming %d.\n",
|
||||
ret, *multiplier);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert,
|
||||
bool high_resolution, bool use_hidpp)
|
||||
{
|
||||
u8 feature_index;
|
||||
u8 feature_type;
|
||||
int ret;
|
||||
u8 params[1];
|
||||
struct hidpp_report response;
|
||||
|
||||
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
|
||||
&feature_index, &feature_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
params[0] = (invert ? BIT(2) : 0) |
|
||||
(high_resolution ? BIT(1) : 0) |
|
||||
(use_hidpp ? BIT(0) : 0);
|
||||
|
||||
return hidpp_send_fap_command_sync(hidpp, feature_index,
|
||||
CMD_HIRES_WHEEL_SET_WHEEL_MODE,
|
||||
params, sizeof(params), &response);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x4301: Solar Keyboard */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -2523,8 +2399,7 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)
|
|||
input_report_rel(mydata->input, REL_Y, v);
|
||||
|
||||
v = hid_snto32(data[6], 8);
|
||||
hid_scroll_counter_handle_scroll(
|
||||
&hidpp->vertical_wheel_counter, v);
|
||||
input_report_rel(mydata->input, REL_WHEEL, v);
|
||||
|
||||
input_sync(mydata->input);
|
||||
}
|
||||
|
@ -2652,72 +2527,6 @@ static int g920_get_config(struct hidpp_device *hidpp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* High-resolution scroll wheels */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* struct hi_res_scroll_info - Stores info on a device's high-res scroll wheel.
|
||||
* @product_id: the HID product ID of the device being described.
|
||||
* @microns_per_hi_res_unit: the distance moved by the user's finger for each
|
||||
* high-resolution unit reported by the device, in
|
||||
* 256ths of a millimetre.
|
||||
*/
|
||||
struct hi_res_scroll_info {
|
||||
__u32 product_id;
|
||||
int microns_per_hi_res_unit;
|
||||
};
|
||||
|
||||
static struct hi_res_scroll_info hi_res_scroll_devices[] = {
|
||||
{ /* Anywhere MX */
|
||||
.product_id = 0x1017, .microns_per_hi_res_unit = 445 },
|
||||
{ /* Performance MX */
|
||||
.product_id = 0x101a, .microns_per_hi_res_unit = 406 },
|
||||
{ /* M560 */
|
||||
.product_id = 0x402d, .microns_per_hi_res_unit = 435 },
|
||||
{ /* MX Master 2S */
|
||||
.product_id = 0x4069, .microns_per_hi_res_unit = 406 },
|
||||
};
|
||||
|
||||
static int hi_res_scroll_look_up_microns(__u32 product_id)
|
||||
{
|
||||
int i;
|
||||
int num_devices = sizeof(hi_res_scroll_devices)
|
||||
/ sizeof(hi_res_scroll_devices[0]);
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
if (hi_res_scroll_devices[i].product_id == product_id)
|
||||
return hi_res_scroll_devices[i].microns_per_hi_res_unit;
|
||||
}
|
||||
/* We don't have a value for this device, so use a sensible default. */
|
||||
return 406;
|
||||
}
|
||||
|
||||
static int hi_res_scroll_enable(struct hidpp_device *hidpp)
|
||||
{
|
||||
int ret;
|
||||
u8 multiplier = 8;
|
||||
|
||||
if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2121) {
|
||||
ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false);
|
||||
hidpp_hrw_get_wheel_capability(hidpp, &multiplier);
|
||||
} else if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2120) {
|
||||
ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true,
|
||||
&multiplier);
|
||||
} else /* if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) */
|
||||
ret = hidpp10_enable_scrolling_acceleration(hidpp);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hidpp->vertical_wheel_counter.resolution_multiplier = multiplier;
|
||||
hidpp->vertical_wheel_counter.microns_per_hi_res_unit =
|
||||
hi_res_scroll_look_up_microns(hidpp->hid_dev->product);
|
||||
hid_info(hidpp->hid_dev, "multiplier = %d, microns = %d\n",
|
||||
multiplier,
|
||||
hidpp->vertical_wheel_counter.microns_per_hi_res_unit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Generic HID++ devices */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -2763,11 +2572,6 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
|
|||
wtp_populate_input(hidpp, input, origin_is_hid_core);
|
||||
else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560)
|
||||
m560_populate_input(hidpp, input, origin_is_hid_core);
|
||||
|
||||
if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) {
|
||||
input_set_capability(input, EV_REL, REL_WHEEL_HI_RES);
|
||||
hidpp->vertical_wheel_counter.dev = input;
|
||||
}
|
||||
}
|
||||
|
||||
static int hidpp_input_configured(struct hid_device *hdev,
|
||||
|
@ -2886,27 +2690,6 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hidpp_event(struct hid_device *hdev, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
/* This function will only be called for scroll events, due to the
|
||||
* restriction imposed in hidpp_usages.
|
||||
*/
|
||||
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
|
||||
struct hid_scroll_counter *counter = &hidpp->vertical_wheel_counter;
|
||||
/* A scroll event may occur before the multiplier has been retrieved or
|
||||
* the input device set, or high-res scroll enabling may fail. In such
|
||||
* cases we must return early (falling back to default behaviour) to
|
||||
* avoid a crash in hid_scroll_counter_handle_scroll.
|
||||
*/
|
||||
if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0
|
||||
|| counter->dev == NULL || counter->resolution_multiplier == 0)
|
||||
return 0;
|
||||
|
||||
hid_scroll_counter_handle_scroll(counter, value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hidpp_initialize_battery(struct hidpp_device *hidpp)
|
||||
{
|
||||
static atomic_t battery_no = ATOMIC_INIT(0);
|
||||
|
@ -3118,9 +2901,6 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
|
|||
if (hidpp->battery.ps)
|
||||
power_supply_changed(hidpp->battery.ps);
|
||||
|
||||
if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL)
|
||||
hi_res_scroll_enable(hidpp);
|
||||
|
||||
if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input)
|
||||
/* if the input nodes are already created, we can stop now */
|
||||
return;
|
||||
|
@ -3306,63 +3086,35 @@ static void hidpp_remove(struct hid_device *hdev)
|
|||
mutex_destroy(&hidpp->send_mutex);
|
||||
}
|
||||
|
||||
#define LDJ_DEVICE(product) \
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \
|
||||
USB_VENDOR_ID_LOGITECH, (product))
|
||||
|
||||
static const struct hid_device_id hidpp_devices[] = {
|
||||
{ /* wireless touchpad */
|
||||
LDJ_DEVICE(0x4011),
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
|
||||
USB_VENDOR_ID_LOGITECH, 0x4011),
|
||||
.driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT |
|
||||
HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS },
|
||||
{ /* wireless touchpad T650 */
|
||||
LDJ_DEVICE(0x4101),
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
|
||||
USB_VENDOR_ID_LOGITECH, 0x4101),
|
||||
.driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT },
|
||||
{ /* wireless touchpad T651 */
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_T651),
|
||||
.driver_data = HIDPP_QUIRK_CLASS_WTP },
|
||||
{ /* Mouse Logitech Anywhere MX */
|
||||
LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
|
||||
{ /* Mouse Logitech Cube */
|
||||
LDJ_DEVICE(0x4010), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 },
|
||||
{ /* Mouse Logitech M335 */
|
||||
LDJ_DEVICE(0x4050), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech M515 */
|
||||
LDJ_DEVICE(0x4007), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 },
|
||||
{ /* Mouse logitech M560 */
|
||||
LDJ_DEVICE(0x402d),
|
||||
.driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560
|
||||
| HIDPP_QUIRK_HI_RES_SCROLL_X2120 },
|
||||
{ /* Mouse Logitech M705 (firmware RQM17) */
|
||||
LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
|
||||
{ /* Mouse Logitech M705 (firmware RQM67) */
|
||||
LDJ_DEVICE(0x406d), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech M720 */
|
||||
LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech MX Anywhere 2 */
|
||||
LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech MX Anywhere 2S */
|
||||
LDJ_DEVICE(0x406a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech MX Master */
|
||||
LDJ_DEVICE(0x4041), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ LDJ_DEVICE(0x4060), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ LDJ_DEVICE(0x4071), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech MX Master 2S */
|
||||
LDJ_DEVICE(0x4069), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
|
||||
{ /* Mouse Logitech Performance MX */
|
||||
LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
|
||||
USB_VENDOR_ID_LOGITECH, 0x402d),
|
||||
.driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
|
||||
{ /* Keyboard logitech K400 */
|
||||
LDJ_DEVICE(0x4024),
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
|
||||
USB_VENDOR_ID_LOGITECH, 0x4024),
|
||||
.driver_data = HIDPP_QUIRK_CLASS_K400 },
|
||||
{ /* Solar Keyboard Logitech K750 */
|
||||
LDJ_DEVICE(0x4002),
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
|
||||
USB_VENDOR_ID_LOGITECH, 0x4002),
|
||||
.driver_data = HIDPP_QUIRK_CLASS_K750 },
|
||||
|
||||
{ LDJ_DEVICE(HID_ANY_ID) },
|
||||
{ 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},
|
||||
|
@ -3371,19 +3123,12 @@ static const struct hid_device_id hidpp_devices[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(hid, hidpp_devices);
|
||||
|
||||
static const struct hid_usage_id hidpp_usages[] = {
|
||||
{ HID_GD_WHEEL, EV_REL, REL_WHEEL },
|
||||
{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
|
||||
};
|
||||
|
||||
static struct hid_driver hidpp_driver = {
|
||||
.name = "logitech-hidpp-device",
|
||||
.id_table = hidpp_devices,
|
||||
.probe = hidpp_probe,
|
||||
.remove = hidpp_remove,
|
||||
.raw_event = hidpp_raw_event,
|
||||
.usage_table = hidpp_usages,
|
||||
.event = hidpp_event,
|
||||
.input_configured = hidpp_input_configured,
|
||||
.input_mapping = hidpp_input_mapping,
|
||||
.input_mapped = hidpp_input_mapped,
|
||||
|
|
|
@ -1814,6 +1814,12 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
|
||||
USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
|
||||
|
||||
/* Cirque devices */
|
||||
{ .driver_data = MT_CLS_WIN_8_DUAL,
|
||||
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
||||
I2C_VENDOR_ID_CIRQUE,
|
||||
I2C_PRODUCT_ID_CIRQUE_121F) },
|
||||
|
||||
/* CJTouch panels */
|
||||
{ .driver_data = MT_CLS_NSMU,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
|
||||
|
|
|
@ -107,6 +107,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
|
||||
|
@ -129,6 +130,8 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003), HID_QUIRK_NOGET },
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
* In order to avoid breaking them this driver creates a layered hidraw device,
|
||||
* so it can detect when the client is running and then:
|
||||
* - it will not send any command to the controller.
|
||||
* - this input device will be disabled, to avoid double input of the same
|
||||
* - this input device will be removed, to avoid double input of the same
|
||||
* user action.
|
||||
* When the client is closed, this input device will be created again.
|
||||
*
|
||||
* For additional functions, such as changing the right-pad margin or switching
|
||||
* the led, you can use the user-space tool at:
|
||||
|
@ -113,7 +114,7 @@ struct steam_device {
|
|||
spinlock_t lock;
|
||||
struct hid_device *hdev, *client_hdev;
|
||||
struct mutex mutex;
|
||||
bool client_opened, input_opened;
|
||||
bool client_opened;
|
||||
struct input_dev __rcu *input;
|
||||
unsigned long quirks;
|
||||
struct work_struct work_connect;
|
||||
|
@ -279,18 +280,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
static void steam_update_lizard_mode(struct steam_device *steam)
|
||||
{
|
||||
mutex_lock(&steam->mutex);
|
||||
if (!steam->client_opened) {
|
||||
if (steam->input_opened)
|
||||
steam_set_lizard_mode(steam, false);
|
||||
else
|
||||
steam_set_lizard_mode(steam, lizard_mode);
|
||||
}
|
||||
mutex_unlock(&steam->mutex);
|
||||
}
|
||||
|
||||
static int steam_input_open(struct input_dev *dev)
|
||||
{
|
||||
struct steam_device *steam = input_get_drvdata(dev);
|
||||
|
@ -301,7 +290,6 @@ static int steam_input_open(struct input_dev *dev)
|
|||
return ret;
|
||||
|
||||
mutex_lock(&steam->mutex);
|
||||
steam->input_opened = true;
|
||||
if (!steam->client_opened && lizard_mode)
|
||||
steam_set_lizard_mode(steam, false);
|
||||
mutex_unlock(&steam->mutex);
|
||||
|
@ -313,7 +301,6 @@ static void steam_input_close(struct input_dev *dev)
|
|||
struct steam_device *steam = input_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&steam->mutex);
|
||||
steam->input_opened = false;
|
||||
if (!steam->client_opened && lizard_mode)
|
||||
steam_set_lizard_mode(steam, true);
|
||||
mutex_unlock(&steam->mutex);
|
||||
|
@ -400,7 +387,7 @@ static int steam_battery_register(struct steam_device *steam)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int steam_register(struct steam_device *steam)
|
||||
static int steam_input_register(struct steam_device *steam)
|
||||
{
|
||||
struct hid_device *hdev = steam->hdev;
|
||||
struct input_dev *input;
|
||||
|
@ -414,17 +401,6 @@ static int steam_register(struct steam_device *steam)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlikely, but getting the serial could fail, and it is not so
|
||||
* important, so make up a serial number and go on.
|
||||
*/
|
||||
if (steam_get_serial(steam) < 0)
|
||||
strlcpy(steam->serial_no, "XXXXXXXXXX",
|
||||
sizeof(steam->serial_no));
|
||||
|
||||
hid_info(hdev, "Steam Controller '%s' connected",
|
||||
steam->serial_no);
|
||||
|
||||
input = input_allocate_device();
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
@ -492,11 +468,6 @@ static int steam_register(struct steam_device *steam)
|
|||
goto input_register_fail;
|
||||
|
||||
rcu_assign_pointer(steam->input, input);
|
||||
|
||||
/* ignore battery errors, we can live without it */
|
||||
if (steam->quirks & STEAM_QUIRK_WIRELESS)
|
||||
steam_battery_register(steam);
|
||||
|
||||
return 0;
|
||||
|
||||
input_register_fail:
|
||||
|
@ -504,27 +475,88 @@ input_register_fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void steam_unregister(struct steam_device *steam)
|
||||
static void steam_input_unregister(struct steam_device *steam)
|
||||
{
|
||||
struct input_dev *input;
|
||||
rcu_read_lock();
|
||||
input = rcu_dereference(steam->input);
|
||||
rcu_read_unlock();
|
||||
if (!input)
|
||||
return;
|
||||
RCU_INIT_POINTER(steam->input, NULL);
|
||||
synchronize_rcu();
|
||||
input_unregister_device(input);
|
||||
}
|
||||
|
||||
static void steam_battery_unregister(struct steam_device *steam)
|
||||
{
|
||||
struct power_supply *battery;
|
||||
|
||||
rcu_read_lock();
|
||||
input = rcu_dereference(steam->input);
|
||||
battery = rcu_dereference(steam->battery);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (battery) {
|
||||
if (!battery)
|
||||
return;
|
||||
RCU_INIT_POINTER(steam->battery, NULL);
|
||||
synchronize_rcu();
|
||||
power_supply_unregister(battery);
|
||||
}
|
||||
if (input) {
|
||||
RCU_INIT_POINTER(steam->input, NULL);
|
||||
synchronize_rcu();
|
||||
|
||||
static int steam_register(struct steam_device *steam)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* This function can be called several times in a row with the
|
||||
* wireless adaptor, without steam_unregister() between them, because
|
||||
* another client send a get_connection_status command, for example.
|
||||
* The battery and serial number are set just once per device.
|
||||
*/
|
||||
if (!steam->serial_no[0]) {
|
||||
/*
|
||||
* Unlikely, but getting the serial could fail, and it is not so
|
||||
* important, so make up a serial number and go on.
|
||||
*/
|
||||
if (steam_get_serial(steam) < 0)
|
||||
strlcpy(steam->serial_no, "XXXXXXXXXX",
|
||||
sizeof(steam->serial_no));
|
||||
|
||||
hid_info(steam->hdev, "Steam Controller '%s' connected",
|
||||
steam->serial_no);
|
||||
|
||||
/* ignore battery errors, we can live without it */
|
||||
if (steam->quirks & STEAM_QUIRK_WIRELESS)
|
||||
steam_battery_register(steam);
|
||||
|
||||
mutex_lock(&steam_devices_lock);
|
||||
list_add(&steam->list, &steam_devices);
|
||||
mutex_unlock(&steam_devices_lock);
|
||||
}
|
||||
|
||||
mutex_lock(&steam->mutex);
|
||||
if (!steam->client_opened) {
|
||||
steam_set_lizard_mode(steam, lizard_mode);
|
||||
ret = steam_input_register(steam);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mutex_unlock(&steam->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void steam_unregister(struct steam_device *steam)
|
||||
{
|
||||
steam_battery_unregister(steam);
|
||||
steam_input_unregister(steam);
|
||||
if (steam->serial_no[0]) {
|
||||
hid_info(steam->hdev, "Steam Controller '%s' disconnected",
|
||||
steam->serial_no);
|
||||
input_unregister_device(input);
|
||||
mutex_lock(&steam_devices_lock);
|
||||
list_del(&steam->list);
|
||||
mutex_unlock(&steam_devices_lock);
|
||||
steam->serial_no[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,6 +632,9 @@ static int steam_client_ll_open(struct hid_device *hdev)
|
|||
mutex_lock(&steam->mutex);
|
||||
steam->client_opened = true;
|
||||
mutex_unlock(&steam->mutex);
|
||||
|
||||
steam_input_unregister(steam);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -609,13 +644,13 @@ static void steam_client_ll_close(struct hid_device *hdev)
|
|||
|
||||
mutex_lock(&steam->mutex);
|
||||
steam->client_opened = false;
|
||||
if (steam->input_opened)
|
||||
steam_set_lizard_mode(steam, false);
|
||||
else
|
||||
steam_set_lizard_mode(steam, lizard_mode);
|
||||
mutex_unlock(&steam->mutex);
|
||||
|
||||
hid_hw_close(steam->hdev);
|
||||
if (steam->connected) {
|
||||
steam_set_lizard_mode(steam, lizard_mode);
|
||||
steam_input_register(steam);
|
||||
}
|
||||
}
|
||||
|
||||
static int steam_client_ll_raw_request(struct hid_device *hdev,
|
||||
|
@ -744,11 +779,6 @@ static int steam_probe(struct hid_device *hdev,
|
|||
}
|
||||
}
|
||||
|
||||
mutex_lock(&steam_devices_lock);
|
||||
steam_update_lizard_mode(steam);
|
||||
list_add(&steam->list, &steam_devices);
|
||||
mutex_unlock(&steam_devices_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
hid_hw_open_fail:
|
||||
|
@ -774,10 +804,6 @@ static void steam_remove(struct hid_device *hdev)
|
|||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&steam_devices_lock);
|
||||
list_del(&steam->list);
|
||||
mutex_unlock(&steam_devices_lock);
|
||||
|
||||
hid_destroy_device(steam->client_hdev);
|
||||
steam->client_opened = false;
|
||||
cancel_work_sync(&steam->work_connect);
|
||||
|
@ -792,12 +818,14 @@ static void steam_remove(struct hid_device *hdev)
|
|||
static void steam_do_connect_event(struct steam_device *steam, bool connected)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool changed;
|
||||
|
||||
spin_lock_irqsave(&steam->lock, flags);
|
||||
changed = steam->connected != connected;
|
||||
steam->connected = connected;
|
||||
spin_unlock_irqrestore(&steam->lock, flags);
|
||||
|
||||
if (schedule_work(&steam->work_connect) == 0)
|
||||
if (changed && schedule_work(&steam->work_connect) == 0)
|
||||
dbg_hid("%s: connected=%d event already queued\n",
|
||||
__func__, connected);
|
||||
}
|
||||
|
@ -1019,13 +1047,8 @@ static int steam_raw_event(struct hid_device *hdev,
|
|||
return 0;
|
||||
rcu_read_lock();
|
||||
input = rcu_dereference(steam->input);
|
||||
if (likely(input)) {
|
||||
if (likely(input))
|
||||
steam_do_input_event(steam, input, data);
|
||||
} else {
|
||||
dbg_hid("%s: input data without connect event\n",
|
||||
__func__);
|
||||
steam_do_connect_event(steam, true);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
case STEAM_EV_CONNECT:
|
||||
|
@ -1074,7 +1097,10 @@ static int steam_param_set_lizard_mode(const char *val,
|
|||
|
||||
mutex_lock(&steam_devices_lock);
|
||||
list_for_each_entry(steam, &steam_devices, list) {
|
||||
steam_update_lizard_mode(steam);
|
||||
mutex_lock(&steam->mutex);
|
||||
if (!steam->client_opened)
|
||||
steam_set_lizard_mode(steam, lizard_mode);
|
||||
mutex_unlock(&steam->mutex);
|
||||
}
|
||||
mutex_unlock(&steam_devices_lock);
|
||||
return 0;
|
||||
|
|
|
@ -177,6 +177,8 @@ static const struct i2c_hid_quirks {
|
|||
I2C_HID_QUIRK_NO_RUNTIME_PM },
|
||||
{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33,
|
||||
I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
|
||||
{ USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
|
||||
I2C_HID_QUIRK_NO_RUNTIME_PM },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hid.h>
|
||||
|
@ -496,12 +497,13 @@ static int uhid_dev_create2(struct uhid_device *uhid,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
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 is zero-initialized, strncpy() is correct, strlcpy() not */
|
||||
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);
|
||||
|
||||
hid->ll_driver = &uhid_hid_driver;
|
||||
hid->bus = ev->u.create2.bus;
|
||||
|
@ -722,6 +724,17 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
|
|||
|
||||
switch (uhid->input_buf.type) {
|
||||
case UHID_CREATE:
|
||||
/*
|
||||
* 'struct uhid_create_req' contains a __user pointer which is
|
||||
* copied from, so it's unsafe to allow this with elevated
|
||||
* privileges (e.g. from a setuid binary) or via kernel_write().
|
||||
*/
|
||||
if (file->f_cred != current_cred() || uaccess_kernel()) {
|
||||
pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n",
|
||||
task_tgid_vnr(current), current->comm);
|
||||
ret = -EACCES;
|
||||
goto unlock;
|
||||
}
|
||||
ret = uhid_dev_create(uhid, &uhid->input_buf);
|
||||
break;
|
||||
case UHID_CREATE2:
|
||||
|
|
|
@ -1139,34 +1139,6 @@ static inline u32 hid_report_len(struct hid_report *report)
|
|||
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
|
||||
int interrupt);
|
||||
|
||||
|
||||
/**
|
||||
* struct hid_scroll_counter - Utility class for processing high-resolution
|
||||
* scroll events.
|
||||
* @dev: the input device for which events should be reported.
|
||||
* @microns_per_hi_res_unit: the amount moved by the user's finger for each
|
||||
* high-resolution unit reported by the mouse, in
|
||||
* microns.
|
||||
* @resolution_multiplier: the wheel's resolution in high-resolution mode as a
|
||||
* multiple of its lower resolution. For example, if
|
||||
* moving the wheel by one "notch" would result in a
|
||||
* value of 1 in low-resolution mode but 8 in
|
||||
* high-resolution, the multiplier is 8.
|
||||
* @remainder: counts the number of high-resolution units moved since the last
|
||||
* low-resolution event (REL_WHEEL or REL_HWHEEL) was sent. Should
|
||||
* only be used by class methods.
|
||||
*/
|
||||
struct hid_scroll_counter {
|
||||
struct input_dev *dev;
|
||||
int microns_per_hi_res_unit;
|
||||
int resolution_multiplier;
|
||||
|
||||
int remainder;
|
||||
};
|
||||
|
||||
void hid_scroll_counter_handle_scroll(struct hid_scroll_counter *counter,
|
||||
int hi_res_value);
|
||||
|
||||
/* HID quirks API */
|
||||
unsigned long hid_lookup_quirk(const struct hid_device *hdev);
|
||||
int hid_quirks_init(char **quirks_param, __u16 bus, int count);
|
||||
|
|
|
@ -716,7 +716,6 @@
|
|||
* the situation described above.
|
||||
*/
|
||||
#define REL_RESERVED 0x0a
|
||||
#define REL_WHEEL_HI_RES 0x0b
|
||||
#define REL_MAX 0x0f
|
||||
#define REL_CNT (REL_MAX+1)
|
||||
|
||||
|
@ -753,15 +752,6 @@
|
|||
|
||||
#define ABS_MISC 0x28
|
||||
|
||||
/*
|
||||
* 0x2e is reserved and should not be used in input drivers.
|
||||
* It was used by HID as ABS_MISC+6 and userspace needs to detect if
|
||||
* the next ABS_* event is correct or is just ABS_MISC + n.
|
||||
* We define here ABS_RESERVED so userspace can rely on it and detect
|
||||
* the situation described above.
|
||||
*/
|
||||
#define ABS_RESERVED 0x2e
|
||||
|
||||
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
|
||||
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
|
||||
|
|
Загрузка…
Ссылка в новой задаче