summaryrefslogtreecommitdiff
path: root/drivers/hid/wacom_wac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/wacom_wac.c')
-rw-r--r--drivers/hid/wacom_wac.c406
1 files changed, 275 insertions, 131 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index bbe32d66e500..fa54d3290659 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -45,6 +45,27 @@ static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
*/
static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
+static void wacom_notify_battery(struct wacom_wac *wacom_wac,
+ int bat_capacity, bool bat_charging, bool bat_connected,
+ bool ps_connected)
+{
+ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+ bool changed = wacom_wac->battery_capacity != bat_capacity ||
+ wacom_wac->bat_charging != bat_charging ||
+ wacom_wac->bat_connected != bat_connected ||
+ wacom_wac->ps_connected != ps_connected;
+
+ if (changed) {
+ wacom_wac->battery_capacity = bat_capacity;
+ wacom_wac->bat_charging = bat_charging;
+ wacom_wac->bat_connected = bat_connected;
+ wacom_wac->ps_connected = ps_connected;
+
+ if (wacom->battery)
+ power_supply_changed(wacom->battery);
+ }
+}
+
static int wacom_penpartner_irq(struct wacom_wac *wacom)
{
unsigned char *data = wacom->data;
@@ -419,17 +440,26 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
rw = (data[7] >> 2 & 0x07);
battery_capacity = batcap_gr[rw];
ps_connected = rw == 7;
- if ((wacom->battery_capacity != battery_capacity) ||
- (wacom->ps_connected != ps_connected)) {
- wacom->battery_capacity = battery_capacity;
- wacom->ps_connected = ps_connected;
- wacom_notify_battery(wacom);
- }
+ wacom_notify_battery(wacom, battery_capacity, ps_connected,
+ 1, ps_connected);
}
exit:
return retval;
}
+static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
+{
+ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+ struct hid_report *r;
+ struct hid_report_enum *re;
+
+ re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
+ r = re->report_id_hash[WACOM_REPORT_INTUOSREAD];
+ if (r) {
+ hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
+ }
+}
+
static int wacom_intuos_inout(struct wacom_wac *wacom)
{
struct wacom_features *features = &wacom->features;
@@ -551,12 +581,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
(features->type == CINTIQ && !(data[1] & 0x40)))
return 1;
- if (wacom->shared) {
- wacom->shared->stylus_in_proximity = true;
-
- if (wacom->shared->touch_down)
- return 1;
- }
+ wacom->shared->stylus_in_proximity = true;
+ if (wacom->shared->touch_down)
+ return 1;
/* in Range while exiting */
if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
@@ -568,8 +595,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
- if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
- wacom->shared->stylus_in_proximity = false;
+ wacom->shared->stylus_in_proximity = false;
wacom->reporting_data = false;
/* don't report exit if we don't know the ID */
@@ -610,8 +636,11 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
}
/* don't report other events if we don't know the ID */
- if (!wacom->id[idx])
+ if (!wacom->id[idx]) {
+ /* but reschedule a read of the current tool */
+ wacom_intuos_schedule_prox_event(wacom);
return 1;
+ }
return 0;
}
@@ -1023,15 +1052,9 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
bat_charging = (power_raw & 0x08) ? 1 : 0;
ps_connected = (power_raw & 0x10) ? 1 : 0;
battery_capacity = batcap_i4[power_raw & 0x07];
- if ((wacom->battery_capacity != battery_capacity) ||
- (wacom->bat_charging != bat_charging) ||
- (wacom->ps_connected != ps_connected)) {
- wacom->battery_capacity = battery_capacity;
- wacom->bat_charging = bat_charging;
- wacom->ps_connected = ps_connected;
- wacom_notify_battery(wacom);
- }
-
+ wacom_notify_battery(wacom, battery_capacity, bat_charging,
+ battery_capacity || bat_charging,
+ ps_connected);
break;
default:
dev_dbg(wacom->input->dev.parent,
@@ -1042,6 +1065,28 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
return 0;
}
+static int wacom_wac_finger_count_touches(struct wacom_wac *wacom)
+{
+ struct input_dev *input = wacom->input;
+ unsigned touch_max = wacom->features.touch_max;
+ int count = 0;
+ int i;
+
+ /* non-HID_GENERIC single touch input doesn't call this routine */
+ if ((touch_max == 1) && (wacom->features.type == HID_GENERIC))
+ return wacom->hid_data.tipswitch &&
+ !wacom->shared->stylus_in_proximity;
+
+ for (i = 0; i < input->mt->num_slots; i++) {
+ struct input_mt_slot *ps = &input->mt->slots[i];
+ int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
+ if (id >= 0)
+ count++;
+ }
+
+ return count;
+}
+
static int wacom_24hdt_irq(struct wacom_wac *wacom)
{
struct input_dev *input = wacom->input;
@@ -1052,7 +1097,6 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
int num_contacts_left = 4; /* maximum contacts per packet */
int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
int y_offset = 2;
- static int contact_with_no_pen_down_count = 0;
if (wacom->features.type == WACOM_27QHDT) {
current_num_contacts = data[63];
@@ -1065,10 +1109,8 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
* First packet resets the counter since only the first
* packet in series will have non-zero current_num_contacts.
*/
- if (current_num_contacts) {
+ if (current_num_contacts)
wacom->num_contacts_left = current_num_contacts;
- contact_with_no_pen_down_count = 0;
- }
contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
@@ -1101,15 +1143,14 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
input_report_abs(input, ABS_MT_ORIENTATION, w > h);
}
- contact_with_no_pen_down_count++;
}
}
- input_mt_report_pointer_emulation(input, true);
+ input_mt_sync_frame(input);
wacom->num_contacts_left -= contacts_to_send;
if (wacom->num_contacts_left <= 0) {
wacom->num_contacts_left = 0;
- wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+ wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
}
return 1;
}
@@ -1122,7 +1163,6 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
int current_num_contacts = data[2];
int contacts_to_send = 0;
int x_offset = 0;
- static int contact_with_no_pen_down_count = 0;
/* MTTPC does not support Height and Width */
if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
@@ -1132,10 +1172,8 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
* First packet resets the counter since only the first
* packet in series will have non-zero current_num_contacts.
*/
- if (current_num_contacts) {
+ if (current_num_contacts)
wacom->num_contacts_left = current_num_contacts;
- contact_with_no_pen_down_count = 0;
- }
/* There are at most 5 contacts per packet */
contacts_to_send = min(5, wacom->num_contacts_left);
@@ -1156,15 +1194,14 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
int y = get_unaligned_le16(&data[offset + x_offset + 9]);
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
- contact_with_no_pen_down_count++;
}
}
- input_mt_report_pointer_emulation(input, true);
+ input_mt_sync_frame(input);
wacom->num_contacts_left -= contacts_to_send;
if (wacom->num_contacts_left <= 0) {
wacom->num_contacts_left = 0;
- wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+ wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
}
return 1;
}
@@ -1173,7 +1210,6 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
{
struct input_dev *input = wacom->input;
unsigned char *data = wacom->data;
- int contact_with_no_pen_down_count = 0;
int i;
for (i = 0; i < 2; i++) {
@@ -1188,13 +1224,12 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
- contact_with_no_pen_down_count++;
}
}
- input_mt_report_pointer_emulation(input, true);
+ input_mt_sync_frame(input);
/* keep touch state for pen event */
- wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+ wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
return 1;
}
@@ -1522,29 +1557,6 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
return 0;
}
-static int wacom_wac_finger_count_touches(struct hid_device *hdev)
-{
- struct wacom *wacom = hid_get_drvdata(hdev);
- struct wacom_wac *wacom_wac = &wacom->wacom_wac;
- struct input_dev *input = wacom_wac->input;
- unsigned touch_max = wacom_wac->features.touch_max;
- int count = 0;
- int i;
-
- if (touch_max == 1)
- return wacom_wac->hid_data.tipswitch &&
- !wacom_wac->shared->stylus_in_proximity;
-
- for (i = 0; i < input->mt->num_slots; i++) {
- struct input_mt_slot *ps = &input->mt->slots[i];
- int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
- if (id >= 0)
- count++;
- }
-
- return count;
-}
-
static void wacom_wac_finger_report(struct hid_device *hdev,
struct hid_report *report)
{
@@ -1559,7 +1571,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
input_sync(input);
/* keep touch state for pen event */
- wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev);
+ wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
}
void wacom_wac_usage_mapping(struct hid_device *hdev,
@@ -1619,7 +1631,6 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
struct input_dev *pad_input = wacom->pad_input;
unsigned char *data = wacom->data;
int i;
- int contact_with_no_pen_down_count = 0;
if (data[0] != 0x02)
return 0;
@@ -1647,22 +1658,21 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
}
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
- contact_with_no_pen_down_count++;
}
}
- input_mt_report_pointer_emulation(input, true);
+ input_mt_sync_frame(input);
input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0);
input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
- wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+ wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
return 1;
}
-static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, int last_touch_count)
+static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
{
struct wacom_features *features = &wacom->features;
struct input_dev *input = wacom->input;
@@ -1670,7 +1680,7 @@ static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, in
int slot = input_mt_get_slot_by_key(input, data[0]);
if (slot < 0)
- return 0;
+ return;
touch = touch && !wacom->shared->stylus_in_proximity;
@@ -1702,9 +1712,7 @@ static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, in
input_report_abs(input, ABS_MT_POSITION_Y, y);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
- last_touch_count++;
}
- return last_touch_count;
}
static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
@@ -1729,7 +1737,6 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
unsigned char *data = wacom->data;
int count = data[1] & 0x07;
int i;
- int contact_with_no_pen_down_count = 0;
if (data[0] != 0x02)
return 0;
@@ -1740,15 +1747,13 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
int msg_id = data[offset];
if (msg_id >= 2 && msg_id <= 17)
- contact_with_no_pen_down_count =
- wacom_bpt3_touch_msg(wacom, data + offset,
- contact_with_no_pen_down_count);
+ wacom_bpt3_touch_msg(wacom, data + offset);
else if (msg_id == 128)
wacom_bpt3_button_msg(wacom, data + offset);
}
- input_mt_report_pointer_emulation(input, true);
- wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+ input_mt_sync_frame(input);
+ wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
return 1;
}
@@ -1760,23 +1765,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
unsigned char *data = wacom->data;
int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
- if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB)
+ if (data[0] != WACOM_REPORT_PENABLED)
return 0;
- if (data[0] == WACOM_REPORT_USB) {
- if (features->type == INTUOSHT &&
- wacom->shared->touch_input &&
- features->touch_max) {
- input_report_switch(wacom->shared->touch_input,
- SW_MUTE_DEVICE, data[8] & 0x40);
- input_sync(wacom->shared->touch_input);
- }
- return 0;
- }
-
- if (wacom->shared->touch_down)
- return 0;
-
prox = (data[1] & 0x20) == 0x20;
/*
@@ -1789,17 +1780,21 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
*
* Hardware does report zero in most out-of-prox cases but not all.
*/
- if (prox) {
- if (!wacom->shared->stylus_in_proximity) {
- if (data[1] & 0x08) {
- wacom->tool[0] = BTN_TOOL_RUBBER;
- wacom->id[0] = ERASER_DEVICE_ID;
- } else {
- wacom->tool[0] = BTN_TOOL_PEN;
- wacom->id[0] = STYLUS_DEVICE_ID;
- }
- wacom->shared->stylus_in_proximity = true;
+ if (!wacom->shared->stylus_in_proximity) {
+ if (data[1] & 0x08) {
+ wacom->tool[0] = BTN_TOOL_RUBBER;
+ wacom->id[0] = ERASER_DEVICE_ID;
+ } else {
+ wacom->tool[0] = BTN_TOOL_PEN;
+ wacom->id[0] = STYLUS_DEVICE_ID;
}
+ }
+
+ wacom->shared->stylus_in_proximity = prox;
+ if (wacom->shared->touch_down)
+ return 0;
+
+ if (prox) {
x = le16_to_cpup((__le16 *)&data[2]);
y = le16_to_cpup((__le16 *)&data[4]);
p = le16_to_cpup((__le16 *)&data[6]);
@@ -1815,6 +1810,8 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
pen = data[1] & 0x01;
btn1 = data[1] & 0x02;
btn2 = data[1] & 0x04;
+ } else {
+ wacom->id[0] = 0;
}
input_report_key(input, BTN_TOUCH, pen);
@@ -1826,11 +1823,6 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
input_report_abs(input, ABS_PRESSURE, p);
input_report_abs(input, ABS_DISTANCE, d);
- if (!prox) {
- wacom->id[0] = 0;
- wacom->shared->stylus_in_proximity = false;
- }
-
input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
@@ -1849,6 +1841,91 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
return 0;
}
+static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
+ unsigned char *data)
+{
+ unsigned char prefix;
+
+ /*
+ * We need to reroute the event from the debug interface to the
+ * pen interface.
+ * We need to add the report ID to the actual pen report, so we
+ * temporary overwrite the first byte to prevent having to kzalloc/kfree
+ * and memcpy the report.
+ */
+ prefix = data[0];
+ data[0] = WACOM_REPORT_BPAD_PEN;
+
+ /*
+ * actually reroute the event.
+ * No need to check if wacom->shared->pen is valid, hid_input_report()
+ * will check for us.
+ */
+ hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
+ WACOM_PKGLEN_PENABLED, 1);
+
+ data[0] = prefix;
+}
+
+static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom,
+ unsigned char *data)
+{
+ struct input_dev *input = wacom->input;
+ unsigned char *finger_data, prefix;
+ unsigned id;
+ int x, y;
+ bool valid;
+
+ prefix = data[0];
+
+ for (id = 0; id < wacom->features.touch_max; id++) {
+ valid = !!(prefix & BIT(id)) &&
+ !wacom->shared->stylus_in_proximity;
+
+ input_mt_slot(input, id);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, valid);
+
+ if (!valid)
+ continue;
+
+ finger_data = data + 1 + id * 3;
+ x = finger_data[0] | ((finger_data[1] & 0x0f) << 8);
+ y = (finger_data[2] << 4) | (finger_data[1] >> 4);
+
+ input_report_abs(input, ABS_MT_POSITION_X, x);
+ input_report_abs(input, ABS_MT_POSITION_Y, y);
+ }
+
+ input_mt_sync_frame(input);
+
+ input_report_key(input, BTN_LEFT, prefix & 0x40);
+ input_report_key(input, BTN_RIGHT, prefix & 0x80);
+
+ /* keep touch state for pen event */
+ wacom->shared->touch_down = !!prefix &&
+ !wacom->shared->stylus_in_proximity;
+
+ return 1;
+}
+
+static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len)
+{
+ unsigned char *data = wacom->data;
+
+ if (!((len == WACOM_PKGLEN_BPAD_TOUCH) ||
+ (len == WACOM_PKGLEN_BPAD_TOUCH_USB)) ||
+ (data[0] != WACOM_REPORT_BPAD_TOUCH))
+ return 0;
+
+ if (data[1] & 0x01)
+ wacom_bamboo_pad_pen_event(wacom, &data[1]);
+
+ if (data[1] & 0x02)
+ return wacom_bamboo_pad_touch_event(wacom, &data[9]);
+
+ return 0;
+}
+
static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
{
unsigned char *data = wacom->data;
@@ -1859,7 +1936,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
connected = data[1] & 0x01;
if (connected) {
- int pid, battery, ps_connected;
+ int pid, battery, charging;
if ((wacom->shared->type == INTUOSHT) &&
wacom->shared->touch_input &&
@@ -1871,30 +1948,63 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
pid = get_unaligned_be16(&data[6]);
battery = (data[5] & 0x3f) * 100 / 31;
- ps_connected = !!(data[5] & 0x80);
+ charging = !!(data[5] & 0x80);
if (wacom->pid != pid) {
wacom->pid = pid;
wacom_schedule_work(wacom);
}
- if (wacom->shared->type &&
- (battery != wacom->battery_capacity ||
- ps_connected != wacom->ps_connected)) {
- wacom->battery_capacity = battery;
- wacom->ps_connected = ps_connected;
- wacom->bat_charging = ps_connected &&
- wacom->battery_capacity < 100;
- wacom_notify_battery(wacom);
- }
+ if (wacom->shared->type)
+ wacom_notify_battery(wacom, battery, charging, 1, 0);
+
} else if (wacom->pid != 0) {
/* disconnected while previously connected */
wacom->pid = 0;
wacom_schedule_work(wacom);
- wacom->battery_capacity = 0;
- wacom->bat_charging = 0;
- wacom->ps_connected = 0;
+ wacom_notify_battery(wacom, 0, 0, 0, 0);
+ }
+
+ return 0;
+}
+
+static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
+{
+ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+ struct wacom_features *features = &wacom_wac->features;
+ unsigned char *data = wacom_wac->data;
+
+ if (data[0] != WACOM_REPORT_USB)
+ return 0;
+
+ if (features->type == INTUOSHT &&
+ wacom_wac->shared->touch_input &&
+ features->touch_max) {
+ input_report_switch(wacom_wac->shared->touch_input,
+ SW_MUTE_DEVICE, data[8] & 0x40);
+ input_sync(wacom_wac->shared->touch_input);
}
+ if (data[9] & 0x02) { /* wireless module is attached */
+ int battery = (data[8] & 0x3f) * 100 / 31;
+ bool charging = !!(data[8] & 0x80);
+
+ wacom_notify_battery(wacom_wac, battery, charging,
+ battery || charging, 1);
+
+ 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);
+ }
+ }
+ else if ((features->quirks & WACOM_QUIRK_BATTERY) &&
+ wacom->battery) {
+ features->quirks &= ~WACOM_QUIRK_BATTERY;
+ INIT_WORK(&wacom->work, wacom_battery_work);
+ wacom_schedule_work(wacom_wac);
+ wacom_notify_battery(wacom_wac, 0, 0, 0, 0);
+ }
return 0;
}
@@ -1967,6 +2077,8 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case INTUOSPL:
if (len == WACOM_PKGLEN_BBTOUCH3)
sync = wacom_bpt3_touch(wacom_wac);
+ else if (wacom_wac->data[0] == WACOM_REPORT_USB)
+ sync = wacom_status_irq(wacom_wac, len);
else
sync = wacom_intuos_irq(wacom_wac);
break;
@@ -1982,7 +2094,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case BAMBOO_PT:
case INTUOSHT:
- sync = wacom_bpt_irq(wacom_wac, len);
+ if (wacom_wac->data[0] == WACOM_REPORT_USB)
+ sync = wacom_status_irq(wacom_wac, len);
+ else
+ sync = wacom_bpt_irq(wacom_wac, len);
+ break;
+
+ case BAMBOO_PAD:
+ sync = wacom_bamboo_pad_irq(wacom_wac, len);
break;
case WIRELESS:
@@ -2054,12 +2173,6 @@ void wacom_setup_device_quirks(struct wacom_features *features)
features->y_max = 1023;
}
- /* these device have multiple inputs */
- if (features->type >= WIRELESS ||
- (features->type >= INTUOS5S && features->type <= INTUOSHT) ||
- (features->oVid && features->oPid))
- features->quirks |= WACOM_QUIRK_MULTI_INPUT;
-
/* quirk for bamboo touch with 2 low res touches */
if (features->type == BAMBOO_PT &&
features->pktlen == WACOM_PKGLEN_BBTOUCH) {
@@ -2323,6 +2436,13 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
0, 0);
}
break;
+ case BAMBOO_PAD:
+ __clear_bit(ABS_MISC, input_dev->absbit);
+ input_mt_init_slots(input_dev, features->touch_max,
+ INPUT_MT_POINTER);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ break;
}
return 0;
}
@@ -2772,6 +2892,15 @@ static const struct wacom_features wacom_features_0x304 =
{ "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
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_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
+static const struct wacom_features wacom_features_0x335 =
+ { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x333, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0xC7 =
{ "Wacom DTU1931", 37832, 30305, 511, 0,
PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2976,6 +3105,12 @@ static const struct wacom_features wacom_features_0x30C =
{ "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x318 =
+ { "Wacom USB Bamboo PAD", 4095, 4095, /* Touch */
+ .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
+static const struct wacom_features wacom_features_0x319 =
+ { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
+ .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
static const struct wacom_features wacom_features_0x323 =
{ "Wacom Intuos P M", 21600, 13500, 1023, 31,
INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
@@ -2992,6 +3127,10 @@ static const struct wacom_features wacom_features_HID_ANY_ID =
HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
.driver_data = (kernel_ulong_t)&wacom_features_##prod
+#define I2C_DEVICE_WACOM(prod) \
+ HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
+
#define USB_DEVICE_LENOVO(prod) \
HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
.driver_data = (kernel_ulong_t)&wacom_features_##prod
@@ -3124,11 +3263,15 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x314) },
{ USB_DEVICE_WACOM(0x315) },
{ USB_DEVICE_WACOM(0x317) },
+ { USB_DEVICE_WACOM(0x318) },
+ { USB_DEVICE_WACOM(0x319) },
{ USB_DEVICE_WACOM(0x323) },
{ USB_DEVICE_WACOM(0x32A) },
{ USB_DEVICE_WACOM(0x32B) },
{ USB_DEVICE_WACOM(0x32C) },
{ USB_DEVICE_WACOM(0x32F) },
+ { USB_DEVICE_WACOM(0x333) },
+ { USB_DEVICE_WACOM(0x335) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) },
@@ -3136,6 +3279,7 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_LENOVO(0x6004) },
{ USB_DEVICE_WACOM(HID_ANY_ID) },
+ { I2C_DEVICE_WACOM(HID_ANY_ID) },
{ }
};
MODULE_DEVICE_TABLE(hid, wacom_ids);