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
This commit is contained in:
commit
d5530d82ef
|
@ -23,19 +23,17 @@
|
|||
#define CP_2WHEEL_MOUSE_HACK 0x02
|
||||
#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
|
||||
* 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 long quirks = (unsigned long)hid_get_drvdata(hdev);
|
||||
unsigned int i;
|
||||
|
||||
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
|
||||
return rdesc;
|
||||
|
||||
if (*rsize < 4)
|
||||
return rdesc;
|
||||
|
||||
|
@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *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,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
|
@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = {
|
|||
.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
|
||||
.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);
|
||||
|
|
|
@ -331,6 +331,8 @@
|
|||
#define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81
|
||||
#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_EASYMAXTOUCH 0x1201
|
||||
|
||||
|
@ -443,6 +445,10 @@
|
|||
#define USB_VENDOR_ID_FRUCTEL 0x25B6
|
||||
#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_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
|
||||
#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002
|
||||
|
@ -485,6 +491,7 @@
|
|||
#define USB_DEVICE_ID_PENPOWER 0x00f4
|
||||
|
||||
#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_VENDOR_ID_GRETAGMACBETH 0x0971
|
||||
|
@ -743,6 +750,7 @@
|
|||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
|
||||
#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_C077 0xc077
|
||||
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
|
||||
|
@ -1298,6 +1306,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_UGTIZER 0x2179
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077
|
||||
|
||||
#define USB_VENDOR_ID_VIEWSONIC 0x0543
|
||||
#define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621
|
||||
|
|
|
@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
|
|||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||
USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
|
||||
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 @@
|
|||
|
||||
#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,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
|
@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
|
|||
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[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
|
||||
/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
|
||||
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
|
||||
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. */
|
||||
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
|
||||
USB_VENDOR_ID_SYNAPTICS,
|
||||
|
@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices);
|
|||
static struct hid_driver ite_driver = {
|
||||
.name = "itetech",
|
||||
.id_table = ite_devices,
|
||||
.probe = ite_probe,
|
||||
.report_fixup = ite_report_fixup,
|
||||
.input_mapping = ite_input_mapping,
|
||||
.event = ite_event,
|
||||
};
|
||||
module_hid_driver(ite_driver);
|
||||
|
|
|
@ -328,7 +328,7 @@ static const char mse_bluetooth_descriptor[] = {
|
|||
0x25, 0x01, /* LOGICAL_MAX (1) */
|
||||
0x75, 0x01, /* REPORT_SIZE (1) */
|
||||
0x95, 0x04, /* REPORT_COUNT (4) */
|
||||
0x81, 0x06, /* INPUT */
|
||||
0x81, 0x02, /* INPUT (Data,Var,Abs) */
|
||||
0xC0, /* END_COLLECTION */
|
||||
0xC0, /* END_COLLECTION */
|
||||
};
|
||||
|
@ -866,11 +866,24 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
|
|||
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,
|
||||
struct hidpp_event *hidpp_report,
|
||||
struct dj_workitem *workitem)
|
||||
{
|
||||
struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
|
||||
int i, id;
|
||||
|
||||
workitem->type = WORKITEM_TYPE_PAIRED;
|
||||
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,
|
|||
workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
|
||||
POWER_KEYS | MEDIA_CENTER |
|
||||
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;
|
||||
case REPORT_TYPE_MOUSE:
|
||||
workitem->reports_supported |= STD_MOUSE | HIDPP;
|
||||
|
|
|
@ -93,6 +93,8 @@ MODULE_PARM_DESC(disable_tap_to_click,
|
|||
#define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3)
|
||||
#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
|
||||
* 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,
|
|||
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 */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -3185,6 +3207,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
field->application != HID_GD_MOUSE)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -3947,6 +3972,7 @@ static const struct hid_device_id hidpp_devices[] = {
|
|||
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(0x4072), .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 },
|
||||
|
@ -3971,6 +3997,9 @@ static const struct hid_device_id hidpp_devices[] = {
|
|||
{ /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */
|
||||
LDJ_DEVICE(0xb305),
|
||||
.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) */
|
||||
LDJ_DEVICE(0xb30b),
|
||||
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
|
||||
|
@ -4013,6 +4042,9 @@ static const struct hid_device_id hidpp_devices[] = {
|
|||
{ /* MX5000 keyboard over Bluetooth */
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
|
||||
.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 */
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
|
||||
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
|
||||
|
|
|
@ -49,6 +49,36 @@ enum {
|
|||
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
|
||||
* is sent only after response to previous has been received. Mutex
|
||||
|
@ -542,7 +572,7 @@ static int mcp_gpio_get(struct gpio_chip *gc,
|
|||
|
||||
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);
|
||||
ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
|
||||
|
@ -559,7 +589,7 @@ static void mcp_gpio_set(struct gpio_chip *gc,
|
|||
memset(mcp->txbuf, 0, 18);
|
||||
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] = !!value;
|
||||
|
@ -575,7 +605,7 @@ static int mcp_gpio_dir_set(struct mcp2221 *mcp,
|
|||
memset(mcp->txbuf, 0, 18);
|
||||
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] = val;
|
||||
|
@ -590,7 +620,7 @@ static int mcp_gpio_direction_input(struct gpio_chip *gc,
|
|||
struct mcp2221 *mcp = gpiochip_get_data(gc);
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
|
@ -603,7 +633,7 @@ static int mcp_gpio_direction_output(struct gpio_chip *gc,
|
|||
struct mcp2221 *mcp = gpiochip_get_data(gc);
|
||||
|
||||
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);
|
||||
|
||||
/* Can't configure as output, bailout early */
|
||||
|
@ -623,7 +653,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
|
|||
|
||||
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);
|
||||
ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
|
||||
|
@ -632,7 +662,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mcp->gpio_dir)
|
||||
if (mcp->gpio_dir == MCP2221_DIR_IN)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
@ -758,7 +788,7 @@ static int mcp2221_raw_event(struct hid_device *hdev,
|
|||
mcp->status = -ENOENT;
|
||||
} else {
|
||||
mcp->status = !!data[mcp->gp_idx];
|
||||
mcp->gpio_dir = !!data[mcp->gp_idx + 1];
|
||||
mcp->gpio_dir = data[mcp->gp_idx + 1];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -860,7 +890,7 @@ static int mcp2221_probe(struct hid_device *hdev,
|
|||
mcp->gc->get_direction = mcp_gpio_get_direction;
|
||||
mcp->gc->set = mcp_gpio_set;
|
||||
mcp->gc->get = mcp_gpio_get;
|
||||
mcp->gc->ngpio = 4;
|
||||
mcp->gc->ngpio = MCP_NGPIO;
|
||||
mcp->gc->base = -1;
|
||||
mcp->gc->can_sleep = 1;
|
||||
mcp->gc->parent = &hdev->dev;
|
||||
|
|
|
@ -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_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_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_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_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 },
|
||||
|
|
|
@ -483,7 +483,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
|
|||
return 1;
|
||||
|
||||
ptr = raw_data;
|
||||
ptr++; /* Skip report id */
|
||||
if (report->id)
|
||||
ptr++; /* Skip report id */
|
||||
|
||||
spin_lock_irqsave(&pdata->lock, flags);
|
||||
|
||||
|
|
|
@ -385,6 +385,8 @@ static const struct hid_device_id uclogic_devices[] = {
|
|||
USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
|
||||
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,
|
||||
USB_DEVICE_ID_UGEE_TABLET_G5) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
|
||||
|
|
|
@ -997,6 +997,8 @@ int uclogic_params_init(struct uclogic_params *params,
|
|||
break;
|
||||
case VID_PID(USB_VENDOR_ID_UGTIZER,
|
||||
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,
|
||||
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
|
||||
case VID_PID(USB_VENDOR_ID_UGEE,
|
||||
|
|
|
@ -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[] = {
|
||||
{"ACPI0C50", 0 },
|
||||
{"PNP0C50", 0 },
|
||||
|
@ -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_enable_wakeup(struct device *dev) {}
|
||||
|
||||
static inline void i2c_hid_acpi_shutdown(struct device *dev) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
@ -1175,6 +1182,8 @@ static void i2c_hid_shutdown(struct i2c_client *client)
|
|||
|
||||
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
|
||||
free_irq(client->irq, ihid);
|
||||
|
||||
i2c_hid_acpi_shutdown(&client->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
Loading…
Reference in New Issue