提交 8c4de9bc 编写于 作者: J Jiri Kosina

Merge branches 'for-4.3/chicony', 'for-4.3/cp2112', 'for-4.3/i2c-hid',...

Merge branches 'for-4.3/chicony', 'for-4.3/cp2112', 'for-4.3/i2c-hid', 'for-4.3/lenovo', 'for-4.3/logitech', 'for-4.3/multitouch', 'for-4.3/picolcd', 'for-4.3/rmi', 'for-4.3/sensor-hub', 'for-4.3/sony' and 'for-4.3/wacom' into for-linus
...@@ -77,3 +77,22 @@ Description: ...@@ -77,3 +77,22 @@ Description:
The format is also scrambled, like in the USB mode, and it can The format is also scrambled, like in the USB mode, and it can
be summarized by converting 76543210 into GECA6420. be summarized by converting 76543210 into GECA6420.
HGFEDCBA HFDB7531 HGFEDCBA HFDB7531
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_remote/unpair_remote
Date: July 2015
Contact: linux-input@vger.kernel.org
Description:
Writing the character sequence '*' followed by a newline to
this file will delete all of the current pairings on the
device. Other character sequences are reserved. This file is
write only.
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_remote/<serial_number>/remote_mode
Date: July 2015
Contact: linux-input@vger.kernel.org
Description:
Reading from this file reports the mode status of the
remote as indicated by the LED lights on the device. If no
reports have been received from the paired device, reading
from this file will report '-1'. The mode is read-only
and cannot be set through the driver.
...@@ -486,6 +486,7 @@ config HID_MULTITOUCH ...@@ -486,6 +486,7 @@ config HID_MULTITOUCH
- Atmel panels - Atmel panels
- Cando dual touch panels - Cando dual touch panels
- Chunghwa panels - Chunghwa panels
- CJTouch panels
- CVTouch panels - CVTouch panels
- Cypress TrueTouch panels - Cypress TrueTouch panels
- Elan Microelectronics touch panels - Elan Microelectronics touch panels
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h>
#include "hid-ids.h" #include "hid-ids.h"
...@@ -57,10 +58,34 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -57,10 +58,34 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1; return 1;
} }
static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
/* Change usage maximum and logical maximum from 0x7fff to
* 0x2fff, so they don't exceed HID_MAX_USAGES */
switch (hdev->product) {
case USB_DEVICE_ID_CHICONY_ACER_SWITCH12:
if (*rsize >= 128 && rdesc[64] == 0xff && rdesc[65] == 0x7f
&& rdesc[69] == 0xff && rdesc[70] == 0x7f) {
hid_info(hdev, "Fixing up report descriptor\n");
rdesc[65] = rdesc[70] = 0x2f;
}
break;
}
}
return rdesc;
}
static const struct hid_device_id ch_devices[] = { static const struct hid_device_id ch_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, ch_devices); MODULE_DEVICE_TABLE(hid, ch_devices);
...@@ -68,6 +93,7 @@ MODULE_DEVICE_TABLE(hid, ch_devices); ...@@ -68,6 +93,7 @@ MODULE_DEVICE_TABLE(hid, ch_devices);
static struct hid_driver ch_driver = { static struct hid_driver ch_driver = {
.name = "chicony", .name = "chicony",
.id_table = ch_devices, .id_table = ch_devices,
.report_fixup = ch_switch12_report_fixup,
.input_mapping = ch_input_mapping, .input_mapping = ch_input_mapping,
}; };
module_hid_driver(ch_driver); module_hid_driver(ch_driver);
......
...@@ -1826,6 +1826,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1826,6 +1826,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
......
...@@ -156,6 +156,7 @@ struct cp2112_device { ...@@ -156,6 +156,7 @@ struct cp2112_device {
wait_queue_head_t wait; wait_queue_head_t wait;
u8 read_data[61]; u8 read_data[61];
u8 read_length; u8 read_length;
u8 hwversion;
int xfer_status; int xfer_status;
atomic_t read_avail; atomic_t read_avail;
atomic_t xfer_avail; atomic_t xfer_avail;
...@@ -446,6 +447,24 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data, ...@@ -446,6 +447,24 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
return data_length + 3; return data_length + 3;
} }
static int cp2112_i2c_write_read_req(void *buf, u8 slave_address,
u8 *addr, int addr_length,
int read_length)
{
struct cp2112_write_read_req_report *report = buf;
if (read_length < 1 || read_length > 512 ||
addr_length > sizeof(report->target_address))
return -EINVAL;
report->report = CP2112_DATA_WRITE_READ_REQUEST;
report->slave_address = slave_address << 1;
report->length = cpu_to_be16(read_length);
report->target_address_length = addr_length;
memcpy(report->target_address, addr, addr_length);
return addr_length + 5;
}
static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num) int num)
{ {
...@@ -453,26 +472,46 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -453,26 +472,46 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
struct hid_device *hdev = dev->hdev; struct hid_device *hdev = dev->hdev;
u8 buf[64]; u8 buf[64];
ssize_t count; ssize_t count;
ssize_t read_length = 0;
u8 *read_buf = NULL;
unsigned int retries; unsigned int retries;
int ret; int ret;
hid_dbg(hdev, "I2C %d messages\n", num); hid_dbg(hdev, "I2C %d messages\n", num);
if (num != 1) { if (num == 1) {
if (msgs->flags & I2C_M_RD) {
hid_dbg(hdev, "I2C read %#04x len %d\n",
msgs->addr, msgs->len);
read_length = msgs->len;
read_buf = msgs->buf;
count = cp2112_read_req(buf, msgs->addr, msgs->len);
} else {
hid_dbg(hdev, "I2C write %#04x len %d\n",
msgs->addr, msgs->len);
count = cp2112_i2c_write_req(buf, msgs->addr,
msgs->buf, msgs->len);
}
if (count < 0)
return count;
} else if (dev->hwversion > 1 && /* no repeated start in rev 1 */
num == 2 &&
msgs[0].addr == msgs[1].addr &&
!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n",
msgs[0].addr, msgs[0].len, msgs[1].len);
read_length = msgs[1].len;
read_buf = msgs[1].buf;
count = cp2112_i2c_write_read_req(buf, msgs[0].addr,
msgs[0].buf, msgs[0].len, msgs[1].len);
if (count < 0)
return count;
} else {
hid_err(hdev, hid_err(hdev,
"Multi-message I2C transactions not supported\n"); "Multi-message I2C transactions not supported\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (msgs->flags & I2C_M_RD)
count = cp2112_read_req(buf, msgs->addr, msgs->len);
else
count = cp2112_i2c_write_req(buf, msgs->addr, msgs->buf,
msgs->len);
if (count < 0)
return count;
ret = hid_hw_power(hdev, PM_HINT_FULLON); ret = hid_hw_power(hdev, PM_HINT_FULLON);
if (ret < 0) { if (ret < 0) {
hid_err(hdev, "power management error: %d\n", ret); hid_err(hdev, "power management error: %d\n", ret);
...@@ -508,21 +547,34 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -508,21 +547,34 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
goto power_normal; goto power_normal;
} }
if (!(msgs->flags & I2C_M_RD)) for (count = 0; count < read_length;) {
goto finish; ret = cp2112_read(dev, read_buf + count, read_length - count);
if (ret < 0)
ret = cp2112_read(dev, msgs->buf, msgs->len); goto power_normal;
if (ret < 0) if (ret == 0) {
goto power_normal; hid_err(hdev, "read returned 0\n");
if (ret != msgs->len) { ret = -EIO;
hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len); goto power_normal;
ret = -EIO; }
goto power_normal; count += ret;
if (count > read_length) {
/*
* The hardware returned too much data.
* This is mostly harmless because cp2112_read()
* has a limit check so didn't overrun our
* buffer. Nevertheless, we return an error
* because something is seriously wrong and
* it shouldn't go unnoticed.
*/
hid_err(hdev, "long read: %d > %zd\n",
ret, read_length - count + ret);
ret = -EIO;
goto power_normal;
}
} }
finish:
/* return the number of transferred messages */ /* return the number of transferred messages */
ret = 1; ret = num;
power_normal: power_normal:
hid_hw_power(hdev, PM_HINT_NORMAL); hid_hw_power(hdev, PM_HINT_NORMAL);
...@@ -537,7 +589,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, ...@@ -537,7 +589,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
struct hid_device *hdev = dev->hdev; struct hid_device *hdev = dev->hdev;
u8 buf[64]; u8 buf[64];
__be16 word; __le16 word;
ssize_t count; ssize_t count;
size_t read_length = 0; size_t read_length = 0;
unsigned int retries; unsigned int retries;
...@@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, ...@@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
if (I2C_SMBUS_READ == read_write) if (I2C_SMBUS_READ == read_write)
count = cp2112_read_req(buf, addr, read_length); count = cp2112_read_req(buf, addr, read_length);
else else
count = cp2112_write_req(buf, addr, data->byte, NULL, count = cp2112_write_req(buf, addr, command, NULL,
0); 0);
break; break;
case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_BYTE_DATA:
...@@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, ...@@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
break; break;
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
read_length = 2; read_length = 2;
word = cpu_to_be16(data->word); word = cpu_to_le16(data->word);
if (I2C_SMBUS_READ == read_write) if (I2C_SMBUS_READ == read_write)
count = cp2112_write_read_req(buf, addr, read_length, count = cp2112_write_read_req(buf, addr, read_length,
...@@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, ...@@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
size = I2C_SMBUS_WORD_DATA; size = I2C_SMBUS_WORD_DATA;
read_write = I2C_SMBUS_READ; read_write = I2C_SMBUS_READ;
read_length = 2; read_length = 2;
word = cpu_to_be16(data->word); word = cpu_to_le16(data->word);
count = cp2112_write_read_req(buf, addr, read_length, command, count = cp2112_write_read_req(buf, addr, read_length, command,
(u8 *)&word, 2); (u8 *)&word, 2);
...@@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, ...@@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
data->byte = buf[0]; data->byte = buf[0];
break; break;
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
data->word = be16_to_cpup((__be16 *)buf); data->word = le16_to_cpup((__le16 *)buf);
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
if (read_length > I2C_SMBUS_BLOCK_MAX) { if (read_length > I2C_SMBUS_BLOCK_MAX) {
...@@ -1030,6 +1082,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1030,6 +1082,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
dev->adap.dev.parent = &hdev->dev; dev->adap.dev.parent = &hdev->dev;
snprintf(dev->adap.name, sizeof(dev->adap.name), snprintf(dev->adap.name, sizeof(dev->adap.name),
"CP2112 SMBus Bridge on hiddev%d", hdev->minor); "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
dev->hwversion = buf[2];
init_waitqueue_head(&dev->wait); init_waitqueue_head(&dev->wait);
hid_device_io_start(hdev); hid_device_io_start(hdev);
......
...@@ -233,12 +233,17 @@ ...@@ -233,12 +233,17 @@
#define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053 #define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053
#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 #define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123
#define USB_DEVICE_ID_CHICONY_AK1D 0x1125 #define USB_DEVICE_ID_CHICONY_AK1D 0x1125
#define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
#define USB_VENDOR_ID_CHUNGHWAT 0x2247 #define USB_VENDOR_ID_CHUNGHWAT 0x2247
#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001
#define USB_VENDOR_ID_CIDC 0x1677 #define USB_VENDOR_ID_CIDC 0x1677
#define USB_VENDOR_ID_CJTOUCH 0x24b8
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040 0x0040
#define USB_VENDOR_ID_CMEDIA 0x0d8c #define USB_VENDOR_ID_CMEDIA 0x0d8c
#define USB_DEVICE_ID_CM109 0x000e #define USB_DEVICE_ID_CM109 0x000e
...@@ -503,6 +508,9 @@ ...@@ -503,6 +508,9 @@
#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615
#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070
#define USB_VENDOR_ID_ITE 0x048d
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
#define USB_VENDOR_ID_JABRA 0x0b0e #define USB_VENDOR_ID_JABRA 0x0b0e
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 #define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
#define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420 #define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420
...@@ -605,6 +613,7 @@ ...@@ -605,6 +613,7 @@
#define USB_DEVICE_ID_LOGITECH_DUAL_ACTION 0xc216 #define USB_DEVICE_ID_LOGITECH_DUAL_ACTION 0xc216
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
#define USB_DEVICE_ID_LOGITECH_G29_WHEEL 0xc24f
#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287
......
...@@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd { ...@@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd {
}; };
struct lenovo_drvdata_cptkbd { struct lenovo_drvdata_cptkbd {
u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
bool fn_lock; bool fn_lock;
int sensitivity; int sensitivity;
}; };
...@@ -146,10 +147,10 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, ...@@ -146,10 +147,10 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
switch (usage->hid & HID_USAGE) { switch (usage->hid & HID_USAGE) {
case 0x0000: case 0x0000:
hid_map_usage(hi, usage, bit, max, EV_REL, 0x06); hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
return 1; return 1;
case 0x0001: case 0x0001:
hid_map_usage(hi, usage, bit, max, EV_REL, 0x08); hid_map_usage(hi, usage, bit, max, EV_REL, REL_WHEEL);
return 1; return 1;
default: default:
return -1; return -1;
...@@ -207,9 +208,12 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev) ...@@ -207,9 +208,12 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock); ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity);
if (ret) if (ret)
hid_err(hdev, "Fn-lock setting failed: %d\n", ret); hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity);
if (ret)
hid_err(hdev, "Sensitivity setting failed: %d\n", ret);
} }
static ssize_t attr_fn_lock_show_cptkbd(struct device *dev, static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
...@@ -313,6 +317,53 @@ static int lenovo_raw_event(struct hid_device *hdev, ...@@ -313,6 +317,53 @@ static int lenovo_raw_event(struct hid_device *hdev,
return 0; return 0;
} }
static int lenovo_event_cptkbd(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage, __s32 value)
{
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
/* "wheel" scroll events */
if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
usage->code == REL_HWHEEL)) {
/* Scroll events disable middle-click event */
cptkbd_data->middlebutton_state = 2;
return 0;
}
/* Middle click events */
if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
if (value == 1) {
cptkbd_data->middlebutton_state = 1;
} else if (value == 0) {
if (cptkbd_data->middlebutton_state == 1) {
/* No scrolling inbetween, send middle-click */
input_event(field->hidinput->input,
EV_KEY, BTN_MIDDLE, 1);
input_sync(field->hidinput->input);
input_event(field->hidinput->input,
EV_KEY, BTN_MIDDLE, 0);
input_sync(field->hidinput->input);
}
cptkbd_data->middlebutton_state = 0;
}
return 1;
}
return 0;
}
static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
switch (hdev->product) {
case USB_DEVICE_ID_LENOVO_CUSBKBD:
case USB_DEVICE_ID_LENOVO_CBTKBD:
return lenovo_event_cptkbd(hdev, field, usage, value);
default:
return 0;
}
}
static int lenovo_features_set_tpkbd(struct hid_device *hdev) static int lenovo_features_set_tpkbd(struct hid_device *hdev)
{ {
struct hid_report *report; struct hid_report *report;
...@@ -705,6 +756,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev) ...@@ -705,6 +756,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
hid_warn(hdev, "Failed to switch middle button: %d\n", ret); hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
/* Set keyboard settings to known state */ /* Set keyboard settings to known state */
cptkbd_data->middlebutton_state = 0;
cptkbd_data->fn_lock = true; cptkbd_data->fn_lock = true;
cptkbd_data->sensitivity = 0x05; cptkbd_data->sensitivity = 0x05;
lenovo_features_set_cptkbd(hdev); lenovo_features_set_cptkbd(hdev);
...@@ -832,6 +884,7 @@ static struct hid_driver lenovo_driver = { ...@@ -832,6 +884,7 @@ static struct hid_driver lenovo_driver = {
.probe = lenovo_probe, .probe = lenovo_probe,
.remove = lenovo_remove, .remove = lenovo_remove,
.raw_event = lenovo_raw_event, .raw_event = lenovo_raw_event,
.event = lenovo_event,
.report_fixup = lenovo_report_fixup, .report_fixup = lenovo_report_fixup,
}; };
module_hid_driver(lenovo_driver); module_hid_driver(lenovo_driver);
......
...@@ -776,6 +776,8 @@ static const struct hid_device_id lg_devices[] = { ...@@ -776,6 +776,8 @@ static const struct hid_device_id lg_devices[] = {
.driver_data = LG_FF }, .driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
.driver_data = LG_FF }, .driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL),
.driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
.driver_data = LG_FF }, .driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
......
...@@ -1145,6 +1145,14 @@ static const struct hid_device_id mt_devices[] = { ...@@ -1145,6 +1145,14 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
/* CJTouch panels */
{ .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
{ .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
/* CVTouch panels */ /* CVTouch panels */
{ .driver_data = MT_CLS_NSMU, { .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
......
...@@ -94,8 +94,7 @@ void picolcd_exit_backlight(struct picolcd_data *data) ...@@ -94,8 +94,7 @@ void picolcd_exit_backlight(struct picolcd_data *data)
struct backlight_device *bdev = data->backlight; struct backlight_device *bdev = data->backlight;
data->backlight = NULL; data->backlight = NULL;
if (bdev) backlight_device_unregister(bdev);
backlight_device_unregister(bdev);
} }
int picolcd_resume_backlight(struct picolcd_data *data) int picolcd_resume_backlight(struct picolcd_data *data)
......
...@@ -145,7 +145,6 @@ void picolcd_exit_cir(struct picolcd_data *data) ...@@ -145,7 +145,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
struct rc_dev *rdev = data->rc_dev; struct rc_dev *rdev = data->rc_dev;
data->rc_dev = NULL; data->rc_dev = NULL;
if (rdev) rc_unregister_device(rdev);
rc_unregister_device(rdev);
} }
...@@ -92,8 +92,7 @@ void picolcd_exit_lcd(struct picolcd_data *data) ...@@ -92,8 +92,7 @@ void picolcd_exit_lcd(struct picolcd_data *data)
struct lcd_device *ldev = data->lcd; struct lcd_device *ldev = data->lcd;
data->lcd = NULL; data->lcd = NULL;
if (ldev) lcd_device_unregister(ldev);
lcd_device_unregister(ldev);
} }
int picolcd_resume_lcd(struct picolcd_data *data) int picolcd_resume_lcd(struct picolcd_data *data)
......
...@@ -33,10 +33,21 @@ ...@@ -33,10 +33,21 @@
#define RMI_READ_DATA_PENDING 1 #define RMI_READ_DATA_PENDING 1
#define RMI_STARTED 2 #define RMI_STARTED 2
#define RMI_SLEEP_NORMAL 0x0
#define RMI_SLEEP_DEEP_SLEEP 0x1
/* device flags */ /* device flags */
#define RMI_DEVICE BIT(0) #define RMI_DEVICE BIT(0)
#define RMI_DEVICE_HAS_PHYS_BUTTONS BIT(1) #define RMI_DEVICE_HAS_PHYS_BUTTONS BIT(1)
/*
* retrieve the ctrl registers
* the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
* and there is no way to know if the first 20 bytes are here or not.
* We use only the first 12 bytes, so get only them.
*/
#define RMI_F11_CTRL_REG_COUNT 12
enum rmi_mode_type { enum rmi_mode_type {
RMI_MODE_OFF = 0, RMI_MODE_OFF = 0,
RMI_MODE_ATTN_REPORTS = 1, RMI_MODE_ATTN_REPORTS = 1,
...@@ -113,6 +124,8 @@ struct rmi_data { ...@@ -113,6 +124,8 @@ struct rmi_data {
unsigned int max_y; unsigned int max_y;
unsigned int x_size_mm; unsigned int x_size_mm;
unsigned int y_size_mm; unsigned int y_size_mm;
bool read_f11_ctrl_regs;
u8 f11_ctrl_regs[RMI_F11_CTRL_REG_COUNT];
unsigned int gpio_led_count; unsigned int gpio_led_count;
unsigned int button_count; unsigned int button_count;
...@@ -126,6 +139,10 @@ struct rmi_data { ...@@ -126,6 +139,10 @@ struct rmi_data {
unsigned long device_flags; unsigned long device_flags;
unsigned long firmware_id; unsigned long firmware_id;
u8 f01_ctrl0;
u8 interrupt_enable_mask;
bool restore_interrupt_mask;
}; };
#define RMI_PAGE(addr) (((addr) >> 8) & 0xff) #define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
...@@ -346,13 +363,34 @@ static void rmi_f11_process_touch(struct rmi_data *hdata, int slot, ...@@ -346,13 +363,34 @@ static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
} }
} }
static int rmi_reset_attn_mode(struct hid_device *hdev)
{
struct rmi_data *data = hid_get_drvdata(hdev);
int ret;
ret = rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
if (ret)
return ret;
if (data->restore_interrupt_mask) {
ret = rmi_write(hdev, data->f01.control_base_addr + 1,
&data->interrupt_enable_mask);
if (ret) {
hid_err(hdev, "can not write F01 control register\n");
return ret;
}
}
return 0;
}
static void rmi_reset_work(struct work_struct *work) static void rmi_reset_work(struct work_struct *work)
{ {
struct rmi_data *hdata = container_of(work, struct rmi_data, struct rmi_data *hdata = container_of(work, struct rmi_data,
reset_work); reset_work);
/* switch the device to RMI if we receive a generic mouse report */ /* switch the device to RMI if we receive a generic mouse report */
rmi_set_mode(hdata->hdev, RMI_MODE_ATTN_REPORTS); rmi_reset_attn_mode(hdata->hdev);
} }
static inline int rmi_schedule_reset(struct hid_device *hdev) static inline int rmi_schedule_reset(struct hid_device *hdev)
...@@ -532,14 +570,77 @@ static int rmi_event(struct hid_device *hdev, struct hid_field *field, ...@@ -532,14 +570,77 @@ static int rmi_event(struct hid_device *hdev, struct hid_field *field,
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int rmi_set_sleep_mode(struct hid_device *hdev, int sleep_mode)
{
struct rmi_data *data = hid_get_drvdata(hdev);
int ret;
u8 f01_ctrl0;
f01_ctrl0 = (data->f01_ctrl0 & ~0x3) | sleep_mode;
ret = rmi_write(hdev, data->f01.control_base_addr,
&f01_ctrl0);
if (ret) {
hid_err(hdev, "can not write sleep mode\n");
return ret;
}
return 0;
}
static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
{
struct rmi_data *data = hid_get_drvdata(hdev);
int ret;
u8 buf[RMI_F11_CTRL_REG_COUNT];
ret = rmi_read_block(hdev, data->f11.control_base_addr, buf,
RMI_F11_CTRL_REG_COUNT);
if (ret)
hid_warn(hdev, "can not read F11 control registers\n");
else
memcpy(data->f11_ctrl_regs, buf, RMI_F11_CTRL_REG_COUNT);
if (!device_may_wakeup(hdev->dev.parent))
return rmi_set_sleep_mode(hdev, RMI_SLEEP_DEEP_SLEEP);
return 0;
}
static int rmi_post_reset(struct hid_device *hdev) static int rmi_post_reset(struct hid_device *hdev)
{ {
return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS); struct rmi_data *data = hid_get_drvdata(hdev);
int ret;
ret = rmi_reset_attn_mode(hdev);
if (ret) {
hid_err(hdev, "can not set rmi mode\n");
return ret;
}
if (data->read_f11_ctrl_regs) {
ret = rmi_write_block(hdev, data->f11.control_base_addr,
data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
if (ret)
hid_warn(hdev,
"can not write F11 control registers after reset\n");
}
if (!device_may_wakeup(hdev->dev.parent)) {
ret = rmi_set_sleep_mode(hdev, RMI_SLEEP_NORMAL);
if (ret) {
hid_err(hdev, "can not write sleep mode\n");
return ret;
}
}
return ret;
} }
static int rmi_post_resume(struct hid_device *hdev) static int rmi_post_resume(struct hid_device *hdev)
{ {
return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS); return rmi_reset_attn_mode(hdev);
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
...@@ -595,6 +696,7 @@ static void rmi_register_function(struct rmi_data *data, ...@@ -595,6 +696,7 @@ static void rmi_register_function(struct rmi_data *data,
f->interrupt_count = pdt_entry->interrupt_source_count; f->interrupt_count = pdt_entry->interrupt_source_count;
f->irq_mask = rmi_gen_mask(f->interrupt_base, f->irq_mask = rmi_gen_mask(f->interrupt_base,
f->interrupt_count); f->interrupt_count);
data->interrupt_enable_mask |= f->irq_mask;
} }
} }
...@@ -732,6 +834,35 @@ static int rmi_populate_f01(struct hid_device *hdev) ...@@ -732,6 +834,35 @@ static int rmi_populate_f01(struct hid_device *hdev)
data->firmware_id += info[2] * 65536; data->firmware_id += info[2] * 65536;
} }
ret = rmi_read_block(hdev, data->f01.control_base_addr, info,
2);
if (ret) {
hid_err(hdev, "can not read f01 ctrl registers\n");
return ret;
}
data->f01_ctrl0 = info[0];
if (!info[1]) {
/*
* Do to a firmware bug in some touchpads the F01 interrupt
* enable control register will be cleared on reset.
* This will stop the touchpad from reporting data, so
* if F01 CTRL1 is 0 then we need to explicitly enable
* interrupts for the functions we want data for.
*/
data->restore_interrupt_mask = true;
ret = rmi_write(hdev, data->f01.control_base_addr + 1,
&data->interrupt_enable_mask);
if (ret) {
hid_err(hdev, "can not write to control reg 1: %d.\n",
ret);
return ret;
}
}
return 0; return 0;
} }
...@@ -904,24 +1035,23 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -904,24 +1035,23 @@ static int rmi_populate_f11(struct hid_device *hdev)
if (has_data40) if (has_data40)
data->f11.report_size += data->max_fingers * 2; data->f11.report_size += data->max_fingers * 2;
/* ret = rmi_read_block(hdev, data->f11.control_base_addr,
* retrieve the ctrl registers data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
* the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
* and there is no way to know if the first 20 bytes are here or not.
* We use only the first 12 bytes, so get only them.
*/
ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 12);
if (ret) { if (ret) {
hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret); hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret);
return ret; return ret;
} }
data->max_x = buf[6] | (buf[7] << 8); /* data->f11_ctrl_regs now contains valid register data */
data->max_y = buf[8] | (buf[9] << 8); data->read_f11_ctrl_regs = true;
data->max_x = data->f11_ctrl_regs[6] | (data->f11_ctrl_regs[7] << 8);
data->max_y = data->f11_ctrl_regs[8] | (data->f11_ctrl_regs[9] << 8);
if (has_dribble) { if (has_dribble) {
buf[0] = buf[0] & ~BIT(6); data->f11_ctrl_regs[0] = data->f11_ctrl_regs[0] & ~BIT(6);
ret = rmi_write(hdev, data->f11.control_base_addr, buf); ret = rmi_write(hdev, data->f11.control_base_addr,
data->f11_ctrl_regs);
if (ret) { if (ret) {
hid_err(hdev, "can not write to control reg 0: %d.\n", hid_err(hdev, "can not write to control reg 0: %d.\n",
ret); ret);
...@@ -930,9 +1060,9 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -930,9 +1060,9 @@ static int rmi_populate_f11(struct hid_device *hdev)
} }
if (has_palm_detect) { if (has_palm_detect) {
buf[11] = buf[11] & ~BIT(0); data->f11_ctrl_regs[11] = data->f11_ctrl_regs[11] & ~BIT(0);
ret = rmi_write(hdev, data->f11.control_base_addr + 11, ret = rmi_write(hdev, data->f11.control_base_addr + 11,
&buf[11]); &data->f11_ctrl_regs[11]);
if (ret) { if (ret) {
hid_err(hdev, "can not write to control reg 11: %d.\n", hid_err(hdev, "can not write to control reg 11: %d.\n",
ret); ret);
...@@ -1273,6 +1403,7 @@ static struct hid_driver rmi_driver = { ...@@ -1273,6 +1403,7 @@ static struct hid_driver rmi_driver = {
.input_mapping = rmi_input_mapping, .input_mapping = rmi_input_mapping,
.input_configured = rmi_input_configured, .input_configured = rmi_input_configured,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = rmi_suspend,
.resume = rmi_post_resume, .resume = rmi_post_resume,
.reset_resume = rmi_post_reset, .reset_resume = rmi_post_reset,
#endif #endif
......
...@@ -774,6 +774,9 @@ static const struct hid_device_id sensor_hub_devices[] = { ...@@ -774,6 +774,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS,
USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA), USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
USB_DEVICE_ID_ITE_LENOVO_YOGA),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
HID_ANY_ID) }, HID_ANY_ID) },
{ } { }
......
...@@ -296,7 +296,14 @@ static __u8 navigation_rdesc[] = { ...@@ -296,7 +296,14 @@ static __u8 navigation_rdesc[] = {
0x09, 0x01, /* Usage (Pointer), */ 0x09, 0x01, /* Usage (Pointer), */
0x81, 0x02, /* Input (Variable), */ 0x81, 0x02, /* Input (Variable), */
0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
0x95, 0x20, /* Report Count (26), */ 0x95, 0x01, /* Report Count (1), */
0x81, 0x02, /* Input (Variable), */
0x05, 0x01, /* Usage Page (Desktop), */
0x95, 0x01, /* Report Count (1), */
0x09, 0x01, /* Usage (Pointer), */
0x81, 0x02, /* Input (Variable), */
0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
0x95, 0x1E, /* Report Count (24), */
0x81, 0x02, /* Input (Variable), */ 0x81, 0x02, /* Input (Variable), */
0x75, 0x08, /* Report Size (8), */ 0x75, 0x08, /* Report Size (8), */
0x95, 0x30, /* Report Count (48), */ 0x95, 0x30, /* Report Count (48), */
...@@ -1270,6 +1277,17 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, ...@@ -1270,6 +1277,17 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
* has to be BYTE_SWAPPED before passing up to joystick interface * has to be BYTE_SWAPPED before passing up to joystick interface
*/ */
if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
/*
* When connected via Bluetooth the Sixaxis occasionally sends
* a report with the second byte 0xff and the rest zeroed.
*
* This report does not reflect the actual state of the
* controller must be ignored to avoid generating false input
* events.
*/
if (rd[1] == 0xff)
return -EINVAL;
swap(rd[41], rd[42]); swap(rd[41], rd[42]);
swap(rd[43], rd[44]); swap(rd[43], rd[44]);
swap(rd[45], rd[46]); swap(rd[45], rd[46]);
...@@ -1836,7 +1854,7 @@ static void dualshock4_state_worker(struct work_struct *work) ...@@ -1836,7 +1854,7 @@ static void dualshock4_state_worker(struct work_struct *work)
} else { } else {
memset(buf, 0, DS4_REPORT_0x11_SIZE); memset(buf, 0, DS4_REPORT_0x11_SIZE);
buf[0] = 0x11; buf[0] = 0x11;
buf[1] = 0xB0; buf[1] = 0x80;
buf[3] = 0x0F; buf[3] = 0x0F;
offset = 6; offset = 6;
} }
......
...@@ -149,6 +149,8 @@ struct i2c_hid { ...@@ -149,6 +149,8 @@ struct i2c_hid {
int irq; int irq;
struct i2c_hid_platform_data pdata; struct i2c_hid_platform_data pdata;
bool irq_wake_enabled;
}; };
static int __i2c_hid_command(struct i2c_client *client, static int __i2c_hid_command(struct i2c_client *client,
...@@ -1091,14 +1093,21 @@ static int i2c_hid_suspend(struct device *dev) ...@@ -1091,14 +1093,21 @@ static int i2c_hid_suspend(struct device *dev)
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
struct hid_device *hid = ihid->hid; struct hid_device *hid = ihid->hid;
int ret = 0; int ret = 0;
int wake_status;
disable_irq(ihid->irq);
if (device_may_wakeup(&client->dev))
enable_irq_wake(ihid->irq);
if (hid->driver && hid->driver->suspend) if (hid->driver && hid->driver->suspend)
ret = hid->driver->suspend(hid, PMSG_SUSPEND); ret = hid->driver->suspend(hid, PMSG_SUSPEND);
disable_irq(ihid->irq);
if (device_may_wakeup(&client->dev)) {
wake_status = enable_irq_wake(ihid->irq);
if (!wake_status)
ihid->irq_wake_enabled = true;
else
hid_warn(hid, "Failed to enable irq wake: %d\n",
wake_status);
}
/* Save some power */ /* Save some power */
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
...@@ -1111,14 +1120,21 @@ static int i2c_hid_resume(struct device *dev) ...@@ -1111,14 +1120,21 @@ static int i2c_hid_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
struct hid_device *hid = ihid->hid; struct hid_device *hid = ihid->hid;
int wake_status;
enable_irq(ihid->irq); enable_irq(ihid->irq);
ret = i2c_hid_hwreset(client); ret = i2c_hid_hwreset(client);
if (ret) if (ret)
return ret; return ret;
if (device_may_wakeup(&client->dev)) if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) {
disable_irq_wake(ihid->irq); wake_status = disable_irq_wake(ihid->irq);
if (!wake_status)
ihid->irq_wake_enabled = false;
else
hid_warn(hid, "Failed to disable irq wake: %d\n",
wake_status);
}
if (hid->driver && hid->driver->reset_resume) { if (hid->driver && hid->driver->reset_resume) {
ret = hid->driver->reset_resume(hid); ret = hid->driver->reset_resume(hid);
......
...@@ -113,7 +113,7 @@ struct wacom { ...@@ -113,7 +113,7 @@ struct wacom {
struct mutex lock; struct mutex lock;
struct work_struct work; struct work_struct work;
struct wacom_led { struct wacom_led {
u8 select[2]; /* status led selector (0..3) */ u8 select[5]; /* status led selector (0..3) */
u8 llv; /* status led brightness no button (1..127) */ u8 llv; /* status led brightness no button (1..127) */
u8 hlv; /* status led brightness button pressed (1..127) */ u8 hlv; /* status led brightness button pressed (1..127) */
u8 img_lum; /* OLED matrix display brightness */ u8 img_lum; /* OLED matrix display brightness */
...@@ -123,6 +123,8 @@ struct wacom { ...@@ -123,6 +123,8 @@ struct wacom {
struct power_supply *ac; struct power_supply *ac;
struct power_supply_desc battery_desc; struct power_supply_desc battery_desc;
struct power_supply_desc ac_desc; struct power_supply_desc ac_desc;
struct kobject *remote_dir;
struct attribute_group remote_group[5];
}; };
static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
...@@ -147,4 +149,7 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field, ...@@ -147,4 +149,7 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value); struct hid_usage *usage, __s32 value);
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report); void wacom_wac_report(struct hid_device *hdev, struct hid_report *report);
void wacom_battery_work(struct work_struct *work); void wacom_battery_work(struct work_struct *work);
int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial,
int index);
void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial);
#endif #endif
...@@ -23,9 +23,13 @@ ...@@ -23,9 +23,13 @@
#define WAC_CMD_ICON_XFER 0x23 #define WAC_CMD_ICON_XFER 0x23
#define WAC_CMD_ICON_BT_XFER 0x26 #define WAC_CMD_ICON_BT_XFER 0x26
#define WAC_CMD_RETRIES 10 #define WAC_CMD_RETRIES 10
#define WAC_CMD_DELETE_PAIRING 0x20
#define WAC_CMD_UNPAIR_ALL 0xFF
#define WAC_REMOTE_SERIAL_MAX_STRLEN 9
#define DEV_ATTR_RW_PERM (S_IRUGO | S_IWUSR | S_IWGRP) #define DEV_ATTR_RW_PERM (S_IRUGO | S_IWUSR | S_IWGRP)
#define DEV_ATTR_WO_PERM (S_IWUSR | S_IWGRP) #define DEV_ATTR_WO_PERM (S_IWUSR | S_IWGRP)
#define DEV_ATTR_RO_PERM (S_IRUSR | S_IRGRP)
static int wacom_get_report(struct hid_device *hdev, u8 type, u8 *buf, static int wacom_get_report(struct hid_device *hdev, u8 type, u8 *buf,
size_t size, unsigned int retries) size_t size, unsigned int retries)
...@@ -453,12 +457,11 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, ...@@ -453,12 +457,11 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
* interface number. * interface number.
*/ */
if (features->type == WIRELESS) { if (features->type == WIRELESS) {
if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { if (intf->cur_altsetting->desc.bInterfaceNumber == 0)
features->device_type = WACOM_DEVICETYPE_WL_MONITOR;
else
features->device_type = WACOM_DEVICETYPE_NONE; features->device_type = WACOM_DEVICETYPE_NONE;
} else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) { return;
features->device_type |= WACOM_DEVICETYPE_TOUCH;
features->pktlen = WACOM_PKGLEN_BBTOUCH3;
}
} }
wacom_parse_hid(hdev, features); wacom_parse_hid(hdev, features);
...@@ -1120,6 +1123,189 @@ static ssize_t wacom_store_speed(struct device *dev, ...@@ -1120,6 +1123,189 @@ static ssize_t wacom_store_speed(struct device *dev,
static DEVICE_ATTR(speed, DEV_ATTR_RW_PERM, static DEVICE_ATTR(speed, DEV_ATTR_RW_PERM,
wacom_show_speed, wacom_store_speed); wacom_show_speed, wacom_store_speed);
static ssize_t wacom_show_remote_mode(struct kobject *kobj,
struct kobj_attribute *kattr,
char *buf, int index)
{
struct device *dev = container_of(kobj->parent, struct device, kobj);
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct wacom *wacom = hid_get_drvdata(hdev);
u8 mode;
mode = wacom->led.select[index];
if (mode >= 0 && mode < 3)
return snprintf(buf, PAGE_SIZE, "%d\n", mode);
else
return snprintf(buf, PAGE_SIZE, "%d\n", -1);
}
#define DEVICE_EKR_ATTR_GROUP(SET_ID) \
static ssize_t wacom_show_remote##SET_ID##_mode(struct kobject *kobj, \
struct kobj_attribute *kattr, char *buf) \
{ \
return wacom_show_remote_mode(kobj, kattr, buf, SET_ID); \
} \
static struct kobj_attribute remote##SET_ID##_mode_attr = { \
.attr = {.name = "remote_mode", \
.mode = DEV_ATTR_RO_PERM}, \
.show = wacom_show_remote##SET_ID##_mode, \
}; \
static struct attribute *remote##SET_ID##_serial_attrs[] = { \
&remote##SET_ID##_mode_attr.attr, \
NULL \
}; \
static struct attribute_group remote##SET_ID##_serial_group = { \
.name = NULL, \
.attrs = remote##SET_ID##_serial_attrs, \
}
DEVICE_EKR_ATTR_GROUP(0);
DEVICE_EKR_ATTR_GROUP(1);
DEVICE_EKR_ATTR_GROUP(2);
DEVICE_EKR_ATTR_GROUP(3);
DEVICE_EKR_ATTR_GROUP(4);
int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int index)
{
int error = 0;
char *buf;
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
wacom_wac->serial[index] = serial;
buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL);
if (!buf)
return -ENOMEM;
snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial);
wacom->remote_group[index].name = buf;
error = sysfs_create_group(wacom->remote_dir,
&wacom->remote_group[index]);
if (error) {
hid_err(wacom->hdev,
"cannot create sysfs group err: %d\n", error);
kobject_put(wacom->remote_dir);
return error;
}
return 0;
}
void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial)
{
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
int i;
if (!serial)
return;
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
if (wacom_wac->serial[i] == serial) {
wacom_wac->serial[i] = 0;
wacom->led.select[i] = WACOM_STATUS_UNKNOWN;
if (wacom->remote_group[i].name) {
sysfs_remove_group(wacom->remote_dir,
&wacom->remote_group[i]);
kfree(wacom->remote_group[i].name);
wacom->remote_group[i].name = NULL;
}
}
}
}
static int wacom_cmd_unpair_remote(struct wacom *wacom, unsigned char selector)
{
const size_t buf_size = 2;
unsigned char *buf;
int retval;
buf = kzalloc(buf_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf[0] = WAC_CMD_DELETE_PAIRING;
buf[1] = selector;
retval = wacom_set_report(wacom->hdev, HID_OUTPUT_REPORT, buf,
buf_size, WAC_CMD_RETRIES);
kfree(buf);
return retval;
}
static ssize_t wacom_store_unpair_remote(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
unsigned char selector = 0;
struct device *dev = container_of(kobj->parent, struct device, kobj);
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct wacom *wacom = hid_get_drvdata(hdev);
int err;
if (!strncmp(buf, "*\n", 2)) {
selector = WAC_CMD_UNPAIR_ALL;
} else {
hid_info(wacom->hdev, "remote: unrecognized unpair code: %s\n",
buf);
return -1;
}
mutex_lock(&wacom->lock);
err = wacom_cmd_unpair_remote(wacom, selector);
mutex_unlock(&wacom->lock);
return err < 0 ? err : count;
}
static struct kobj_attribute unpair_remote_attr = {
.attr = {.name = "unpair_remote", .mode = 0200},
.store = wacom_store_unpair_remote,
};
static const struct attribute *remote_unpair_attrs[] = {
&unpair_remote_attr.attr,
NULL
};
static int wacom_initialize_remote(struct wacom *wacom)
{
int error = 0;
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
int i;
if (wacom->wacom_wac.features.type != REMOTE)
return 0;
wacom->remote_group[0] = remote0_serial_group;
wacom->remote_group[1] = remote1_serial_group;
wacom->remote_group[2] = remote2_serial_group;
wacom->remote_group[3] = remote3_serial_group;
wacom->remote_group[4] = remote4_serial_group;
wacom->remote_dir = kobject_create_and_add("wacom_remote",
&wacom->hdev->dev.kobj);
if (!wacom->remote_dir)
return -ENOMEM;
error = sysfs_create_files(wacom->remote_dir, remote_unpair_attrs);
if (error) {
hid_err(wacom->hdev,
"cannot create sysfs group err: %d\n", error);
return error;
}
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
wacom->led.select[i] = WACOM_STATUS_UNKNOWN;
wacom_wac->serial[i] = 0;
}
return 0;
}
static struct input_dev *wacom_allocate_input(struct wacom *wacom) static struct input_dev *wacom_allocate_input(struct wacom *wacom)
{ {
struct input_dev *input_dev; struct input_dev *input_dev;
...@@ -1130,7 +1316,7 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom) ...@@ -1130,7 +1316,7 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
if (!input_dev) if (!input_dev)
return NULL; return NULL;
input_dev->name = wacom_wac->pen_name; input_dev->name = wacom_wac->features.name;
input_dev->phys = hdev->phys; input_dev->phys = hdev->phys;
input_dev->dev.parent = &hdev->dev; input_dev->dev.parent = &hdev->dev;
input_dev->open = wacom_open; input_dev->open = wacom_open;
...@@ -1145,40 +1331,6 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom) ...@@ -1145,40 +1331,6 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
return input_dev; return input_dev;
} }
static void wacom_free_inputs(struct wacom *wacom)
{
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
input_free_device(wacom_wac->pen_input);
input_free_device(wacom_wac->touch_input);
input_free_device(wacom_wac->pad_input);
wacom_wac->pen_input = NULL;
wacom_wac->touch_input = NULL;
wacom_wac->pad_input = NULL;
}
static int wacom_allocate_inputs(struct wacom *wacom)
{
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
pen_input_dev = wacom_allocate_input(wacom);
touch_input_dev = wacom_allocate_input(wacom);
pad_input_dev = wacom_allocate_input(wacom);
if (!pen_input_dev || !touch_input_dev || !pad_input_dev) {
wacom_free_inputs(wacom);
return -ENOMEM;
}
wacom_wac->pen_input = pen_input_dev;
wacom_wac->touch_input = touch_input_dev;
wacom_wac->touch_input->name = wacom_wac->touch_name;
wacom_wac->pad_input = pad_input_dev;
wacom_wac->pad_input->name = wacom_wac->pad_name;
return 0;
}
static void wacom_clean_inputs(struct wacom *wacom) static void wacom_clean_inputs(struct wacom *wacom)
{ {
if (wacom->wacom_wac.pen_input) { if (wacom->wacom_wac.pen_input) {
...@@ -1199,12 +1351,33 @@ static void wacom_clean_inputs(struct wacom *wacom) ...@@ -1199,12 +1351,33 @@ static void wacom_clean_inputs(struct wacom *wacom)
else else
input_free_device(wacom->wacom_wac.pad_input); input_free_device(wacom->wacom_wac.pad_input);
} }
if (wacom->remote_dir)
kobject_put(wacom->remote_dir);
wacom->wacom_wac.pen_input = NULL; wacom->wacom_wac.pen_input = NULL;
wacom->wacom_wac.touch_input = NULL; wacom->wacom_wac.touch_input = NULL;
wacom->wacom_wac.pad_input = NULL; wacom->wacom_wac.pad_input = NULL;
wacom_destroy_leds(wacom); wacom_destroy_leds(wacom);
} }
static int wacom_allocate_inputs(struct wacom *wacom)
{
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
wacom_wac->pen_input = wacom_allocate_input(wacom);
wacom_wac->touch_input = wacom_allocate_input(wacom);
wacom_wac->pad_input = wacom_allocate_input(wacom);
if (!wacom_wac->pen_input || !wacom_wac->touch_input || !wacom_wac->pad_input) {
wacom_clean_inputs(wacom);
return -ENOMEM;
}
wacom_wac->pen_input->name = wacom_wac->pen_name;
wacom_wac->touch_input->name = wacom_wac->touch_name;
wacom_wac->pad_input->name = wacom_wac->pad_name;
return 0;
}
static int wacom_register_inputs(struct wacom *wacom) static int wacom_register_inputs(struct wacom *wacom)
{ {
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev; struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
...@@ -1259,10 +1432,16 @@ static int wacom_register_inputs(struct wacom *wacom) ...@@ -1259,10 +1432,16 @@ static int wacom_register_inputs(struct wacom *wacom)
error = wacom_initialize_leds(wacom); error = wacom_initialize_leds(wacom);
if (error) if (error)
goto fail_leds; goto fail_leds;
error = wacom_initialize_remote(wacom);
if (error)
goto fail_remote;
} }
return 0; return 0;
fail_remote:
wacom_destroy_leds(wacom);
fail_leds: fail_leds:
input_unregister_device(pad_input_dev); input_unregister_device(pad_input_dev);
pad_input_dev = NULL; pad_input_dev = NULL;
...@@ -1553,11 +1732,9 @@ static int wacom_probe(struct hid_device *hdev, ...@@ -1553,11 +1732,9 @@ static int wacom_probe(struct hid_device *hdev,
mutex_init(&wacom->lock); mutex_init(&wacom->lock);
INIT_WORK(&wacom->work, wacom_wireless_work); INIT_WORK(&wacom->work, wacom_wireless_work);
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { error = wacom_allocate_inputs(wacom);
error = wacom_allocate_inputs(wacom); if (error)
if (error) goto fail_allocate_inputs;
goto fail_allocate_inputs;
}
/* /*
* Bamboo Pad has a generic hid handling for the Pen, and we switch it * Bamboo Pad has a generic hid handling for the Pen, and we switch it
...@@ -1603,18 +1780,16 @@ static int wacom_probe(struct hid_device *hdev, ...@@ -1603,18 +1780,16 @@ static int wacom_probe(struct hid_device *hdev,
if (error) if (error)
goto fail_shared_data; goto fail_shared_data;
if (!(features->quirks & WACOM_QUIRK_MONITOR) && if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
(features->quirks & WACOM_QUIRK_BATTERY)) { (features->quirks & WACOM_QUIRK_BATTERY)) {
error = wacom_initialize_battery(wacom); error = wacom_initialize_battery(wacom);
if (error) if (error)
goto fail_battery; goto fail_battery;
} }
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { error = wacom_register_inputs(wacom);
error = wacom_register_inputs(wacom); if (error)
if (error) goto fail_register_inputs;
goto fail_register_inputs;
}
if (hdev->bus == BUS_BLUETOOTH) { if (hdev->bus == BUS_BLUETOOTH) {
error = device_create_file(&hdev->dev, &dev_attr_speed); error = device_create_file(&hdev->dev, &dev_attr_speed);
...@@ -1637,7 +1812,7 @@ static int wacom_probe(struct hid_device *hdev, ...@@ -1637,7 +1812,7 @@ static int wacom_probe(struct hid_device *hdev,
/* Note that if query fails it is not a hard failure */ /* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(hdev, features); wacom_query_tablet_data(hdev, features);
if (features->quirks & WACOM_QUIRK_MONITOR) if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
error = hid_hw_open(hdev); error = hid_hw_open(hdev);
if (wacom_wac->features.type == INTUOSHT && if (wacom_wac->features.type == INTUOSHT &&
...@@ -1711,7 +1886,6 @@ static struct hid_driver wacom_driver = { ...@@ -1711,7 +1886,6 @@ static struct hid_driver wacom_driver = {
.id_table = wacom_ids, .id_table = wacom_ids,
.probe = wacom_probe, .probe = wacom_probe,
.remove = wacom_remove, .remove = wacom_remove,
.event = wacom_wac_event,
.report = wacom_wac_report, .report = wacom_wac_report,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.resume = wacom_resume, .resume = wacom_resume,
......
此差异已折叠。
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#define WACOM_PKGLEN_MAX 192 #define WACOM_PKGLEN_MAX 192
#define WACOM_NAME_MAX 64 #define WACOM_NAME_MAX 64
#define WACOM_MAX_REMOTES 5
#define WACOM_STATUS_UNKNOWN 255
/* packet length for individual models */ /* packet length for individual models */
#define WACOM_PKGLEN_BBFUN 9 #define WACOM_PKGLEN_BBFUN 9
...@@ -65,11 +67,11 @@ ...@@ -65,11 +67,11 @@
#define WACOM_REPORT_USB 192 #define WACOM_REPORT_USB 192
#define WACOM_REPORT_BPAD_PEN 3 #define WACOM_REPORT_BPAD_PEN 3
#define WACOM_REPORT_BPAD_TOUCH 16 #define WACOM_REPORT_BPAD_TOUCH 16
#define WACOM_REPORT_DEVICE_LIST 16
#define WACOM_REPORT_REMOTE 17
/* device quirks */ /* device quirks */
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001
#define WACOM_QUIRK_NO_INPUT 0x0002
#define WACOM_QUIRK_MONITOR 0x0004
#define WACOM_QUIRK_BATTERY 0x0008 #define WACOM_QUIRK_BATTERY 0x0008
/* device types */ /* device types */
...@@ -77,6 +79,7 @@ ...@@ -77,6 +79,7 @@
#define WACOM_DEVICETYPE_PEN 0x0001 #define WACOM_DEVICETYPE_PEN 0x0001
#define WACOM_DEVICETYPE_TOUCH 0x0002 #define WACOM_DEVICETYPE_TOUCH 0x0002
#define WACOM_DEVICETYPE_PAD 0x0004 #define WACOM_DEVICETYPE_PAD 0x0004
#define WACOM_DEVICETYPE_WL_MONITOR 0x0008
#define WACOM_VENDORDEFINED_PEN 0xff0d0001 #define WACOM_VENDORDEFINED_PEN 0xff0d0001
...@@ -130,6 +133,7 @@ enum { ...@@ -130,6 +133,7 @@ enum {
WACOM_24HDT, WACOM_24HDT,
WACOM_27QHDT, WACOM_27QHDT,
BAMBOO_PAD, BAMBOO_PAD,
REMOTE,
TABLETPC, /* add new TPC below */ TABLETPC, /* add new TPC below */
TABLETPCE, TABLETPCE,
TABLETPC2FG, TABLETPC2FG,
...@@ -149,6 +153,7 @@ struct wacom_features { ...@@ -149,6 +153,7 @@ struct wacom_features {
int type; int type;
int x_resolution; int x_resolution;
int y_resolution; int y_resolution;
int numbered_buttons;
int x_min; int x_min;
int y_min; int y_min;
int device_type; int device_type;
...@@ -193,6 +198,10 @@ struct hid_data { ...@@ -193,6 +198,10 @@ struct hid_data {
int width; int width;
int height; int height;
int id; int id;
int cc_index;
int cc_value_index;
int num_expected;
int num_received;
}; };
struct wacom_wac { struct wacom_wac {
...@@ -204,7 +213,7 @@ struct wacom_wac { ...@@ -204,7 +213,7 @@ struct wacom_wac {
unsigned char data[WACOM_PKGLEN_MAX]; unsigned char data[WACOM_PKGLEN_MAX];
int tool[2]; int tool[2];
int id[2]; int id[2];
__u32 serial[2]; __u32 serial[5];
bool reporting_data; bool reporting_data;
struct wacom_features features; struct wacom_features features;
struct wacom_shared *shared; struct wacom_shared *shared;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册