Commit 851328fe authored by Linus Torvalds's avatar Linus Torvalds

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

Pull HID updates from Jiri Kosina:
 "to receive patches queued for 4.3 merge window in HID tree. Highlights:

   - a lot of improvements (regarding supported features and devices) to
     Wacom driver, from Aaron Skomra and Jason Gerecke
   - a lot of functional fixes and support for large I2C transfer to
     cp2112 driver, from Ellen Wang
   - HW support improvements to RMI driver, from Andrew Duggan
   - quite some small fixes and device ID additions all over the place"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (44 commits)
  HID: wacom: wacom_setup_numbered_buttons is local to wacom_wac
  HID: wacom: Add support for Express Key Remote.
  HID: wacom: Set button bits based on a new numbered_buttons
  HID: quirks: add QUIRK_NOGET for an other TPV touchscreen
  HID: usbhid: Fix the check for HID_RESET_PENDING in hid_io_error
  HID: i2c-hid: Only disable irq wake if it was successfully enabled during suspend
  HID: wacom: Use tablet-provided touch height/width values for INTUOSHT
  HID: gembird: add new driver to fix Gembird JPD-DualForce 2
  HID: lenovo: Hide middle-button press until release
  HID: lenovo: Add missing return-value check
  HID: lenovo: Use constants for axes names
  HID: wacom: Simplify 'wacom_pl_irq'
  HID: wacom: Do not repeatedly attempt to set device mode on error
  HID: wacom: Do not repeatedly attempt to set device mode on error
  HID: wacom: Remove WACOM_QUIRK_NO_INPUT
  HID: wacom: Replace WACOM_QUIRK_MONITOR with WACOM_DEVICETYPE_WL_MONITOR
  HID: wacom: Use calculated pkglen for wireless touch interface
  HID: sony: Fix DS4 controller reporting rate issues
  HID: chicony: Add support for Acer Aspire Switch 12
  HID: hid-lg: Add USBID for Logitech G29 Wheel
  ...
