提交 d5530d82 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID fixes from Jiri Kosina:

 - Various functionality / regression fixes for Logitech devices from
   Hans de Goede

 - Fix for (recently added) GPIO support in mcp2221 driver from Lars
   Povlsen

 - Power management handling fix/quirk in i2c-hid driver for certain
   BIOSes that have strange aproach to power-cycle from Hans de Goede

 - a few device ID additions and device-specific quirks

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
  HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
  HID: Add Logitech Dinovo Edge battery quirk
  HID: logitech-hidpp: Add HIDPP_CONSUMER_VENDOR_KEYS quirk for the Dinovo Edge
  HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
  HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
  HID: mcp2221: Fix GPIO output handling
  HID: hid-sensor-hub: Fix issue with devices with no report ID
  HID: i2c-hid: Put ACPI enumerated devices in D3 on shutdown
  HID: add support for Sega Saturn
  HID: cypress: Support Varmilo Keyboards' media hotkeys
  HID: ite: Replace ABS_MISC 120/121 events with touchpad on/off keypresses
  HID: logitech-hidpp: Add PID for MX Anywhere 2
  HID: uclogic: Add ID for Trust Flex Design Tablet
...@@ -23,19 +23,17 @@ ...@@ -23,19 +23,17 @@
#define CP_2WHEEL_MOUSE_HACK 0x02 #define CP_2WHEEL_MOUSE_HACK 0x02
#define CP_2WHEEL_MOUSE_HACK_ON 0x04 #define CP_2WHEEL_MOUSE_HACK_ON 0x04
#define VA_INVAL_LOGICAL_BOUNDARY 0x08
/* /*
* Some USB barcode readers from cypress have usage min and usage max in * Some USB barcode readers from cypress have usage min and usage max in
* the wrong order * the wrong order
*/ */
static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize) unsigned int *rsize)
{ {
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
unsigned int i; unsigned int i;
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
return rdesc;
if (*rsize < 4) if (*rsize < 4)
return rdesc; return rdesc;
...@@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc; return rdesc;
} }
static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
/*
* Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly
* reports Logical Minimum of its Consumer Control device as 572
* (0x02 0x3c). Fix this by setting its Logical Minimum to zero.
*/
if (*rsize == 25 &&
rdesc[0] == 0x05 && rdesc[1] == 0x0c &&
rdesc[2] == 0x09 && rdesc[3] == 0x01 &&
rdesc[6] == 0x19 && rdesc[7] == 0x00 &&
rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) {
hid_info(hdev,
"fixing up varmilo VA104M consumer control report descriptor\n");
rdesc[12] = 0x00;
rdesc[13] = 0x00;
}
return rdesc;
}
static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if (quirks & CP_RDESC_SWAPPED_MIN_MAX)
rdesc = cp_rdesc_fixup(hdev, rdesc, rsize);
if (quirks & VA_INVAL_LOGICAL_BOUNDARY)
rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize);
return rdesc;
}
static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage, struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max) unsigned long **bit, int *max)
...@@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = { ...@@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = {
.driver_data = CP_RDESC_SWAPPED_MIN_MAX }, .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
.driver_data = CP_2WHEEL_MOUSE_HACK }, .driver_data = CP_2WHEEL_MOUSE_HACK },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1),
.driver_data = VA_INVAL_LOGICAL_BOUNDARY },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, cp_devices); MODULE_DEVICE_TABLE(hid, cp_devices);
......
...@@ -331,6 +331,8 @@ ...@@ -331,6 +331,8 @@
#define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 #define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81
#define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001
#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1 0X07b1
#define USB_VENDOR_ID_DATA_MODUL 0x7374 #define USB_VENDOR_ID_DATA_MODUL 0x7374
#define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH 0x1201 #define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH 0x1201
...@@ -443,6 +445,10 @@ ...@@ -443,6 +445,10 @@
#define USB_VENDOR_ID_FRUCTEL 0x25B6 #define USB_VENDOR_ID_FRUCTEL 0x25B6
#define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002 #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002
#define USB_VENDOR_ID_GAMEVICE 0x27F8
#define USB_DEVICE_ID_GAMEVICE_GV186 0x0BBE
#define USB_DEVICE_ID_GAMEVICE_KISHI 0x0BBF
#define USB_VENDOR_ID_GAMERON 0x0810 #define USB_VENDOR_ID_GAMERON 0x0810
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002
...@@ -485,6 +491,7 @@ ...@@ -485,6 +491,7 @@
#define USB_DEVICE_ID_PENPOWER 0x00f4 #define USB_DEVICE_ID_PENPOWER 0x00f4
#define USB_VENDOR_ID_GREENASIA 0x0e8f #define USB_VENDOR_ID_GREENASIA 0x0e8f
#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010
#define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013 #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013
#define USB_VENDOR_ID_GRETAGMACBETH 0x0971 #define USB_VENDOR_ID_GRETAGMACBETH 0x0971
...@@ -743,6 +750,7 @@ ...@@ -743,6 +750,7 @@
#define USB_VENDOR_ID_LOGITECH 0x046d #define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
#define USB_DEVICE_ID_LOGITECH_T651 0xb00c #define USB_DEVICE_ID_LOGITECH_T651 0xb00c
#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309
#define USB_DEVICE_ID_LOGITECH_C007 0xc007 #define USB_DEVICE_ID_LOGITECH_C007 0xc007
#define USB_DEVICE_ID_LOGITECH_C077 0xc077 #define USB_DEVICE_ID_LOGITECH_C077 0xc077
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
...@@ -1298,6 +1306,7 @@ ...@@ -1298,6 +1306,7 @@
#define USB_VENDOR_ID_UGTIZER 0x2179 #define USB_VENDOR_ID_UGTIZER 0x2179
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053 #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053
#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077
#define USB_VENDOR_ID_VIEWSONIC 0x0543 #define USB_VENDOR_ID_VIEWSONIC 0x0543
#define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621 #define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621
......
...@@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = { ...@@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
HID_BATTERY_QUIRK_IGNORE }, HID_BATTERY_QUIRK_IGNORE },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
HID_BATTERY_QUIRK_IGNORE },
{} {}
}; };
......
...@@ -11,6 +11,48 @@ ...@@ -11,6 +11,48 @@
#include "hid-ids.h" #include "hid-ids.h"
#define QUIRK_TOUCHPAD_ON_OFF_REPORT BIT(0)
static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
hid_info(hdev, "Fixing up ITE keyboard report descriptor\n");
rdesc[163] = HID_MAIN_ITEM_RELATIVE;
}
}
return rdesc;
}
static int ite_input_mapping(struct hid_device *hdev,
struct hid_input *hi, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit,
int *max)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
(usage->hid & HID_USAGE_PAGE) == 0x00880000) {
if (usage->hid == 0x00880078) {
/* Touchpad on, userspace expects F22 for this */
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
return 1;
}
if (usage->hid == 0x00880079) {
/* Touchpad off, userspace expects F23 for this */
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
return 1;
}
return -1;
}
return 0;
}
static int ite_event(struct hid_device *hdev, struct hid_field *field, static int ite_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value) struct hid_usage *usage, __s32 value)
{ {
...@@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field, ...@@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
return 0; return 0;
} }
static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
hid_set_drvdata(hdev, (void *)id->driver_data);
ret = hid_open_report(hdev);
if (ret)
return ret;
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
static const struct hid_device_id ite_devices[] = { static const struct hid_device_id ite_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) }, { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) }, { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */ /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_SYNAPTICS, USB_VENDOR_ID_SYNAPTICS,
USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) }, USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
.driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
/* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_SYNAPTICS, USB_VENDOR_ID_SYNAPTICS,
...@@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices); ...@@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices);
static struct hid_driver ite_driver = { static struct hid_driver ite_driver = {
.name = "itetech", .name = "itetech",
.id_table = ite_devices, .id_table = ite_devices,
.probe = ite_probe,
.report_fixup = ite_report_fixup,
.input_mapping = ite_input_mapping,
.event = ite_event, .event = ite_event,
}; };
module_hid_driver(ite_driver); module_hid_driver(ite_driver);
......
...@@ -328,7 +328,7 @@ static const char mse_bluetooth_descriptor[] = { ...@@ -328,7 +328,7 @@ static const char mse_bluetooth_descriptor[] = {
0x25, 0x01, /* LOGICAL_MAX (1) */ 0x25, 0x01, /* LOGICAL_MAX (1) */
0x75, 0x01, /* REPORT_SIZE (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */
0x95, 0x04, /* REPORT_COUNT (4) */ 0x95, 0x04, /* REPORT_COUNT (4) */
0x81, 0x06, /* INPUT */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */
0xC0, /* END_COLLECTION */ 0xC0, /* END_COLLECTION */
0xC0, /* END_COLLECTION */ 0xC0, /* END_COLLECTION */
}; };
...@@ -866,11 +866,24 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, ...@@ -866,11 +866,24 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
schedule_work(&djrcv_dev->work); schedule_work(&djrcv_dev->work);
} }
/*
* Some quad/bluetooth keyboards have a builtin touchpad in this case we see
* only 1 paired device with a device_type of REPORT_TYPE_KEYBOARD. For the
* touchpad to work we must also forward mouse input reports to the dj_hiddev
* created for the keyboard (instead of forwarding them to a second paired
* device with a device_type of REPORT_TYPE_MOUSE as we normally would).
*/
static const u16 kbd_builtin_touchpad_ids[] = {
0xb309, /* Dinovo Edge */
0xb30c, /* Dinovo Mini */
};
static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev, static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
struct hidpp_event *hidpp_report, struct hidpp_event *hidpp_report,
struct dj_workitem *workitem) struct dj_workitem *workitem)
{ {
struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
int i, id;
workitem->type = WORKITEM_TYPE_PAIRED; workitem->type = WORKITEM_TYPE_PAIRED;
workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
...@@ -882,6 +895,13 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev, ...@@ -882,6 +895,13 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
POWER_KEYS | MEDIA_CENTER | POWER_KEYS | MEDIA_CENTER |
HIDPP; HIDPP;
id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb;
for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) {
if (id == kbd_builtin_touchpad_ids[i]) {
workitem->reports_supported |= STD_MOUSE;
break;
}
}
break; break;
case REPORT_TYPE_MOUSE: case REPORT_TYPE_MOUSE:
workitem->reports_supported |= STD_MOUSE | HIDPP; workitem->reports_supported |= STD_MOUSE | HIDPP;
......
...@@ -93,6 +93,8 @@ MODULE_PARM_DESC(disable_tap_to_click, ...@@ -93,6 +93,8 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3) #define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3)
#define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4) #define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4)
#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
/* /*
* There are two hidpp protocols in use, the first version hidpp10 is known * There are two hidpp protocols in use, the first version hidpp10 is known
* as register access protocol or RAP, the second version hidpp20 is known as * as register access protocol or RAP, the second version hidpp20 is known as
...@@ -2950,6 +2952,26 @@ static int g920_get_config(struct hidpp_device *hidpp, ...@@ -2950,6 +2952,26 @@ static int g920_get_config(struct hidpp_device *hidpp,
return g920_ff_set_autocenter(hidpp, data); return g920_ff_set_autocenter(hidpp, data);
} }
/* -------------------------------------------------------------------------- */
/* Logitech Dinovo Mini keyboard with builtin touchpad */
/* -------------------------------------------------------------------------- */
#define DINOVO_MINI_PRODUCT_ID 0xb30c
static int lg_dinovo_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
return 0;
switch (usage->hid & HID_USAGE) {
case 0x00d: lg_map_key_clear(KEY_MEDIA); break;
default:
return 0;
}
return 1;
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* HID++1.0 devices which use HID++ reports for their wheels */ /* HID++1.0 devices which use HID++ reports for their wheels */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
...@@ -3185,6 +3207,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -3185,6 +3207,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
field->application != HID_GD_MOUSE) field->application != HID_GD_MOUSE)
return m560_input_mapping(hdev, hi, field, usage, bit, max); return m560_input_mapping(hdev, hi, field, usage, bit, max);
if (hdev->product == DINOVO_MINI_PRODUCT_ID)
return lg_dinovo_input_mapping(hdev, hi, field, usage, bit, max);
return 0; return 0;
} }
...@@ -3947,6 +3972,7 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -3947,6 +3972,7 @@ static const struct hid_device_id hidpp_devices[] = {
LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech MX Anywhere 2 */ { /* Mouse Logitech MX Anywhere 2 */
LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0xb013), .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(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, { LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
...@@ -3971,6 +3997,9 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -3971,6 +3997,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */ { /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */
LDJ_DEVICE(0xb305), LDJ_DEVICE(0xb305),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
{ /* Dinovo Edge (Bluetooth-receiver in HID proxy mode) */
LDJ_DEVICE(0xb309),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
{ /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */ { /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */
LDJ_DEVICE(0xb30b), LDJ_DEVICE(0xb30b),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
...@@ -4013,6 +4042,9 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -4013,6 +4042,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* MX5000 keyboard over Bluetooth */ { /* MX5000 keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305), HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
{ /* Dinovo Edge keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb309),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
{ /* MX5500 keyboard over Bluetooth */ { /* MX5500 keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
......
...@@ -49,6 +49,36 @@ enum { ...@@ -49,6 +49,36 @@ enum {
MCP2221_ALT_F_NOT_GPIOD = 0xEF, MCP2221_ALT_F_NOT_GPIOD = 0xEF,
}; };
/* MCP GPIO direction encoding */
enum {
MCP2221_DIR_OUT = 0x00,
MCP2221_DIR_IN = 0x01,
};
#define MCP_NGPIO 4
/* MCP GPIO set command layout */
struct mcp_set_gpio {
u8 cmd;
u8 dummy;
struct {
u8 change_value;
u8 value;
u8 change_direction;
u8 direction;
} gpio[MCP_NGPIO];
} __packed;
/* MCP GPIO get command layout */
struct mcp_get_gpio {
u8 cmd;
u8 dummy;
struct {
u8 direction;
u8 value;
} gpio[MCP_NGPIO];
} __packed;
/* /*
* There is no way to distinguish responses. Therefore next command * There is no way to distinguish responses. Therefore next command
* is sent only after response to previous has been received. Mutex * is sent only after response to previous has been received. Mutex
...@@ -542,7 +572,7 @@ static int mcp_gpio_get(struct gpio_chip *gc, ...@@ -542,7 +572,7 @@ static int mcp_gpio_get(struct gpio_chip *gc,
mcp->txbuf[0] = MCP2221_GPIO_GET; mcp->txbuf[0] = MCP2221_GPIO_GET;
mcp->gp_idx = (offset + 1) * 2; mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].value);
mutex_lock(&mcp->lock); mutex_lock(&mcp->lock);
ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
...@@ -559,7 +589,7 @@ static void mcp_gpio_set(struct gpio_chip *gc, ...@@ -559,7 +589,7 @@ static void mcp_gpio_set(struct gpio_chip *gc,
memset(mcp->txbuf, 0, 18); memset(mcp->txbuf, 0, 18);
mcp->txbuf[0] = MCP2221_GPIO_SET; mcp->txbuf[0] = MCP2221_GPIO_SET;
mcp->gp_idx = ((offset + 1) * 4) - 1; mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].value);
mcp->txbuf[mcp->gp_idx - 1] = 1; mcp->txbuf[mcp->gp_idx - 1] = 1;
mcp->txbuf[mcp->gp_idx] = !!value; mcp->txbuf[mcp->gp_idx] = !!value;
...@@ -575,7 +605,7 @@ static int mcp_gpio_dir_set(struct mcp2221 *mcp, ...@@ -575,7 +605,7 @@ static int mcp_gpio_dir_set(struct mcp2221 *mcp,
memset(mcp->txbuf, 0, 18); memset(mcp->txbuf, 0, 18);
mcp->txbuf[0] = MCP2221_GPIO_SET; mcp->txbuf[0] = MCP2221_GPIO_SET;
mcp->gp_idx = (offset + 1) * 5; mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].direction);
mcp->txbuf[mcp->gp_idx - 1] = 1; mcp->txbuf[mcp->gp_idx - 1] = 1;
mcp->txbuf[mcp->gp_idx] = val; mcp->txbuf[mcp->gp_idx] = val;
...@@ -590,7 +620,7 @@ static int mcp_gpio_direction_input(struct gpio_chip *gc, ...@@ -590,7 +620,7 @@ static int mcp_gpio_direction_input(struct gpio_chip *gc,
struct mcp2221 *mcp = gpiochip_get_data(gc); struct mcp2221 *mcp = gpiochip_get_data(gc);
mutex_lock(&mcp->lock); mutex_lock(&mcp->lock);
ret = mcp_gpio_dir_set(mcp, offset, 0); ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_IN);
mutex_unlock(&mcp->lock); mutex_unlock(&mcp->lock);
return ret; return ret;
...@@ -603,7 +633,7 @@ static int mcp_gpio_direction_output(struct gpio_chip *gc, ...@@ -603,7 +633,7 @@ static int mcp_gpio_direction_output(struct gpio_chip *gc,
struct mcp2221 *mcp = gpiochip_get_data(gc); struct mcp2221 *mcp = gpiochip_get_data(gc);
mutex_lock(&mcp->lock); mutex_lock(&mcp->lock);
ret = mcp_gpio_dir_set(mcp, offset, 1); ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_OUT);
mutex_unlock(&mcp->lock); mutex_unlock(&mcp->lock);
/* Can't configure as output, bailout early */ /* Can't configure as output, bailout early */
...@@ -623,7 +653,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc, ...@@ -623,7 +653,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
mcp->txbuf[0] = MCP2221_GPIO_GET; mcp->txbuf[0] = MCP2221_GPIO_GET;
mcp->gp_idx = (offset + 1) * 2; mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].direction);
mutex_lock(&mcp->lock); mutex_lock(&mcp->lock);
ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
...@@ -632,7 +662,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc, ...@@ -632,7 +662,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
if (ret) if (ret)
return ret; return ret;
if (mcp->gpio_dir) if (mcp->gpio_dir == MCP2221_DIR_IN)
return GPIO_LINE_DIRECTION_IN; return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_OUT;
...@@ -758,7 +788,7 @@ static int mcp2221_raw_event(struct hid_device *hdev, ...@@ -758,7 +788,7 @@ static int mcp2221_raw_event(struct hid_device *hdev,
mcp->status = -ENOENT; mcp->status = -ENOENT;
} else { } else {
mcp->status = !!data[mcp->gp_idx]; mcp->status = !!data[mcp->gp_idx];
mcp->gpio_dir = !!data[mcp->gp_idx + 1]; mcp->gpio_dir = data[mcp->gp_idx + 1];
} }
break; break;
default: default:
...@@ -860,7 +890,7 @@ static int mcp2221_probe(struct hid_device *hdev, ...@@ -860,7 +890,7 @@ static int mcp2221_probe(struct hid_device *hdev,
mcp->gc->get_direction = mcp_gpio_get_direction; mcp->gc->get_direction = mcp_gpio_get_direction;
mcp->gc->set = mcp_gpio_set; mcp->gc->set = mcp_gpio_set;
mcp->gc->get = mcp_gpio_get; mcp->gc->get = mcp_gpio_get;
mcp->gc->ngpio = 4; mcp->gc->ngpio = MCP_NGPIO;
mcp->gc->base = -1; mcp->gc->base = -1;
mcp->gc->can_sleep = 1; mcp->gc->can_sleep = 1;
mcp->gc->parent = &hdev->dev; mcp->gc->parent = &hdev->dev;
......
...@@ -83,7 +83,12 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -83,7 +83,12 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186),
HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI),
HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
......
...@@ -483,7 +483,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev, ...@@ -483,7 +483,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
return 1; return 1;
ptr = raw_data; ptr = raw_data;
ptr++; /* Skip report id */ if (report->id)
ptr++; /* Skip report id */
spin_lock_irqsave(&pdata->lock, flags); spin_lock_irqsave(&pdata->lock, flags);
......
...@@ -385,6 +385,8 @@ static const struct hid_device_id uclogic_devices[] = { ...@@ -385,6 +385,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
USB_DEVICE_ID_UGTIZER_TABLET_GT5040) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_TABLET_G5) }, USB_DEVICE_ID_UGEE_TABLET_G5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
......
...@@ -997,6 +997,8 @@ int uclogic_params_init(struct uclogic_params *params, ...@@ -997,6 +997,8 @@ int uclogic_params_init(struct uclogic_params *params,
break; break;
case VID_PID(USB_VENDOR_ID_UGTIZER, case VID_PID(USB_VENDOR_ID_UGTIZER,
USB_DEVICE_ID_UGTIZER_TABLET_GP0610): USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
case VID_PID(USB_VENDOR_ID_UGTIZER,
USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
......
...@@ -943,6 +943,11 @@ static void i2c_hid_acpi_enable_wakeup(struct device *dev) ...@@ -943,6 +943,11 @@ static void i2c_hid_acpi_enable_wakeup(struct device *dev)
} }
} }
static void i2c_hid_acpi_shutdown(struct device *dev)
{
acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D3_COLD);
}
static const struct acpi_device_id i2c_hid_acpi_match[] = { static const struct acpi_device_id i2c_hid_acpi_match[] = {
{"ACPI0C50", 0 }, {"ACPI0C50", 0 },
{"PNP0C50", 0 }, {"PNP0C50", 0 },
...@@ -959,6 +964,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client, ...@@ -959,6 +964,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {} static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {}
static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {} static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {}
static inline void i2c_hid_acpi_shutdown(struct device *dev) {}
#endif #endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -1175,6 +1182,8 @@ static void i2c_hid_shutdown(struct i2c_client *client) ...@@ -1175,6 +1182,8 @@ static void i2c_hid_shutdown(struct i2c_client *client)
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
free_irq(client->irq, ihid); free_irq(client->irq, ihid);
i2c_hid_acpi_shutdown(&client->dev);
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册