mirror of https://gitee.com/openkylin/linux.git
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 ...
This commit is contained in:
commit
851328feb8
|
@ -77,3 +77,22 @@ Description:
|
|||
The format is also scrambled, like in the USB mode, and it can
|
||||
be summarized by converting 76543210 into GECA6420.
|
||||
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
|
|||
---help---
|
||||
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
|
||||
tristate "Holtek HID devices"
|
||||
depends on USB_HID
|
||||
|
@ -480,6 +486,7 @@ config HID_MULTITOUCH
|
|||
- Atmel panels
|
||||
- Cando dual touch panels
|
||||
- Chunghwa panels
|
||||
- CJTouch panels
|
||||
- CVTouch panels
|
||||
- Cypress TrueTouch panels
|
||||
- Elan Microelectronics touch panels
|
||||
|
|
|
@ -36,6 +36,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
|
|||
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
|
||||
obj-$(CONFIG_HID_ELO) += hid-elo.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_GYRATION) += hid-gyration.o
|
||||
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
|
@ -57,10 +58,34 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
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[] = {
|
||||
{ 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_AK1D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ch_devices);
|
||||
|
@ -68,6 +93,7 @@ MODULE_DEVICE_TABLE(hid, ch_devices);
|
|||
static struct hid_driver ch_driver = {
|
||||
.name = "chicony",
|
||||
.id_table = ch_devices,
|
||||
.report_fixup = ch_switch12_report_fixup,
|
||||
.input_mapping = ch_input_mapping,
|
||||
};
|
||||
module_hid_driver(ch_driver);
|
||||
|
|
|
@ -427,6 +427,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
|||
{
|
||||
__u32 data;
|
||||
unsigned n;
|
||||
__u32 count;
|
||||
|
||||
data = item_udata(item);
|
||||
|
||||
|
@ -490,6 +491,24 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
|||
if (item->size <= 2)
|
||||
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++)
|
||||
if (hid_add_usage(parser, n)) {
|
||||
dbg_hid("hid_add_usage failed\n");
|
||||
|
@ -705,8 +724,9 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
|
|||
hid->group = HID_GROUP_SENSOR_HUB;
|
||||
|
||||
if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
|
||||
(hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
|
||||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3_JP ||
|
||||
(hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
|
||||
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->group == HID_GROUP_MULTITOUCH)
|
||||
hid->group = HID_GROUP_GENERIC;
|
||||
|
@ -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_WIRELESS2) },
|
||||
{ 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_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
|
||||
{ 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[] = {
|
|||
{ 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_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, 0x0012) },
|
||||
{ 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[] = {
|
|||
{ 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_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_JP) },
|
||||
{ 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_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
|
||||
|
|
|
@ -156,6 +156,7 @@ struct cp2112_device {
|
|||
wait_queue_head_t wait;
|
||||
u8 read_data[61];
|
||||
u8 read_length;
|
||||
u8 hwversion;
|
||||
int xfer_status;
|
||||
atomic_t read_avail;
|
||||
atomic_t xfer_avail;
|
||||
|
@ -446,6 +447,24 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
|
|||
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,
|
||||
int num)
|
||||
{
|
||||
|
@ -453,26 +472,46 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||
struct hid_device *hdev = dev->hdev;
|
||||
u8 buf[64];
|
||||
ssize_t count;
|
||||
ssize_t read_length = 0;
|
||||
u8 *read_buf = NULL;
|
||||
unsigned int retries;
|
||||
int ret;
|
||||
|
||||
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,
|
||||
"Multi-message I2C transactions not supported\n");
|
||||
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);
|
||||
if (ret < 0) {
|
||||
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,
|
|||
goto power_normal;
|
||||
}
|
||||
|
||||
if (!(msgs->flags & I2C_M_RD))
|
||||
goto finish;
|
||||
|
||||
ret = cp2112_read(dev, msgs->buf, msgs->len);
|
||||
if (ret < 0)
|
||||
goto power_normal;
|
||||
if (ret != msgs->len) {
|
||||
hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len);
|
||||
ret = -EIO;
|
||||
goto power_normal;
|
||||
for (count = 0; count < read_length;) {
|
||||
ret = cp2112_read(dev, read_buf + count, read_length - count);
|
||||
if (ret < 0)
|
||||
goto power_normal;
|
||||
if (ret == 0) {
|
||||
hid_err(hdev, "read returned 0\n");
|
||||
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 */
|
||||
ret = 1;
|
||||
ret = num;
|
||||
|
||||
power_normal:
|
||||
hid_hw_power(hdev, PM_HINT_NORMAL);
|
||||
|
@ -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 hid_device *hdev = dev->hdev;
|
||||
u8 buf[64];
|
||||
__be16 word;
|
||||
__le16 word;
|
||||
ssize_t count;
|
||||
size_t read_length = 0;
|
||||
unsigned int retries;
|
||||
|
@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
|
|||
if (I2C_SMBUS_READ == read_write)
|
||||
count = cp2112_read_req(buf, addr, read_length);
|
||||
else
|
||||
count = cp2112_write_req(buf, addr, data->byte, NULL,
|
||||
count = cp2112_write_req(buf, addr, command, NULL,
|
||||
0);
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
|
@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
|
|||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
read_length = 2;
|
||||
word = cpu_to_be16(data->word);
|
||||
word = cpu_to_le16(data->word);
|
||||
|
||||
if (I2C_SMBUS_READ == read_write)
|
||||
count = cp2112_write_read_req(buf, addr, read_length,
|
||||
|
@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
|
|||
size = I2C_SMBUS_WORD_DATA;
|
||||
read_write = I2C_SMBUS_READ;
|
||||
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,
|
||||
(u8 *)&word, 2);
|
||||
|
@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
|
|||
data->byte = buf[0];
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
data->word = be16_to_cpup((__be16 *)buf);
|
||||
data->word = le16_to_cpup((__le16 *)buf);
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
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)
|
|||
dev->adap.dev.parent = &hdev->dev;
|
||||
snprintf(dev->adap.name, sizeof(dev->adap.name),
|
||||
"CP2112 SMBus Bridge on hiddev%d", hdev->minor);
|
||||
dev->hwversion = buf[2];
|
||||
init_waitqueue_head(&dev->wait);
|
||||
|
||||
hid_device_io_start(hdev);
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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 @@
|
|||
#define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053
|
||||
#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123
|
||||
#define USB_DEVICE_ID_CHICONY_AK1D 0x1125
|
||||
#define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
|
||||
|
||||
#define USB_VENDOR_ID_CHUNGHWAT 0x2247
|
||||
#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001
|
||||
|
||||
#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_DEVICE_ID_CM109 0x000e
|
||||
|
||||
|
@ -358,6 +363,9 @@
|
|||
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
|
||||
#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_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
|
||||
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100
|
||||
|
@ -500,6 +508,9 @@
|
|||
#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615
|
||||
#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_DEVICE_ID_JABRA_SPEAK_410 0x0412
|
||||
#define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420
|
||||
|
@ -602,6 +613,7 @@
|
|||
#define USB_DEVICE_ID_LOGITECH_DUAL_ACTION 0xc216
|
||||
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
|
||||
#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_FORCE3D_PRO 0xc286
|
||||
#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287
|
||||
|
@ -666,8 +678,9 @@
|
|||
#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
|
||||
#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_3 0x07dc
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_3_JP 0x07dd
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc
|
||||
#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_VENDOR_ID_MOJO 0x8282
|
||||
|
@ -925,7 +938,8 @@
|
|||
#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688
|
||||
|
||||
#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_DEVICE_ID_TURBOX_KEYBOARD 0x0201
|
||||
|
|
|
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
|
||||
|
|
|
@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd {
|
|||
};
|
||||
|
||||
struct lenovo_drvdata_cptkbd {
|
||||
u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
|
||||
bool fn_lock;
|
||||
int sensitivity;
|
||||
};
|
||||
|
@ -146,10 +147,10 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
|
|||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
return -1;
|
||||
|
@ -207,9 +208,12 @@ static void lenovo_features_set_cptkbd(struct hid_device *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, 0x02, cptkbd_data->sensitivity);
|
||||
if (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,
|
||||
|
@ -313,6 +317,53 @@ static int lenovo_raw_event(struct hid_device *hdev,
|
|||
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)
|
||||
{
|
||||
struct hid_report *report;
|
||||
|
@ -705,6 +756,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
|
|||
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
|
||||
|
||||
/* Set keyboard settings to known state */
|
||||
cptkbd_data->middlebutton_state = 0;
|
||||
cptkbd_data->fn_lock = true;
|
||||
cptkbd_data->sensitivity = 0x05;
|
||||
lenovo_features_set_cptkbd(hdev);
|
||||
|
@ -832,6 +884,7 @@ static struct hid_driver lenovo_driver = {
|
|||
.probe = lenovo_probe,
|
||||
.remove = lenovo_remove,
|
||||
.raw_event = lenovo_raw_event,
|
||||
.event = lenovo_event,
|
||||
.report_fixup = lenovo_report_fixup,
|
||||
};
|
||||
module_hid_driver(lenovo_driver);
|
||||
|
|
|
@ -776,6 +776,8 @@ static const struct hid_device_id lg_devices[] = {
|
|||
.driver_data = LG_FF },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
|
||||
.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),
|
||||
.driver_data = LG_FF },
|
||||
{ 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[] = {
|
|||
.driver_data = MS_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
|
||||
.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_3_JP),
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
|
||||
.driver_data = MS_HIDINPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
|
||||
.driver_data = MS_HIDINPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
|
||||
.driver_data = MS_HIDINPUT },
|
||||
|
|
|
@ -1145,6 +1145,14 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
|
||||
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 */
|
||||
{ .driver_data = MT_CLS_NSMU,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
|
||||
|
|
|
@ -94,8 +94,7 @@ void picolcd_exit_backlight(struct picolcd_data *data)
|
|||
struct backlight_device *bdev = data->backlight;
|
||||
|
||||
data->backlight = NULL;
|
||||
if (bdev)
|
||||
backlight_device_unregister(bdev);
|
||||
backlight_device_unregister(bdev);
|
||||
}
|
||||
|
||||
int picolcd_resume_backlight(struct picolcd_data *data)
|
||||
|
|
|
@ -145,7 +145,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
|
|||
struct rc_dev *rdev = data->rc_dev;
|
||||
|
||||
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)
|
|||
struct lcd_device *ldev = data->lcd;
|
||||
|
||||
data->lcd = NULL;
|
||||
if (ldev)
|
||||
lcd_device_unregister(ldev);
|
||||
lcd_device_unregister(ldev);
|
||||
}
|
||||
|
||||
int picolcd_resume_lcd(struct picolcd_data *data)
|
||||
|
|
|
@ -33,10 +33,21 @@
|
|||
#define RMI_READ_DATA_PENDING 1
|
||||
#define RMI_STARTED 2
|
||||
|
||||
#define RMI_SLEEP_NORMAL 0x0
|
||||
#define RMI_SLEEP_DEEP_SLEEP 0x1
|
||||
|
||||
/* device flags */
|
||||
#define RMI_DEVICE BIT(0)
|
||||
#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 {
|
||||
RMI_MODE_OFF = 0,
|
||||
RMI_MODE_ATTN_REPORTS = 1,
|
||||
|
@ -113,6 +124,8 @@ struct rmi_data {
|
|||
unsigned int max_y;
|
||||
unsigned int x_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 button_count;
|
||||
|
@ -126,6 +139,10 @@ struct rmi_data {
|
|||
|
||||
unsigned long device_flags;
|
||||
unsigned long firmware_id;
|
||||
|
||||
u8 f01_ctrl0;
|
||||
u8 interrupt_enable_mask;
|
||||
bool restore_interrupt_mask;
|
||||
};
|
||||
|
||||
#define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
|
||||
|
@ -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)
|
||||
{
|
||||
struct rmi_data *hdata = container_of(work, struct rmi_data,
|
||||
reset_work);
|
||||
|
||||
/* 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)
|
||||
|
@ -532,14 +570,77 @@ static int rmi_event(struct hid_device *hdev, struct hid_field *field,
|
|||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
|
||||
return rmi_reset_attn_mode(hdev);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
@ -595,6 +696,7 @@ static void rmi_register_function(struct rmi_data *data,
|
|||
f->interrupt_count = pdt_entry->interrupt_source_count;
|
||||
f->irq_mask = rmi_gen_mask(f->interrupt_base,
|
||||
f->interrupt_count);
|
||||
data->interrupt_enable_mask |= f->irq_mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,6 +834,35 @@ static int rmi_populate_f01(struct hid_device *hdev)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -904,24 +1035,23 @@ static int rmi_populate_f11(struct hid_device *hdev)
|
|||
if (has_data40)
|
||||
data->f11.report_size += data->max_fingers * 2;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 12);
|
||||
ret = rmi_read_block(hdev, data->f11.control_base_addr,
|
||||
data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
|
||||
if (ret) {
|
||||
hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->max_x = buf[6] | (buf[7] << 8);
|
||||
data->max_y = buf[8] | (buf[9] << 8);
|
||||
/* data->f11_ctrl_regs now contains valid register data */
|
||||
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) {
|
||||
buf[0] = buf[0] & ~BIT(6);
|
||||
ret = rmi_write(hdev, data->f11.control_base_addr, buf);
|
||||
data->f11_ctrl_regs[0] = data->f11_ctrl_regs[0] & ~BIT(6);
|
||||
ret = rmi_write(hdev, data->f11.control_base_addr,
|
||||
data->f11_ctrl_regs);
|
||||
if (ret) {
|
||||
hid_err(hdev, "can not write to control reg 0: %d.\n",
|
||||
ret);
|
||||
|
@ -930,9 +1060,9 @@ static int rmi_populate_f11(struct hid_device *hdev)
|
|||
}
|
||||
|
||||
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,
|
||||
&buf[11]);
|
||||
&data->f11_ctrl_regs[11]);
|
||||
if (ret) {
|
||||
hid_err(hdev, "can not write to control reg 11: %d.\n",
|
||||
ret);
|
||||
|
@ -1273,6 +1403,7 @@ static struct hid_driver rmi_driver = {
|
|||
.input_mapping = rmi_input_mapping,
|
||||
.input_configured = rmi_input_configured,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = rmi_suspend,
|
||||
.resume = rmi_post_resume,
|
||||
.reset_resume = rmi_post_reset,
|
||||
#endif
|
||||
|
|
|
@ -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,
|
||||
USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA),
|
||||
.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_ANY_ID) },
|
||||
{ }
|
||||
|
|
|
@ -296,7 +296,14 @@ static __u8 navigation_rdesc[] = {
|
|||
0x09, 0x01, /* Usage (Pointer), */
|
||||
0x81, 0x02, /* Input (Variable), */
|
||||
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), */
|
||||
0x75, 0x08, /* Report Size (8), */
|
||||
0x95, 0x30, /* Report Count (48), */
|
||||
|
@ -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
|
||||
*/
|
||||
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[43], rd[44]);
|
||||
swap(rd[45], rd[46]);
|
||||
|
@ -1836,7 +1854,7 @@ static void dualshock4_state_worker(struct work_struct *work)
|
|||
} else {
|
||||
memset(buf, 0, DS4_REPORT_0x11_SIZE);
|
||||
buf[0] = 0x11;
|
||||
buf[1] = 0xB0;
|
||||
buf[1] = 0x80;
|
||||
buf[3] = 0x0F;
|
||||
offset = 6;
|
||||
}
|
||||
|
|
|
@ -149,6 +149,8 @@ struct i2c_hid {
|
|||
int irq;
|
||||
|
||||
struct i2c_hid_platform_data pdata;
|
||||
|
||||
bool irq_wake_enabled;
|
||||
};
|
||||
|
||||
static int __i2c_hid_command(struct i2c_client *client,
|
||||
|
@ -1091,14 +1093,21 @@ static int i2c_hid_suspend(struct device *dev)
|
|||
struct i2c_hid *ihid = i2c_get_clientdata(client);
|
||||
struct hid_device *hid = ihid->hid;
|
||||
int ret = 0;
|
||||
|
||||
disable_irq(ihid->irq);
|
||||
if (device_may_wakeup(&client->dev))
|
||||
enable_irq_wake(ihid->irq);
|
||||
int wake_status;
|
||||
|
||||
if (hid->driver && hid->driver->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 */
|
||||
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
|
||||
|
||||
|
@ -1111,14 +1120,21 @@ static int i2c_hid_resume(struct device *dev)
|
|||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_hid *ihid = i2c_get_clientdata(client);
|
||||
struct hid_device *hid = ihid->hid;
|
||||
int wake_status;
|
||||
|
||||
enable_irq(ihid->irq);
|
||||
ret = i2c_hid_hwreset(client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
disable_irq_wake(ihid->irq);
|
||||
if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) {
|
||||
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) {
|
||||
ret = hid->driver->reset_resume(hid);
|
||||
|
|
|
@ -164,7 +164,7 @@ static void hid_io_error(struct hid_device *hid)
|
|||
if (time_after(jiffies, usbhid->stop_retry)) {
|
||||
|
||||
/* 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)) {
|
||||
|
||||
schedule_work(&usbhid->reset_work);
|
||||
|
@ -710,7 +710,8 @@ int usbhid_open(struct hid_device *hid)
|
|||
* Wait 50 msec for the queue to empty before allowing events
|
||||
* to go through hid.
|
||||
*/
|
||||
msleep(50);
|
||||
if (res == 0 && !(hid->quirks & HID_QUIRK_ALWAYS_POLL))
|
||||
msleep(50);
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
}
|
||||
done:
|
||||
|
|
|
@ -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_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_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_JP, 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_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
|
||||
|
@ -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_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_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_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 },
|
||||
|
|
|
@ -113,7 +113,7 @@ struct wacom {
|
|||
struct mutex lock;
|
||||
struct work_struct work;
|
||||
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 hlv; /* status led brightness button pressed (1..127) */
|
||||
u8 img_lum; /* OLED matrix display brightness */
|
||||
|
@ -123,6 +123,8 @@ struct wacom {
|
|||
struct power_supply *ac;
|
||||
struct power_supply_desc battery_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)
|
||||
|
@ -147,4 +149,7 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
|
|||
struct hid_usage *usage, __s32 value);
|
||||
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report);
|
||||
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
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
#define WAC_CMD_ICON_XFER 0x23
|
||||
#define WAC_CMD_ICON_BT_XFER 0x26
|
||||
#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_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,
|
||||
size_t size, unsigned int retries)
|
||||
|
@ -335,7 +339,7 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
|
|||
if (error >= 0)
|
||||
error = wacom_get_report(hdev, HID_FEATURE_REPORT,
|
||||
rep_data, length, 1);
|
||||
} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
|
||||
} while (error >= 0 && rep_data[1] != mode && limit++ < WAC_MSG_RETRIES);
|
||||
|
||||
kfree(rep_data);
|
||||
|
||||
|
@ -453,12 +457,11 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
|
|||
* interface number.
|
||||
*/
|
||||
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;
|
||||
} else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) {
|
||||
features->device_type |= WACOM_DEVICETYPE_TOUCH;
|
||||
features->pktlen = WACOM_PKGLEN_BBTOUCH3;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
wacom_parse_hid(hdev, features);
|
||||
|
@ -1120,6 +1123,189 @@ static ssize_t wacom_store_speed(struct device *dev,
|
|||
static DEVICE_ATTR(speed, DEV_ATTR_RW_PERM,
|
||||
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)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
|
@ -1130,7 +1316,7 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
|
|||
if (!input_dev)
|
||||
return NULL;
|
||||
|
||||
input_dev->name = wacom_wac->pen_name;
|
||||
input_dev->name = wacom_wac->features.name;
|
||||
input_dev->phys = hdev->phys;
|
||||
input_dev->dev.parent = &hdev->dev;
|
||||
input_dev->open = wacom_open;
|
||||
|
@ -1145,43 +1331,6 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
|
|||
return input_dev;
|
||||
}
|
||||
|
||||
static void wacom_free_inputs(struct wacom *wacom)
|
||||
{
|
||||
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
|
||||
|
||||
if (wacom_wac->pen_input)
|
||||
input_free_device(wacom_wac->pen_input);
|
||||
if (wacom_wac->touch_input)
|
||||
input_free_device(wacom_wac->touch_input);
|
||||
if (wacom_wac->pad_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)
|
||||
{
|
||||
if (wacom->wacom_wac.pen_input) {
|
||||
|
@ -1202,12 +1351,33 @@ static void wacom_clean_inputs(struct wacom *wacom)
|
|||
else
|
||||
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.touch_input = NULL;
|
||||
wacom->wacom_wac.pad_input = NULL;
|
||||
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)
|
||||
{
|
||||
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
|
||||
|
@ -1262,10 +1432,16 @@ static int wacom_register_inputs(struct wacom *wacom)
|
|||
error = wacom_initialize_leds(wacom);
|
||||
if (error)
|
||||
goto fail_leds;
|
||||
|
||||
error = wacom_initialize_remote(wacom);
|
||||
if (error)
|
||||
goto fail_remote;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_remote:
|
||||
wacom_destroy_leds(wacom);
|
||||
fail_leds:
|
||||
input_unregister_device(pad_input_dev);
|
||||
pad_input_dev = NULL;
|
||||
|
@ -1556,11 +1732,9 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
mutex_init(&wacom->lock);
|
||||
INIT_WORK(&wacom->work, wacom_wireless_work);
|
||||
|
||||
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
|
||||
error = wacom_allocate_inputs(wacom);
|
||||
if (error)
|
||||
goto fail_allocate_inputs;
|
||||
}
|
||||
error = wacom_allocate_inputs(wacom);
|
||||
if (error)
|
||||
goto fail_allocate_inputs;
|
||||
|
||||
/*
|
||||
* Bamboo Pad has a generic hid handling for the Pen, and we switch it
|
||||
|
@ -1606,18 +1780,16 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
if (error)
|
||||
goto fail_shared_data;
|
||||
|
||||
if (!(features->quirks & WACOM_QUIRK_MONITOR) &&
|
||||
if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
|
||||
(features->quirks & WACOM_QUIRK_BATTERY)) {
|
||||
error = wacom_initialize_battery(wacom);
|
||||
if (error)
|
||||
goto fail_battery;
|
||||
}
|
||||
|
||||
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
|
||||
error = wacom_register_inputs(wacom);
|
||||
if (error)
|
||||
goto fail_register_inputs;
|
||||
}
|
||||
error = wacom_register_inputs(wacom);
|
||||
if (error)
|
||||
goto fail_register_inputs;
|
||||
|
||||
if (hdev->bus == BUS_BLUETOOTH) {
|
||||
error = device_create_file(&hdev->dev, &dev_attr_speed);
|
||||
|
@ -1640,7 +1812,7 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
/* Note that if query fails it is not a hard failure */
|
||||
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);
|
||||
|
||||
if (wacom_wac->features.type == INTUOSHT &&
|
||||
|
@ -1714,7 +1886,6 @@ static struct hid_driver wacom_driver = {
|
|||
.id_table = wacom_ids,
|
||||
.probe = wacom_probe,
|
||||
.remove = wacom_remove,
|
||||
.event = wacom_wac_event,
|
||||
.report = wacom_wac_report,
|
||||
#ifdef CONFIG_PM
|
||||
.resume = wacom_resume,
|
||||
|
|
|
@ -125,61 +125,47 @@ static int wacom_pl_irq(struct wacom_wac *wacom)
|
|||
|
||||
prox = data[1] & 0x40;
|
||||
|
||||
if (prox) {
|
||||
wacom->id[0] = ERASER_DEVICE_ID;
|
||||
pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
|
||||
if (features->pressure_max > 255)
|
||||
pressure = (pressure << 1) | ((data[4] >> 6) & 1);
|
||||
pressure += (features->pressure_max + 1) / 2;
|
||||
|
||||
/*
|
||||
* if going from out of proximity into proximity select between the eraser
|
||||
* and the pen based on the state of the stylus2 button, choose eraser if
|
||||
* pressed else choose pen. if not a proximity change from out to in, send
|
||||
* an out of proximity for previous tool then a in for new tool.
|
||||
*/
|
||||
if (!wacom->tool[0]) {
|
||||
/* Eraser bit set for DTF */
|
||||
if (data[1] & 0x10)
|
||||
wacom->tool[1] = BTN_TOOL_RUBBER;
|
||||
else
|
||||
/* Going into proximity select tool */
|
||||
wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
|
||||
} else {
|
||||
/* was entered with stylus2 pressed */
|
||||
if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
|
||||
/* report out proximity for previous tool */
|
||||
input_report_key(input, wacom->tool[1], 0);
|
||||
input_sync(input);
|
||||
wacom->tool[1] = BTN_TOOL_PEN;
|
||||
return 0;
|
||||
}
|
||||
if (!wacom->id[0]) {
|
||||
if ((data[0] & 0x10) || (data[4] & 0x20)) {
|
||||
wacom->tool[0] = BTN_TOOL_RUBBER;
|
||||
wacom->id[0] = ERASER_DEVICE_ID;
|
||||
}
|
||||
if (wacom->tool[1] != BTN_TOOL_RUBBER) {
|
||||
/* Unknown tool selected default to pen tool */
|
||||
wacom->tool[1] = BTN_TOOL_PEN;
|
||||
else {
|
||||
wacom->tool[0] = BTN_TOOL_PEN;
|
||||
wacom->id[0] = STYLUS_DEVICE_ID;
|
||||
}
|
||||
input_report_key(input, wacom->tool[1], prox); /* report in proximity for tool */
|
||||
input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
|
||||
input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_PRESSURE, pressure);
|
||||
|
||||
input_report_key(input, BTN_TOUCH, data[4] & 0x08);
|
||||
input_report_key(input, BTN_STYLUS, data[4] & 0x10);
|
||||
/* Only allow the stylus2 button to be reported for the pen tool. */
|
||||
input_report_key(input, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
|
||||
} else {
|
||||
/* report proximity-out of a (valid) tool */
|
||||
if (wacom->tool[1] != BTN_TOOL_RUBBER) {
|
||||
/* Unknown tool selected default to pen tool */
|
||||
wacom->tool[1] = BTN_TOOL_PEN;
|
||||
}
|
||||
input_report_key(input, wacom->tool[1], prox);
|
||||
}
|
||||
|
||||
wacom->tool[0] = prox; /* Save proximity state */
|
||||
/* If the eraser is in prox, STYLUS2 is always set. If we
|
||||
* mis-detected the type and notice that STYLUS2 isn't set
|
||||
* then force the eraser out of prox and let the pen in.
|
||||
*/
|
||||
if (wacom->tool[0] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
|
||||
input_report_key(input, BTN_TOOL_RUBBER, 0);
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
input_sync(input);
|
||||
wacom->tool[0] = BTN_TOOL_PEN;
|
||||
wacom->id[0] = STYLUS_DEVICE_ID;
|
||||
}
|
||||
|
||||
pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
|
||||
if (features->pressure_max > 255)
|
||||
pressure = (pressure << 1) | ((data[4] >> 6) & 1);
|
||||
pressure += (features->pressure_max + 1) / 2;
|
||||
|
||||
input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_PRESSURE, pressure);
|
||||
|
||||
input_report_key(input, BTN_TOUCH, data[4] & 0x08);
|
||||
input_report_key(input, BTN_STYLUS, data[4] & 0x10);
|
||||
/* Only allow the stylus2 button to be reported for the pen tool. */
|
||||
input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
|
||||
|
||||
if (!prox)
|
||||
wacom->id[0] = 0;
|
||||
input_report_key(input, wacom->tool[0], prox);
|
||||
input_report_abs(input, ABS_MISC, wacom->id[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -645,6 +631,130 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
{
|
||||
unsigned char *data = wacom_wac->data;
|
||||
struct input_dev *input = wacom_wac->pad_input;
|
||||
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
int bat_charging, bat_percent, touch_ring_mode;
|
||||
__u32 serial;
|
||||
int i;
|
||||
|
||||
if (data[0] != WACOM_REPORT_REMOTE) {
|
||||
dev_dbg(input->dev.parent,
|
||||
"%s: received unknown report #%d", __func__, data[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
serial = data[3] + (data[4] << 8) + (data[5] << 16);
|
||||
wacom_wac->id[0] = PAD_DEVICE_ID;
|
||||
|
||||
input_report_key(input, BTN_0, (data[9] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[9] & 0x02));
|
||||
input_report_key(input, BTN_2, (data[9] & 0x04));
|
||||
input_report_key(input, BTN_3, (data[9] & 0x08));
|
||||
input_report_key(input, BTN_4, (data[9] & 0x10));
|
||||
input_report_key(input, BTN_5, (data[9] & 0x20));
|
||||
input_report_key(input, BTN_6, (data[9] & 0x40));
|
||||
input_report_key(input, BTN_7, (data[9] & 0x80));
|
||||
|
||||
input_report_key(input, BTN_8, (data[10] & 0x01));
|
||||
input_report_key(input, BTN_9, (data[10] & 0x02));
|
||||
input_report_key(input, BTN_A, (data[10] & 0x04));
|
||||
input_report_key(input, BTN_B, (data[10] & 0x08));
|
||||
input_report_key(input, BTN_C, (data[10] & 0x10));
|
||||
input_report_key(input, BTN_X, (data[10] & 0x20));
|
||||
input_report_key(input, BTN_Y, (data[10] & 0x40));
|
||||
input_report_key(input, BTN_Z, (data[10] & 0x80));
|
||||
|
||||
input_report_key(input, BTN_BASE, (data[11] & 0x01));
|
||||
input_report_key(input, BTN_BASE2, (data[11] & 0x02));
|
||||
|
||||
if (data[12] & 0x80)
|
||||
input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f));
|
||||
else
|
||||
input_report_abs(input, ABS_WHEEL, 0);
|
||||
|
||||
bat_percent = data[7] & 0x7f;
|
||||
bat_charging = !!(data[7] & 0x80);
|
||||
|
||||
if (data[9] | data[10] | (data[11] & 0x03) | data[12])
|
||||
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
else
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
|
||||
input_event(input, EV_MSC, MSC_SERIAL, serial);
|
||||
|
||||
/*Which mode select (LED light) is currently on?*/
|
||||
touch_ring_mode = (data[11] & 0xC0) >> 6;
|
||||
|
||||
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
|
||||
if (wacom_wac->serial[i] == serial)
|
||||
wacom->led.select[i] = touch_ring_mode;
|
||||
}
|
||||
|
||||
if (!wacom->battery &&
|
||||
!(features->quirks & WACOM_QUIRK_BATTERY)) {
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
INIT_WORK(&wacom->work, wacom_battery_work);
|
||||
wacom_schedule_work(wacom_wac);
|
||||
}
|
||||
|
||||
wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1,
|
||||
bat_charging);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
{
|
||||
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
|
||||
unsigned char *data = wacom_wac->data;
|
||||
int i;
|
||||
|
||||
if (data[0] != WACOM_REPORT_DEVICE_LIST)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
|
||||
int j = i * 6;
|
||||
int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4];
|
||||
bool connected = data[j+2];
|
||||
|
||||
if (connected) {
|
||||
int k;
|
||||
|
||||
if (wacom_wac->serial[i] == serial)
|
||||
continue;
|
||||
|
||||
if (wacom_wac->serial[i]) {
|
||||
wacom_remote_destroy_attr_group(wacom,
|
||||
wacom_wac->serial[i]);
|
||||
}
|
||||
|
||||
/* A remote can pair more than once with an EKR,
|
||||
* check to make sure this serial isn't already paired.
|
||||
*/
|
||||
for (k = 0; k < WACOM_MAX_REMOTES; k++) {
|
||||
if (wacom_wac->serial[k] == serial)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k < WACOM_MAX_REMOTES) {
|
||||
wacom_wac->serial[i] = serial;
|
||||
continue;
|
||||
}
|
||||
wacom_remote_create_attr_group(wacom, serial, i);
|
||||
|
||||
} else if (wacom_wac->serial[i]) {
|
||||
wacom_remote_destroy_attr_group(wacom,
|
||||
wacom_wac->serial[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wacom_intuos_general(struct wacom_wac *wacom)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
|
@ -1437,6 +1547,12 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wacom_wac_pen_pre_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void wacom_wac_pen_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
|
@ -1491,6 +1607,13 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
|
|||
wacom_map_usage(input, usage, field, EV_ABS,
|
||||
ABS_MT_POSITION_Y, 4);
|
||||
break;
|
||||
case HID_DG_WIDTH:
|
||||
case HID_DG_HEIGHT:
|
||||
features->last_slot_field = usage->hid;
|
||||
wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
|
||||
wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
|
||||
input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
features->last_slot_field = usage->hid;
|
||||
break;
|
||||
|
@ -1504,6 +1627,10 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
|
|||
features->last_slot_field = usage->hid;
|
||||
wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
|
||||
break;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
wacom_wac->hid_data.cc_index = field->index;
|
||||
wacom_wac->hid_data.cc_value_index = usage->usage_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1515,6 +1642,10 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
|
|||
bool prox = hid_data->tipswitch &&
|
||||
!wacom_wac->shared->stylus_in_proximity;
|
||||
|
||||
wacom_wac->hid_data.num_received++;
|
||||
if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected)
|
||||
return;
|
||||
|
||||
if (mt) {
|
||||
int slot;
|
||||
|
||||
|
@ -1531,6 +1662,13 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
|
|||
hid_data->x);
|
||||
input_report_abs(input, mt ? ABS_MT_POSITION_Y : ABS_Y,
|
||||
hid_data->y);
|
||||
|
||||
if (test_bit(ABS_MT_TOUCH_MAJOR, input->absbit)) {
|
||||
input_report_abs(input, ABS_MT_TOUCH_MAJOR, max(hid_data->width, hid_data->height));
|
||||
input_report_abs(input, ABS_MT_TOUCH_MINOR, min(hid_data->width, hid_data->height));
|
||||
if (hid_data->width != hid_data->height)
|
||||
input_report_abs(input, ABS_MT_ORIENTATION, hid_data->width <= hid_data->height ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1547,6 +1685,12 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
|
|||
case HID_GD_Y:
|
||||
wacom_wac->hid_data.y = value;
|
||||
break;
|
||||
case HID_DG_WIDTH:
|
||||
wacom_wac->hid_data.width = value;
|
||||
break;
|
||||
case HID_DG_HEIGHT:
|
||||
wacom_wac->hid_data.height = value;
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
wacom_wac->hid_data.id = value;
|
||||
break;
|
||||
|
@ -1564,6 +1708,24 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wacom_wac_finger_pre_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct hid_data* hid_data = &wacom_wac->hid_data;
|
||||
|
||||
if (hid_data->cc_index >= 0) {
|
||||
struct hid_field *field = report->field[hid_data->cc_index];
|
||||
int value = field->value[hid_data->cc_value_index];
|
||||
if (value)
|
||||
hid_data->num_expected = value;
|
||||
}
|
||||
else {
|
||||
hid_data->num_expected = wacom_wac->features.touch_max;
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_finger_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
|
@ -1572,10 +1734,18 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
|
|||
struct input_dev *input = wacom_wac->touch_input;
|
||||
unsigned touch_max = wacom_wac->features.touch_max;
|
||||
|
||||
/* If more packets of data are expected, give us a chance to
|
||||
* process them rather than immediately syncing a partial
|
||||
* update.
|
||||
*/
|
||||
if (wacom_wac->hid_data.num_received < wacom_wac->hid_data.num_expected)
|
||||
return;
|
||||
|
||||
if (touch_max > 1)
|
||||
input_mt_sync_frame(input);
|
||||
|
||||
input_sync(input);
|
||||
wacom_wac->hid_data.num_received = 0;
|
||||
|
||||
/* keep touch state for pen event */
|
||||
wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
|
||||
|
@ -1615,6 +1785,25 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wacom_report_events(struct hid_device *hdev, struct hid_report *report)
|
||||
{
|
||||
int r;
|
||||
|
||||
for (r = 0; r < report->maxfield; r++) {
|
||||
struct hid_field *field;
|
||||
unsigned count, n;
|
||||
|
||||
field = report->field[r];
|
||||
count = field->report_count;
|
||||
|
||||
if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
|
||||
continue;
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
wacom_wac_event(hdev, field, &field->usage[n], field->value[n]);
|
||||
}
|
||||
}
|
||||
|
||||
void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
|
@ -1624,6 +1813,14 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
|||
if (wacom_wac->features.type != HID_GENERIC)
|
||||
return;
|
||||
|
||||
if (WACOM_PEN_FIELD(field))
|
||||
wacom_wac_pen_pre_report(hdev, report);
|
||||
|
||||
if (WACOM_FINGER_FIELD(field))
|
||||
wacom_wac_finger_pre_report(hdev, report);
|
||||
|
||||
wacom_report_events(hdev, report);
|
||||
|
||||
if (WACOM_PEN_FIELD(field))
|
||||
return wacom_wac_pen_report(hdev, report);
|
||||
|
||||
|
@ -1699,7 +1896,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
|
|||
int y = (data[3] << 4) | (data[4] & 0x0f);
|
||||
int width, height;
|
||||
|
||||
if (features->type >= INTUOSPS && features->type <= INTUOSPL) {
|
||||
if (features->type >= INTUOSPS && features->type <= INTUOSHT) {
|
||||
width = data[5] * 100;
|
||||
height = data[6] * 100;
|
||||
} else {
|
||||
|
@ -2118,6 +2315,13 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
|||
sync = wacom_wireless_irq(wacom_wac, len);
|
||||
break;
|
||||
|
||||
case REMOTE:
|
||||
if (wacom_wac->data[0] == WACOM_REPORT_DEVICE_LIST)
|
||||
sync = wacom_remote_status_irq(wacom_wac, len);
|
||||
else
|
||||
sync = wacom_remote_irq(wacom_wac, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
sync = false;
|
||||
break;
|
||||
|
@ -2223,10 +2427,13 @@ void wacom_setup_device_quirks(struct wacom *wacom)
|
|||
* 0, whose HID descriptor has an application usage of 0xFF0D
|
||||
* (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
|
||||
* out through the HID_GENERIC device created for interface 1,
|
||||
* so rewrite this one to be of type BTN_TOOL_FINGER.
|
||||
* so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
|
||||
*/
|
||||
if (features->type == BAMBOO_PAD)
|
||||
features->device_type |= WACOM_DEVICETYPE_TOUCH;
|
||||
features->device_type = WACOM_DEVICETYPE_TOUCH;
|
||||
|
||||
if (features->type == REMOTE)
|
||||
features->device_type = WACOM_DEVICETYPE_PAD;
|
||||
|
||||
if (wacom->hdev->bus == BUS_BLUETOOTH)
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
|
@ -2242,13 +2449,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
|
|||
}
|
||||
|
||||
if (features->type == WIRELESS) {
|
||||
|
||||
/* monitor never has input and pen/touch have delayed create */
|
||||
features->quirks |= WACOM_QUIRK_NO_INPUT;
|
||||
|
||||
/* must be monitor interface if no device_type set */
|
||||
if (features->device_type == WACOM_DEVICETYPE_NONE) {
|
||||
features->quirks |= WACOM_QUIRK_MONITOR;
|
||||
if (features->device_type == WACOM_DEVICETYPE_WL_MONITOR) {
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
}
|
||||
}
|
||||
|
@ -2513,11 +2714,23 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
|
||||
int button_count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < button_count && i < 10; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
for (i = 10; i < button_count && i < 16; i++)
|
||||
__set_bit(BTN_A + (i-10), input_dev->keybit);
|
||||
for (i = 16; i < button_count && i < 18; i++)
|
||||
__set_bit(BTN_BASE + (i-16), input_dev->keybit);
|
||||
}
|
||||
|
||||
int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
||||
struct wacom_wac *wacom_wac)
|
||||
{
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
int i;
|
||||
|
||||
if (!(features->device_type & WACOM_DEVICETYPE_PAD))
|
||||
return -ENODEV;
|
||||
|
@ -2534,10 +2747,14 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
/* kept for making udev and libwacom accepting the pad */
|
||||
__set_bit(BTN_STYLUS, input_dev->keybit);
|
||||
|
||||
wacom_setup_numbered_buttons(input_dev, features->numbered_buttons);
|
||||
|
||||
switch (features->type) {
|
||||
|
||||
case CINTIQ_HYBRID:
|
||||
case DTK:
|
||||
case DTUS:
|
||||
case GRAPHIRE_BT:
|
||||
__set_bit(BTN_0, input_dev->keybit);
|
||||
__set_bit(BTN_1, input_dev->keybit);
|
||||
break;
|
||||
|
||||
case WACOM_MO:
|
||||
|
@ -2555,16 +2772,6 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
break;
|
||||
|
||||
case WACOM_24HD:
|
||||
__set_bit(BTN_A, input_dev->keybit);
|
||||
__set_bit(BTN_B, input_dev->keybit);
|
||||
__set_bit(BTN_C, input_dev->keybit);
|
||||
__set_bit(BTN_X, input_dev->keybit);
|
||||
__set_bit(BTN_Y, input_dev->keybit);
|
||||
__set_bit(BTN_Z, input_dev->keybit);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
__set_bit(KEY_PROG1, input_dev->keybit);
|
||||
__set_bit(KEY_PROG2, input_dev->keybit);
|
||||
__set_bit(KEY_PROG3, input_dev->keybit);
|
||||
|
@ -2586,12 +2793,6 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
__set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit);
|
||||
break;
|
||||
|
||||
case DTK:
|
||||
for (i = 0; i < 6; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
break;
|
||||
|
||||
case WACOM_22HD:
|
||||
__set_bit(KEY_PROG1, input_dev->keybit);
|
||||
__set_bit(KEY_PROG2, input_dev->keybit);
|
||||
|
@ -2599,52 +2800,22 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
/* fall through */
|
||||
|
||||
case WACOM_21UX2:
|
||||
__set_bit(BTN_A, input_dev->keybit);
|
||||
__set_bit(BTN_B, input_dev->keybit);
|
||||
__set_bit(BTN_C, input_dev->keybit);
|
||||
__set_bit(BTN_X, input_dev->keybit);
|
||||
__set_bit(BTN_Y, input_dev->keybit);
|
||||
__set_bit(BTN_Z, input_dev->keybit);
|
||||
__set_bit(BTN_BASE, input_dev->keybit);
|
||||
__set_bit(BTN_BASE2, input_dev->keybit);
|
||||
/* fall through */
|
||||
|
||||
case WACOM_BEE:
|
||||
__set_bit(BTN_8, input_dev->keybit);
|
||||
__set_bit(BTN_9, input_dev->keybit);
|
||||
/* fall through */
|
||||
|
||||
case CINTIQ:
|
||||
for (i = 0; i < 8; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
|
||||
break;
|
||||
|
||||
case WACOM_13HD:
|
||||
for (i = 0; i < 9; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
|
||||
break;
|
||||
|
||||
case INTUOS3:
|
||||
case INTUOS3L:
|
||||
__set_bit(BTN_4, input_dev->keybit);
|
||||
__set_bit(BTN_5, input_dev->keybit);
|
||||
__set_bit(BTN_6, input_dev->keybit);
|
||||
__set_bit(BTN_7, input_dev->keybit);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
|
||||
/* fall through */
|
||||
|
||||
case INTUOS3S:
|
||||
__set_bit(BTN_0, input_dev->keybit);
|
||||
__set_bit(BTN_1, input_dev->keybit);
|
||||
__set_bit(BTN_2, input_dev->keybit);
|
||||
__set_bit(BTN_3, input_dev->keybit);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
|
||||
break;
|
||||
|
||||
|
@ -2652,15 +2823,8 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
case INTUOS5L:
|
||||
case INTUOSPM:
|
||||
case INTUOSPL:
|
||||
__set_bit(BTN_7, input_dev->keybit);
|
||||
__set_bit(BTN_8, input_dev->keybit);
|
||||
/* fall through */
|
||||
|
||||
case INTUOS5S:
|
||||
case INTUOSPS:
|
||||
for (i = 0; i < 7; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
|
||||
break;
|
||||
|
||||
|
@ -2675,28 +2839,10 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
|
||||
case INTUOS4:
|
||||
case INTUOS4L:
|
||||
__set_bit(BTN_7, input_dev->keybit);
|
||||
__set_bit(BTN_8, input_dev->keybit);
|
||||
/* fall through */
|
||||
|
||||
case INTUOS4S:
|
||||
for (i = 0; i < 7; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
|
||||
break;
|
||||
|
||||
case CINTIQ_HYBRID:
|
||||
for (i = 0; i < 9; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
|
||||
break;
|
||||
|
||||
case DTUS:
|
||||
for (i = 0; i < 4; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
break;
|
||||
|
||||
case INTUOSHT:
|
||||
case BAMBOO_PT:
|
||||
__clear_bit(ABS_MISC, input_dev->absbit);
|
||||
|
@ -2708,6 +2854,11 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
|
||||
break;
|
||||
|
||||
case REMOTE:
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
|
||||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* no pad supported */
|
||||
return -ENODEV;
|
||||
|
@ -2723,7 +2874,7 @@ static const struct wacom_features wacom_features_0x10 =
|
|||
GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
|
||||
static const struct wacom_features wacom_features_0x81 =
|
||||
{ "Wacom Graphire BT", 16704, 12064, 511, 32,
|
||||
GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
|
||||
GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES, 2 };
|
||||
static const struct wacom_features wacom_features_0x11 =
|
||||
{ "Wacom Graphire2 4x5", 10206, 7422, 511, 63,
|
||||
GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
|
||||
|
@ -2849,77 +3000,77 @@ static const struct wacom_features wacom_features_0x45 =
|
|||
INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xB0 =
|
||||
{ "Wacom Intuos3 4x5", 25400, 20320, 1023, 63,
|
||||
INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 4 };
|
||||
static const struct wacom_features wacom_features_0xB1 =
|
||||
{ "Wacom Intuos3 6x8", 40640, 30480, 1023, 63,
|
||||
INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
|
||||
static const struct wacom_features wacom_features_0xB2 =
|
||||
{ "Wacom Intuos3 9x12", 60960, 45720, 1023, 63,
|
||||
INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
|
||||
static const struct wacom_features wacom_features_0xB3 =
|
||||
{ "Wacom Intuos3 12x12", 60960, 60960, 1023, 63,
|
||||
INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
|
||||
static const struct wacom_features wacom_features_0xB4 =
|
||||
{ "Wacom Intuos3 12x19", 97536, 60960, 1023, 63,
|
||||
INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
|
||||
static const struct wacom_features wacom_features_0xB5 =
|
||||
{ "Wacom Intuos3 6x11", 54204, 31750, 1023, 63,
|
||||
INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
|
||||
static const struct wacom_features wacom_features_0xB7 =
|
||||
{ "Wacom Intuos3 4x6", 31496, 19685, 1023, 63,
|
||||
INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 4 };
|
||||
static const struct wacom_features wacom_features_0xB8 =
|
||||
{ "Wacom Intuos4 4x6", 31496, 19685, 2047, 63,
|
||||
INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7 };
|
||||
static const struct wacom_features wacom_features_0xB9 =
|
||||
{ "Wacom Intuos4 6x9", 44704, 27940, 2047, 63,
|
||||
INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
|
||||
static const struct wacom_features wacom_features_0xBA =
|
||||
{ "Wacom Intuos4 8x13", 65024, 40640, 2047, 63,
|
||||
INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
|
||||
static const struct wacom_features wacom_features_0xBB =
|
||||
{ "Wacom Intuos4 12x19", 97536, 60960, 2047, 63,
|
||||
INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
|
||||
static const struct wacom_features wacom_features_0xBC =
|
||||
{ "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
|
||||
INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
|
||||
static const struct wacom_features wacom_features_0xBD =
|
||||
{ "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
|
||||
INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
|
||||
static const struct wacom_features wacom_features_0x26 =
|
||||
{ "Wacom Intuos5 touch S", 31496, 19685, 2047, 63,
|
||||
INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
|
||||
INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x27 =
|
||||
{ "Wacom Intuos5 touch M", 44704, 27940, 2047, 63,
|
||||
INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
|
||||
INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x28 =
|
||||
{ "Wacom Intuos5 touch L", 65024, 40640, 2047, 63,
|
||||
INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
|
||||
INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x29 =
|
||||
{ "Wacom Intuos5 S", 31496, 19685, 2047, 63,
|
||||
INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7 };
|
||||
static const struct wacom_features wacom_features_0x2A =
|
||||
{ "Wacom Intuos5 M", 44704, 27940, 2047, 63,
|
||||
INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
|
||||
static const struct wacom_features wacom_features_0x314 =
|
||||
{ "Wacom Intuos Pro S", 31496, 19685, 2047, 63,
|
||||
INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
|
||||
INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16,
|
||||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0x315 =
|
||||
{ "Wacom Intuos Pro M", 44704, 27940, 2047, 63,
|
||||
INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
|
||||
INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
|
||||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0x317 =
|
||||
{ "Wacom Intuos Pro L", 65024, 40640, 2047, 63,
|
||||
INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
|
||||
INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
|
||||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0xF4 =
|
||||
{ "Wacom Cintiq 24HD", 104080, 65200, 2047, 63,
|
||||
WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
|
||||
static const struct wacom_features wacom_features_0xF8 =
|
||||
{ "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */
|
||||
WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
|
||||
static const struct wacom_features wacom_features_0xF6 =
|
||||
|
@ -2928,11 +3079,11 @@ static const struct wacom_features wacom_features_0xF6 =
|
|||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0x32A =
|
||||
{ "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63,
|
||||
WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
|
||||
static const struct wacom_features wacom_features_0x32B =
|
||||
{ "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
|
||||
WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
|
||||
static const struct wacom_features wacom_features_0x32C =
|
||||
|
@ -2940,20 +3091,20 @@ static const struct wacom_features wacom_features_0x32C =
|
|||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32B, .touch_max = 10 };
|
||||
static const struct wacom_features wacom_features_0x3F =
|
||||
{ "Wacom Cintiq 21UX", 87200, 65600, 1023, 63,
|
||||
CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
|
||||
static const struct wacom_features wacom_features_0xC5 =
|
||||
{ "Wacom Cintiq 20WSX", 86680, 54180, 1023, 63,
|
||||
WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
|
||||
static const struct wacom_features wacom_features_0xC6 =
|
||||
{ "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
|
||||
WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
|
||||
static const struct wacom_features wacom_features_0x304 =
|
||||
{ "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
|
||||
WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
|
||||
static const struct wacom_features wacom_features_0x333 =
|
||||
{ "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
|
||||
WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
|
||||
static const struct wacom_features wacom_features_0x335 =
|
||||
|
@ -2972,22 +3123,22 @@ static const struct wacom_features wacom_features_0xF0 =
|
|||
DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xFB =
|
||||
{ "Wacom DTU1031", 21896, 13760, 511, 0,
|
||||
DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
|
||||
WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
|
||||
static const struct wacom_features wacom_features_0x32F =
|
||||
{ "Wacom DTU1031X", 22472, 12728, 511, 0,
|
||||
DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0,
|
||||
WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
|
||||
static const struct wacom_features wacom_features_0x336 =
|
||||
{ "Wacom DTU1141", 23472, 13203, 1023, 0,
|
||||
DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
|
||||
static const struct wacom_features wacom_features_0x57 =
|
||||
{ "Wacom DTK2241", 95640, 54060, 2047, 63,
|
||||
DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
|
||||
static const struct wacom_features wacom_features_0x59 = /* Pen */
|
||||
{ "Wacom DTH2242", 95640, 54060, 2047, 63,
|
||||
DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
|
||||
static const struct wacom_features wacom_features_0x5D = /* Touch */
|
||||
|
@ -2996,15 +3147,15 @@ static const struct wacom_features wacom_features_0x5D = /* Touch */
|
|||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0xCC =
|
||||
{ "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63,
|
||||
WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
|
||||
static const struct wacom_features wacom_features_0xFA =
|
||||
{ "Wacom Cintiq 22HD", 95440, 53860, 2047, 63,
|
||||
WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
|
||||
static const struct wacom_features wacom_features_0x5B =
|
||||
{ "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63,
|
||||
WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
|
||||
static const struct wacom_features wacom_features_0x5E =
|
||||
|
@ -3151,7 +3302,7 @@ static const struct wacom_features wacom_features_0x6004 =
|
|||
TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0x307 =
|
||||
{ "Wacom ISDv5 307", 59152, 33448, 2047, 63,
|
||||
CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
|
||||
static const struct wacom_features wacom_features_0x309 =
|
||||
|
@ -3160,7 +3311,7 @@ static const struct wacom_features wacom_features_0x309 =
|
|||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0x30A =
|
||||
{ "Wacom ISDv5 30A", 59152, 33448, 2047, 63,
|
||||
CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
|
||||
WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
|
||||
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
|
||||
static const struct wacom_features wacom_features_0x30C =
|
||||
|
@ -3177,6 +3328,10 @@ static const struct wacom_features wacom_features_0x323 =
|
|||
{ "Wacom Intuos P M", 21600, 13500, 1023, 31,
|
||||
INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
||||
static const struct wacom_features wacom_features_0x331 =
|
||||
{ "Wacom Express Key Remote", 0, 0, 0, 0,
|
||||
REMOTE, 0, 0, 18, .check_for_hid_type = true,
|
||||
.hid_type = HID_TYPE_USBNONE };
|
||||
|
||||
static const struct wacom_features wacom_features_HID_ANY_ID =
|
||||
{ "Wacom HID", .type = HID_GENERIC };
|
||||
|
@ -3332,6 +3487,7 @@ const struct hid_device_id wacom_ids[] = {
|
|||
{ USB_DEVICE_WACOM(0x32B) },
|
||||
{ USB_DEVICE_WACOM(0x32C) },
|
||||
{ USB_DEVICE_WACOM(0x32F) },
|
||||
{ USB_DEVICE_WACOM(0x331) },
|
||||
{ USB_DEVICE_WACOM(0x333) },
|
||||
{ USB_DEVICE_WACOM(0x335) },
|
||||
{ USB_DEVICE_WACOM(0x336) },
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define WACOM_PKGLEN_MAX 192
|
||||
|
||||
#define WACOM_NAME_MAX 64
|
||||
#define WACOM_MAX_REMOTES 5
|
||||
#define WACOM_STATUS_UNKNOWN 255
|
||||
|
||||
/* packet length for individual models */
|
||||
#define WACOM_PKGLEN_BBFUN 9
|
||||
|
@ -65,11 +67,11 @@
|
|||
#define WACOM_REPORT_USB 192
|
||||
#define WACOM_REPORT_BPAD_PEN 3
|
||||
#define WACOM_REPORT_BPAD_TOUCH 16
|
||||
#define WACOM_REPORT_DEVICE_LIST 16
|
||||
#define WACOM_REPORT_REMOTE 17
|
||||
|
||||
/* device quirks */
|
||||
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001
|
||||
#define WACOM_QUIRK_NO_INPUT 0x0002
|
||||
#define WACOM_QUIRK_MONITOR 0x0004
|
||||
#define WACOM_QUIRK_BATTERY 0x0008
|
||||
|
||||
/* device types */
|
||||
|
@ -77,6 +79,7 @@
|
|||
#define WACOM_DEVICETYPE_PEN 0x0001
|
||||
#define WACOM_DEVICETYPE_TOUCH 0x0002
|
||||
#define WACOM_DEVICETYPE_PAD 0x0004
|
||||
#define WACOM_DEVICETYPE_WL_MONITOR 0x0008
|
||||
|
||||
#define WACOM_VENDORDEFINED_PEN 0xff0d0001
|
||||
|
||||
|
@ -130,6 +133,7 @@ enum {
|
|||
WACOM_24HDT,
|
||||
WACOM_27QHDT,
|
||||
BAMBOO_PAD,
|
||||
REMOTE,
|
||||
TABLETPC, /* add new TPC below */
|
||||
TABLETPCE,
|
||||
TABLETPC2FG,
|
||||
|
@ -149,6 +153,7 @@ struct wacom_features {
|
|||
int type;
|
||||
int x_resolution;
|
||||
int y_resolution;
|
||||
int numbered_buttons;
|
||||
int x_min;
|
||||
int y_min;
|
||||
int device_type;
|
||||
|
@ -193,6 +198,10 @@ struct hid_data {
|
|||
int width;
|
||||
int height;
|
||||
int id;
|
||||
int cc_index;
|
||||
int cc_value_index;
|
||||
int num_expected;
|
||||
int num_received;
|
||||
};
|
||||
|
||||
struct wacom_wac {
|
||||
|
@ -204,7 +213,7 @@ struct wacom_wac {
|
|||
unsigned char data[WACOM_PKGLEN_MAX];
|
||||
int tool[2];
|
||||
int id[2];
|
||||
__u32 serial[2];
|
||||
__u32 serial[5];
|
||||
bool reporting_data;
|
||||
struct wacom_features features;
|
||||
struct wacom_shared *shared;
|
||||
|
|
Loading…
Reference in New Issue