parents 2d678b68 f212bd95
...@@ -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.
...@@ -251,6 +251,12 @@ config HID_EZKEY ...@@ -251,6 +251,12 @@ config HID_EZKEY
---help--- ---help---
Support for Ezkey BTC 8193 keyboard. Support for Ezkey BTC 8193 keyboard.
config HID_GEMBIRD
tristate "Gembird Joypad"
depends on HID
---help---
Support for Gembird JPD-DualForce 2.
config HID_HOLTEK config HID_HOLTEK
tristate "Holtek HID devices" tristate "Holtek HID devices"
depends on USB_HID depends on USB_HID
...@@ -480,6 +486,7 @@ config HID_MULTITOUCH ...@@ -480,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
......
...@@ -36,6 +36,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o ...@@ -36,6 +36,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
obj-$(CONFIG_HID_ELO) += hid-elo.o obj-$(CONFIG_HID_ELO) += hid-elo.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
obj-$(CONFIG_HID_GT683R) += hid-gt683r.o obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
......
...@@ -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);
......
...@@ -427,6 +427,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) ...@@ -427,6 +427,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
{ {
__u32 data; __u32 data;
unsigned n; unsigned n;
__u32 count;
data = item_udata(item); data = item_udata(item);
...@@ -490,6 +491,24 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) ...@@ -490,6 +491,24 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
if (item->size <= 2) if (item->size <= 2)
data = (parser->global.usage_page << 16) + data; data = (parser->global.usage_page << 16) + data;
count = data - parser->local.usage_minimum;
if (count + parser->local.usage_index >= HID_MAX_USAGES) {
/*
* We do not warn if the name is not set, we are
* actually pre-scanning the device.
*/
if (dev_name(&parser->device->dev))
hid_warn(parser->device,
"ignoring exceeding usage max\n");
data = HID_MAX_USAGES - parser->local.usage_index +
parser->local.usage_minimum - 1;
if (data <= 0) {
hid_err(parser->device,
"no more usage index available\n");
return -1;
}
}
for (n = parser->local.usage_minimum; n <= data; n++) for (n = parser->local.usage_minimum; n <= data; n++)
if (hid_add_usage(parser, n)) { if (hid_add_usage(parser, n)) {
dbg_hid("hid_add_usage failed\n"); dbg_hid("hid_add_usage failed\n");
...@@ -705,8 +724,9 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) ...@@ -705,8 +724,9 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
hid->group = HID_GROUP_SENSOR_HUB; hid->group = HID_GROUP_SENSOR_HUB;
if (hid->vendor == USB_VENDOR_ID_MICROSOFT && if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
(hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3_JP || hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
hid->product == USB_DEVICE_ID_MS_POWER_COVER) && hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
hid->group == HID_GROUP_MULTITOUCH) hid->group == HID_GROUP_MULTITOUCH)
hid->group = HID_GROUP_GENERIC; hid->group = HID_GROUP_GENERIC;
...@@ -1807,6 +1827,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1807,6 +1827,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) },
...@@ -1823,6 +1844,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1823,6 +1844,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
...@@ -1905,8 +1927,9 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1905,8 +1927,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
......
...@@ -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);
......
/*
* HID driver for Gembird Joypad, "PC Game Controller"
*
* Copyright (c) 2015 Red Hat, Inc
* Copyright (c) 2015 Benjamin Tissoires
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define GEMBIRD_START_FAULTY_RDESC 8
static const __u8 gembird_jpd_faulty_rdesc[] = {
0x75, 0x08, /* Report Size (8) */
0x95, 0x05, /* Report Count (5) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xff, 0x00, /* Logical Maximum (255) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0xff, 0x00, /* Physical Maximum (255) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x09, 0x32, /* Usage (Z) */
0x09, 0x32, /* Usage (Z) */
0x09, 0x35, /* Usage (Rz) */
0x81, 0x02, /* Input (Data,Var,Abs) */
};
/*
* we fix the report descriptor by:
* - marking the first Z axis as constant (so it is ignored by HID)
* - assign the original second Z to Rx
* - assign the original Rz to Ry
*/
static const __u8 gembird_jpd_fixed_rdesc[] = {
0x75, 0x08, /* Report Size (8) */
0x95, 0x02, /* Report Count (2) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xff, 0x00, /* Logical Maximum (255) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0xff, 0x00, /* Physical Maximum (255) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x81, 0x02, /* Input (Data,Var,Abs) */
0x95, 0x01, /* Report Count (1) */
0x09, 0x32, /* Usage (Z) */
0x81, 0x01, /* Input (Cnst,Arr,Abs) */
0x95, 0x02, /* Report Count (2) */
0x09, 0x33, /* Usage (Rx) */
0x09, 0x34, /* Usage (Ry) */
0x81, 0x02, /* Input (Data,Var,Abs) */
};
static __u8 *gembird_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
__u8 *new_rdesc;
/* delta_size is > 0 */
size_t delta_size = sizeof(gembird_jpd_fixed_rdesc) -
sizeof(gembird_jpd_faulty_rdesc);
size_t new_size = *rsize + delta_size;
if (*rsize >= 31 && !memcmp(&rdesc[GEMBIRD_START_FAULTY_RDESC],
gembird_jpd_faulty_rdesc,
sizeof(gembird_jpd_faulty_rdesc))) {
new_rdesc = devm_kzalloc(&hdev->dev, new_size, GFP_KERNEL);
if (new_rdesc == NULL)
return rdesc;
dev_info(&hdev->dev,
"fixing Gembird JPD-DualForce 2 report descriptor.\n");
/* start by copying the end of the rdesc */
memcpy(new_rdesc + delta_size, rdesc, *rsize);
/* add the correct beginning */
memcpy(new_rdesc, rdesc, GEMBIRD_START_FAULTY_RDESC);
/* replace the faulty part with the fixed one */
memcpy(new_rdesc + GEMBIRD_START_FAULTY_RDESC,
gembird_jpd_fixed_rdesc,
sizeof(gembird_jpd_fixed_rdesc));
*rsize = new_size;
rdesc = new_rdesc;
}
return rdesc;
}
static const struct hid_device_id gembird_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD,
USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
{ }
};
MODULE_DEVICE_TABLE(hid, gembird_devices);
static struct hid_driver gembird_driver = {
.name = "gembird",
.id_table = gembird_devices,
.report_fixup = gembird_report_fixup,
};
module_hid_driver(gembird_driver);
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
MODULE_DESCRIPTION("HID Gembird joypad driver");
MODULE_LICENSE("GPL");
...@@ -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
...@@ -358,6 +363,9 @@ ...@@ -358,6 +363,9 @@
#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
#define USB_VENDOR_ID_GEMBIRD 0x11ff
#define USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2 0x3331
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100
...@@ -500,6 +508,9 @@ ...@@ -500,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
...@@ -602,6 +613,7 @@ ...@@ -602,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
...@@ -666,8 +678,9 @@ ...@@ -666,8 +678,9 @@
#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07dc #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc
#define USB_DEVICE_ID_MS_TYPE_COVER_3_JP 0x07dd #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da #define USB_DEVICE_ID_MS_POWER_COVER 0x07da
#define USB_VENDOR_ID_MOJO 0x8282 #define USB_VENDOR_ID_MOJO 0x8282
...@@ -925,7 +938,8 @@ ...@@ -925,7 +938,8 @@
#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688
#define USB_VENDOR_ID_TPV 0x25aa #define USB_VENDOR_ID_TPV 0x25aa
#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN 0x8883 #define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882 0x8882
#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883 0x8883
#define USB_VENDOR_ID_TURBOX 0x062a #define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
......
...@@ -1166,8 +1166,11 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct ...@@ -1166,8 +1166,11 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
input_event(input, usage->type, usage->code, value); input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) if ((field->flags & HID_MAIN_ITEM_RELATIVE) &&
usage->type == EV_KEY && value) {
input_sync(input);
input_event(input, usage->type, usage->code, 0); input_event(input, usage->type, usage->code, 0);
}
} }
void hidinput_report_event(struct hid_device *hid, struct hid_report *report) void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
......
...@@ -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),
......
...@@ -276,9 +276,11 @@ static const struct hid_device_id ms_devices[] = { ...@@ -276,9 +276,11 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_NOGET }, .driver_data = MS_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
.driver_data = MS_DUPLICATE_USAGES }, .driver_data = MS_DUPLICATE_USAGES },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3),
.driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
.driver_data = MS_HIDINPUT }, .driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
.driver_data = MS_HIDINPUT }, .driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
.driver_data = MS_HIDINPUT }, .driver_data = MS_HIDINPUT },
......
...@@ -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);
......
...@@ -164,7 +164,7 @@ static void hid_io_error(struct hid_device *hid) ...@@ -164,7 +164,7 @@ static void hid_io_error(struct hid_device *hid)
if (time_after(jiffies, usbhid->stop_retry)) { if (time_after(jiffies, usbhid->stop_retry)) {
/* Retries failed, so do a port reset unless we lack bandwidth*/ /* Retries failed, so do a port reset unless we lack bandwidth*/
if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
&& !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
schedule_work(&usbhid->reset_work); schedule_work(&usbhid->reset_work);
...@@ -710,7 +710,8 @@ int usbhid_open(struct hid_device *hid) ...@@ -710,7 +710,8 @@ int usbhid_open(struct hid_device *hid)
* Wait 50 msec for the queue to empty before allowing events * Wait 50 msec for the queue to empty before allowing events
* to go through hid. * to go through hid.
*/ */
msleep(50); if (res == 0 && !(hid->quirks & HID_QUIRK_ALWAYS_POLL))
msleep(50);
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
} }
done: done:
......
...@@ -90,8 +90,9 @@ static const struct hid_blacklist { ...@@ -90,8 +90,9 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
...@@ -117,7 +118,8 @@ static const struct hid_blacklist { ...@@ -117,7 +118,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT },
......
...@@ -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
This diff is collapsed.
This diff is collapsed.
...@@ -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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment