summaryrefslogtreecommitdiffstats
path: root/drivers/hid/wacom_wac.c
diff options
context:
space:
mode:
authorAaron Skomra2015-08-21 01:05:17 +0200
committerJiri Kosina2015-08-28 20:43:20 +0200
commit72b236d60218fe211a8e1210be31c31e81684b86 (patch)
tree4efe8829d583489d482daf98238bb6fd268f4199 /drivers/hid/wacom_wac.c
parentHID: wacom: Set button bits based on a new numbered_buttons (diff)
downloadkernel-qcow2-linux-72b236d60218fe211a8e1210be31c31e81684b86.tar.gz
kernel-qcow2-linux-72b236d60218fe211a8e1210be31c31e81684b86.tar.xz
kernel-qcow2-linux-72b236d60218fe211a8e1210be31c31e81684b86.zip
HID: wacom: Add support for Express Key Remote.
This device is pad (buttons) only, there is no stylus or touch. Up to five remotes can pair with the device's associated USB dongle. Signed-off-by: Aaron Skomra <aaron.skomra@wacom.com> Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/wacom_wac.c')
-rw-r--r--drivers/hid/wacom_wac.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index ee5d278afa3f..391a68731fe3 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -631,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;
@@ -2191,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;
@@ -2298,6 +2429,9 @@ void wacom_setup_device_quirks(struct wacom *wacom)
if (features->type == BAMBOO_PAD)
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;
@@ -2717,6 +2851,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;
@@ -3186,6 +3325,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 };
@@ -3341,6 +3484,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) },