Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
276e7227
Commit
276e7227
authored
Oct 23, 2018
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.20/logitech-highres' into for-linus
High-resolution support for hid-logitech
parents
4e7be68e
d9ca1c99
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
383 additions
and
28 deletions
+383
-28
Documentation/input/event-codes.rst
Documentation/input/event-codes.rst
+10
-1
drivers/hid/hid-input.c
drivers/hid/hid-input.c
+45
-0
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-logitech-hidpp.c
+282
-27
include/linux/hid.h
include/linux/hid.h
+28
-0
include/uapi/linux/input-event-codes.h
include/uapi/linux/input-event-codes.h
+18
-0
No files found.
Documentation/input/event-codes.rst
View file @
276e7227
...
@@ -190,7 +190,16 @@ A few EV_REL codes have special meanings:
...
@@ -190,7 +190,16 @@ A few EV_REL codes have special meanings:
* REL_WHEEL, REL_HWHEEL:
* REL_WHEEL, REL_HWHEEL:
- These codes are used for vertical and horizontal scroll wheels,
- These codes are used for vertical and horizontal scroll wheels,
respectively.
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.
EV_ABS
EV_ABS
------
------
...
...
drivers/hid/hid-input.c
View file @
276e7227
...
@@ -1838,3 +1838,48 @@ void hidinput_disconnect(struct hid_device *hid)
...
@@ -1838,3 +1838,48 @@ void hidinput_disconnect(struct hid_device *hid)
}
}
EXPORT_SYMBOL_GPL
(
hidinput_disconnect
);
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_scroll_amount
;
/* Some wheels will rest 7/8ths of a notch from the previous notch
* after slow movement, so we want the threshold for low-res events to
* be in the middle of the notches (e.g. after 4/8ths) as opposed to on
* the notches themselves (8/8ths).
*/
int
threshold
=
counter
->
resolution_multiplier
/
2
;
input_report_rel
(
counter
->
dev
,
REL_WHEEL_HI_RES
,
hi_res_value
*
counter
->
microns_per_hi_res_unit
);
counter
->
remainder
+=
hi_res_value
;
if
(
abs
(
counter
->
remainder
)
>=
threshold
)
{
/* Add (or subtract) 1 because we want to trigger when the wheel
* is half-way to the next notch (i.e. scroll 1 notch after a
* 1/2 notch movement, 2 notches after a 1 1/2 notch movement,
* etc.).
*/
low_res_scroll_amount
=
counter
->
remainder
/
counter
->
resolution_multiplier
+
(
hi_res_value
>
0
?
1
:
-
1
);
input_report_rel
(
counter
->
dev
,
REL_WHEEL
,
low_res_scroll_amount
);
counter
->
remainder
-=
low_res_scroll_amount
*
counter
->
resolution_multiplier
;
}
}
EXPORT_SYMBOL_GPL
(
hid_scroll_counter_handle_scroll
);
drivers/hid/hid-logitech-hidpp.c
View file @
276e7227
...
@@ -64,6 +64,14 @@ MODULE_PARM_DESC(disable_tap_to_click,
...
@@ -64,6 +64,14 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
#define HIDPP_QUIRK_UNIFYING BIT(25)
#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
#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
...
@@ -149,6 +157,7 @@ struct hidpp_device {
...
@@ -149,6 +157,7 @@ struct hidpp_device {
unsigned
long
capabilities
;
unsigned
long
capabilities
;
struct
hidpp_battery
battery
;
struct
hidpp_battery
battery
;
struct
hid_scroll_counter
vertical_wheel_counter
;
};
};
/* HID++ 1.0 error codes */
/* HID++ 1.0 error codes */
...
@@ -400,9 +409,15 @@ static void hidpp_prefix_name(char **name, int name_length)
...
@@ -400,9 +409,15 @@ static void hidpp_prefix_name(char **name, int name_length)
#define HIDPP_SET_LONG_REGISTER 0x82
#define HIDPP_SET_LONG_REGISTER 0x82
#define HIDPP_GET_LONG_REGISTER 0x83
#define HIDPP_GET_LONG_REGISTER 0x83
#define HIDPP_REG_GENERAL 0x00
/**
* hidpp10_set_register_bit() - Sets a single bit in a HID++ 1.0 register.
static
int
hidpp10_enable_battery_reporting
(
struct
hidpp_device
*
hidpp_dev
)
* @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
)
{
{
struct
hidpp_report
response
;
struct
hidpp_report
response
;
int
ret
;
int
ret
;
...
@@ -411,23 +426,38 @@ static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)
...
@@ -411,23 +426,38 @@ static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)
ret
=
hidpp_send_rap_command_sync
(
hidpp_dev
,
ret
=
hidpp_send_rap_command_sync
(
hidpp_dev
,
REPORT_ID_HIDPP_SHORT
,
REPORT_ID_HIDPP_SHORT
,
HIDPP_GET_REGISTER
,
HIDPP_GET_REGISTER
,
HIDPP_REG_GENERAL
,
register_address
,
NULL
,
0
,
&
response
);
NULL
,
0
,
&
response
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
memcpy
(
params
,
response
.
rap
.
params
,
3
);
memcpy
(
params
,
response
.
rap
.
params
,
3
);
/* Set the battery bit */
params
[
byte
]
|=
BIT
(
bit
);
params
[
0
]
|=
BIT
(
4
);
return
hidpp_send_rap_command_sync
(
hidpp_dev
,
return
hidpp_send_rap_command_sync
(
hidpp_dev
,
REPORT_ID_HIDPP_SHORT
,
REPORT_ID_HIDPP_SHORT
,
HIDPP_SET_REGISTER
,
HIDPP_SET_REGISTER
,
HIDPP_REG_GENERAL
,
register_address
,
params
,
3
,
&
response
);
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
#define HIDPP_REG_BATTERY_STATUS 0x07
static
int
hidpp10_battery_status_map_level
(
u8
param
)
static
int
hidpp10_battery_status_map_level
(
u8
param
)
...
@@ -1136,6 +1166,100 @@ static int hidpp_battery_get_property(struct power_supply *psy,
...
@@ -1136,6 +1166,100 @@ static int hidpp_battery_get_property(struct power_supply *psy,
return
ret
;
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 */
/* 0x4301: Solar Keyboard */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
...
@@ -2399,7 +2523,8 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)
...
@@ -2399,7 +2523,8 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)
input_report_rel
(
mydata
->
input
,
REL_Y
,
v
);
input_report_rel
(
mydata
->
input
,
REL_Y
,
v
);
v
=
hid_snto32
(
data
[
6
],
8
);
v
=
hid_snto32
(
data
[
6
],
8
);
input_report_rel
(
mydata
->
input
,
REL_WHEEL
,
v
);
hid_scroll_counter_handle_scroll
(
&
hidpp
->
vertical_wheel_counter
,
v
);
input_sync
(
mydata
->
input
);
input_sync
(
mydata
->
input
);
}
}
...
@@ -2527,6 +2652,72 @@ static int g920_get_config(struct hidpp_device *hidpp)
...
@@ -2527,6 +2652,72 @@ static int g920_get_config(struct hidpp_device *hidpp)
return
0
;
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 */
/* Generic HID++ devices */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
...
@@ -2572,6 +2763,11 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
...
@@ -2572,6 +2763,11 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
wtp_populate_input
(
hidpp
,
input
,
origin_is_hid_core
);
wtp_populate_input
(
hidpp
,
input
,
origin_is_hid_core
);
else
if
(
hidpp
->
quirks
&
HIDPP_QUIRK_CLASS_M560
)
else
if
(
hidpp
->
quirks
&
HIDPP_QUIRK_CLASS_M560
)
m560_populate_input
(
hidpp
,
input
,
origin_is_hid_core
);
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
,
static
int
hidpp_input_configured
(
struct
hid_device
*
hdev
,
...
@@ -2690,6 +2886,27 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
...
@@ -2690,6 +2886,27 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
return
0
;
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
int
hidpp_initialize_battery
(
struct
hidpp_device
*
hidpp
)
{
{
static
atomic_t
battery_no
=
ATOMIC_INIT
(
0
);
static
atomic_t
battery_no
=
ATOMIC_INIT
(
0
);
...
@@ -2901,6 +3118,9 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
...
@@ -2901,6 +3118,9 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
if
(
hidpp
->
battery
.
ps
)
if
(
hidpp
->
battery
.
ps
)
power_supply_changed
(
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
(
!
(
hidpp
->
quirks
&
HIDPP_QUIRK_NO_HIDINPUT
)
||
hidpp
->
delayed_input
)
/* if the input nodes are already created, we can stop now */
/* if the input nodes are already created, we can stop now */
return
;
return
;
...
@@ -3086,35 +3306,63 @@ static void hidpp_remove(struct hid_device *hdev)
...
@@ -3086,35 +3306,63 @@ static void hidpp_remove(struct hid_device *hdev)
mutex_destroy
(
&
hidpp
->
send_mutex
);
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
[]
=
{
static
const
struct
hid_device_id
hidpp_devices
[]
=
{
{
/* wireless touchpad */
{
/* wireless touchpad */
HID_DEVICE
(
BUS_USB
,
HID_GROUP_LOGITECH_DJ_DEVICE
,
LDJ_DEVICE
(
0x4011
),
USB_VENDOR_ID_LOGITECH
,
0x4011
),
.
driver_data
=
HIDPP_QUIRK_CLASS_WTP
|
HIDPP_QUIRK_DELAYED_INIT
|
.
driver_data
=
HIDPP_QUIRK_CLASS_WTP
|
HIDPP_QUIRK_DELAYED_INIT
|
HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS
},
HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS
},
{
/* wireless touchpad T650 */
{
/* wireless touchpad T650 */
HID_DEVICE
(
BUS_USB
,
HID_GROUP_LOGITECH_DJ_DEVICE
,
LDJ_DEVICE
(
0x4101
),
USB_VENDOR_ID_LOGITECH
,
0x4101
),
.
driver_data
=
HIDPP_QUIRK_CLASS_WTP
|
HIDPP_QUIRK_DELAYED_INIT
},
.
driver_data
=
HIDPP_QUIRK_CLASS_WTP
|
HIDPP_QUIRK_DELAYED_INIT
},
{
/* wireless touchpad T651 */
{
/* wireless touchpad T651 */
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_LOGITECH
,
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_LOGITECH_T651
),
USB_DEVICE_ID_LOGITECH_T651
),
.
driver_data
=
HIDPP_QUIRK_CLASS_WTP
},
.
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 */
{
/* Mouse logitech M560 */
HID_DEVICE
(
BUS_USB
,
HID_GROUP_LOGITECH_DJ_DEVICE
,
LDJ_DEVICE
(
0x402d
),
USB_VENDOR_ID_LOGITECH
,
0x402d
),
.
driver_data
=
HIDPP_QUIRK_DELAYED_INIT
|
HIDPP_QUIRK_CLASS_M560
.
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
},
{
/* Keyboard logitech K400 */
{
/* Keyboard logitech K400 */
HID_DEVICE
(
BUS_USB
,
HID_GROUP_LOGITECH_DJ_DEVICE
,
LDJ_DEVICE
(
0x4024
),
USB_VENDOR_ID_LOGITECH
,
0x4024
),
.
driver_data
=
HIDPP_QUIRK_CLASS_K400
},
.
driver_data
=
HIDPP_QUIRK_CLASS_K400
},
{
/* Solar Keyboard Logitech K750 */
{
/* Solar Keyboard Logitech K750 */
HID_DEVICE
(
BUS_USB
,
HID_GROUP_LOGITECH_DJ_DEVICE
,
LDJ_DEVICE
(
0x4002
),
USB_VENDOR_ID_LOGITECH
,
0x4002
),
.
driver_data
=
HIDPP_QUIRK_CLASS_K750
},
.
driver_data
=
HIDPP_QUIRK_CLASS_K750
},
{
HID_DEVICE
(
BUS_USB
,
HID_GROUP_LOGITECH_DJ_DEVICE
,
{
LDJ_DEVICE
(
HID_ANY_ID
)
},
USB_VENDOR_ID_LOGITECH
,
HID_ANY_ID
)},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_LOGITECH_G920_WHEEL
),
{
HID_USB_DEVICE
(
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_LOGITECH_G920_WHEEL
),
.
driver_data
=
HIDPP_QUIRK_CLASS_G920
|
HIDPP_QUIRK_FORCE_OUTPUT_REPORTS
},
.
driver_data
=
HIDPP_QUIRK_CLASS_G920
|
HIDPP_QUIRK_FORCE_OUTPUT_REPORTS
},
...
@@ -3123,12 +3371,19 @@ static const struct hid_device_id hidpp_devices[] = {
...
@@ -3123,12 +3371,19 @@ static const struct hid_device_id hidpp_devices[] = {
MODULE_DEVICE_TABLE
(
hid
,
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
=
{
static
struct
hid_driver
hidpp_driver
=
{
.
name
=
"logitech-hidpp-device"
,
.
name
=
"logitech-hidpp-device"
,
.
id_table
=
hidpp_devices
,
.
id_table
=
hidpp_devices
,
.
probe
=
hidpp_probe
,
.
probe
=
hidpp_probe
,
.
remove
=
hidpp_remove
,
.
remove
=
hidpp_remove
,
.
raw_event
=
hidpp_raw_event
,
.
raw_event
=
hidpp_raw_event
,
.
usage_table
=
hidpp_usages
,
.
event
=
hidpp_event
,
.
input_configured
=
hidpp_input_configured
,
.
input_configured
=
hidpp_input_configured
,
.
input_mapping
=
hidpp_input_mapping
,
.
input_mapping
=
hidpp_input_mapping
,
.
input_mapped
=
hidpp_input_mapped
,
.
input_mapped
=
hidpp_input_mapped
,
...
...
include/linux/hid.h
View file @
276e7227
...
@@ -1139,6 +1139,34 @@ static inline u32 hid_report_len(struct hid_report *report)
...
@@ -1139,6 +1139,34 @@ 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
hid_report_raw_event
(
struct
hid_device
*
hid
,
int
type
,
u8
*
data
,
u32
size
,
int
interrupt
);
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 */
/* HID quirks API */
unsigned
long
hid_lookup_quirk
(
const
struct
hid_device
*
hdev
);
unsigned
long
hid_lookup_quirk
(
const
struct
hid_device
*
hdev
);
int
hid_quirks_init
(
char
**
quirks_param
,
__u16
bus
,
int
count
);
int
hid_quirks_init
(
char
**
quirks_param
,
__u16
bus
,
int
count
);
...
...
include/uapi/linux/input-event-codes.h
View file @
276e7227
...
@@ -708,6 +708,15 @@
...
@@ -708,6 +708,15 @@
#define REL_DIAL 0x07
#define REL_DIAL 0x07
#define REL_WHEEL 0x08
#define REL_WHEEL 0x08
#define REL_MISC 0x09
#define REL_MISC 0x09
/*
* 0x0a is reserved and should not be used in input drivers.
* It was used by HID as REL_MISC+1 and userspace needs to detect if
* the next REL_* event is correct or is just REL_MISC + n.
* We define here REL_RESERVED so userspace can rely on it and detect
* the situation described above.
*/
#define REL_RESERVED 0x0a
#define REL_WHEEL_HI_RES 0x0b
#define REL_MAX 0x0f
#define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1)
#define REL_CNT (REL_MAX+1)
...
@@ -744,6 +753,15 @@
...
@@ -744,6 +753,15 @@
#define ABS_MISC 0x28
#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_SLOT 0x2f
/* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30
/* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MAJOR 0x30
/* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31
/* Minor axis (omit if circular) */
#define ABS_MT_TOUCH_MINOR 0x31
/* Minor axis (omit if circular) */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment