aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-07-24 15:48:28 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-07-25 21:53:46 -0400
commitd2d13f18aaa51af070c7b6f20606d5cfdb7e87c1 (patch)
treef70adf9beca587ed536a95565fe6cc186c2f8b29
parent7097d4cb597d1d9fe5296082cc3f191db44ab349 (diff)
Input: wacom - create a separate input device for pads
Currently, the pad events are sent through the stylus input device for the Intuos/Cintiqs, and through the touch input device for the Bamboos. To differentiate the buttons pressed on the pad from the ones pressed on the stylus, the Intuos/Cintiq uses MISC_SERIAL and ABS_MISC. This lead to a multiplexing of the events into one device, which are then splitted out in xf86-input-wacom. Bamboos are not using MISC events because the pad is attached to the touch interface, and only BTN_TOUCH is used for the finger (and DOUBLE_TAP, etc...). However, the user space driver still splits out the pad from the touch interface in the same way it does for the pro line devices. The other problem we can see with this fact is that some of the Intuos and Cintiq have a wheel, and the effective range of the reported values is [0..71]. Unfortunately, the airbrush stylus also sends wheel events (there is a small wheel on it), but in the range [0..1023]. From the user space point of view it is kind of difficult to understand that because the wheel on the pad are quite common, while the airbrush tool is not. A solution to fix all of these problems is to split out the pad device from the stylus/touch. This decision makes more sense because the pad is not linked to the absolute position of the finger or pen, and usually, the events from the pad are filtered out by the compositor, which then convert them into actions or keyboard shortcuts. For backward compatibility with current xf86-input-wacom, the pad devices still present the ABS_X, ABS_Y and ABS_MISC events, but they can be completely ignored in the new implementation. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Reviewed-by: Ping Cheng <pingc@wacom.com> Reviewed-by: Jason Gerecke <killertofu@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/tablet/wacom.h2
-rw-r--r--drivers/input/tablet/wacom_sys.c63
-rw-r--r--drivers/input/tablet/wacom_wac.c27
-rw-r--r--drivers/input/tablet/wacom_wac.h2
4 files changed, 85 insertions, 9 deletions
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 9ebf0ed3b3b3..caa59cab2c5f 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -136,4 +136,6 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
136void wacom_setup_device_quirks(struct wacom_features *features); 136void wacom_setup_device_quirks(struct wacom_features *features);
137int wacom_setup_input_capabilities(struct input_dev *input_dev, 137int wacom_setup_input_capabilities(struct input_dev *input_dev,
138 struct wacom_wac *wacom_wac); 138 struct wacom_wac *wacom_wac);
139int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
140 struct wacom_wac *wacom_wac);
139#endif 141#endif
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 7cd0886cddd2..b25848581fc1 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -135,6 +135,9 @@ static int wacom_open(struct input_dev *dev)
135 135
136 mutex_lock(&wacom->lock); 136 mutex_lock(&wacom->lock);
137 137
138 if (wacom->open)
139 goto out;
140
138 if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { 141 if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
139 retval = -EIO; 142 retval = -EIO;
140 goto out; 143 goto out;
@@ -157,9 +160,14 @@ static void wacom_close(struct input_dev *dev)
157 autopm_error = usb_autopm_get_interface(wacom->intf); 160 autopm_error = usb_autopm_get_interface(wacom->intf);
158 161
159 mutex_lock(&wacom->lock); 162 mutex_lock(&wacom->lock);
163 if (!wacom->open)
164 goto out;
165
160 usb_kill_urb(wacom->irq); 166 usb_kill_urb(wacom->irq);
161 wacom->open = false; 167 wacom->open = false;
162 wacom->intf->needs_remote_wakeup = 0; 168 wacom->intf->needs_remote_wakeup = 0;
169
170out:
163 mutex_unlock(&wacom->lock); 171 mutex_unlock(&wacom->lock);
164 172
165 if (!autopm_error) 173 if (!autopm_error)
@@ -1112,19 +1120,16 @@ static void wacom_destroy_battery(struct wacom *wacom)
1112 } 1120 }
1113} 1121}
1114 1122
1115static int wacom_register_input(struct wacom *wacom) 1123static struct input_dev *wacom_allocate_input(struct wacom *wacom)
1116{ 1124{
1117 struct input_dev *input_dev; 1125 struct input_dev *input_dev;
1118 struct usb_interface *intf = wacom->intf; 1126 struct usb_interface *intf = wacom->intf;
1119 struct usb_device *dev = interface_to_usbdev(intf); 1127 struct usb_device *dev = interface_to_usbdev(intf);
1120 struct wacom_wac *wacom_wac = &(wacom->wacom_wac); 1128 struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
1121 int error;
1122 1129
1123 input_dev = input_allocate_device(); 1130 input_dev = input_allocate_device();
1124 if (!input_dev) { 1131 if (!input_dev)
1125 error = -ENOMEM; 1132 return NULL;
1126 goto fail1;
1127 }
1128 1133
1129 input_dev->name = wacom_wac->name; 1134 input_dev->name = wacom_wac->name;
1130 input_dev->phys = wacom->phys; 1135 input_dev->phys = wacom->phys;
@@ -1134,21 +1139,59 @@ static int wacom_register_input(struct wacom *wacom)
1134 usb_to_input_id(dev, &input_dev->id); 1139 usb_to_input_id(dev, &input_dev->id);
1135 input_set_drvdata(input_dev, wacom); 1140 input_set_drvdata(input_dev, wacom);
1136 1141
1142 return input_dev;
1143}
1144
1145static int wacom_register_input(struct wacom *wacom)
1146{
1147 struct input_dev *input_dev, *pad_input_dev;
1148 struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
1149 int error;
1150
1151 input_dev = wacom_allocate_input(wacom);
1152 pad_input_dev = wacom_allocate_input(wacom);
1153 if (!input_dev || !pad_input_dev) {
1154 error = -ENOMEM;
1155 goto fail1;
1156 }
1157
1137 wacom_wac->input = input_dev; 1158 wacom_wac->input = input_dev;
1159 wacom_wac->pad_input = pad_input_dev;
1160 wacom_wac->pad_input->name = wacom_wac->pad_name;
1161
1138 error = wacom_setup_input_capabilities(input_dev, wacom_wac); 1162 error = wacom_setup_input_capabilities(input_dev, wacom_wac);
1139 if (error) 1163 if (error)
1140 goto fail1; 1164 goto fail2;
1141 1165
1142 error = input_register_device(input_dev); 1166 error = input_register_device(input_dev);
1143 if (error) 1167 if (error)
1144 goto fail2; 1168 goto fail2;
1145 1169
1170 error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
1171 if (error) {
1172 /* no pad in use on this interface */
1173 input_free_device(pad_input_dev);
1174 wacom_wac->pad_input = NULL;
1175 pad_input_dev = NULL;
1176 } else {
1177 error = input_register_device(pad_input_dev);
1178 if (error)
1179 goto fail3;
1180 }
1181
1146 return 0; 1182 return 0;
1147 1183
1184fail3:
1185 input_unregister_device(input_dev);
1186 input_dev = NULL;
1148fail2: 1187fail2:
1149 input_free_device(input_dev);
1150 wacom_wac->input = NULL; 1188 wacom_wac->input = NULL;
1189 wacom_wac->pad_input = NULL;
1151fail1: 1190fail1:
1191 if (input_dev)
1192 input_free_device(input_dev);
1193 if (pad_input_dev)
1194 input_free_device(pad_input_dev);
1152 return error; 1195 return error;
1153} 1196}
1154 1197
@@ -1367,6 +1410,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
1367 wacom_calculate_res(features); 1410 wacom_calculate_res(features);
1368 1411
1369 strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); 1412 strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
1413 snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name),
1414 "%s Pad", features->name);
1370 1415
1371 if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { 1416 if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
1372 struct usb_device *other_dev; 1417 struct usb_device *other_dev;
@@ -1441,6 +1486,8 @@ static void wacom_disconnect(struct usb_interface *intf)
1441 cancel_work_sync(&wacom->work); 1486 cancel_work_sync(&wacom->work);
1442 if (wacom->wacom_wac.input) 1487 if (wacom->wacom_wac.input)
1443 input_unregister_device(wacom->wacom_wac.input); 1488 input_unregister_device(wacom->wacom_wac.input);
1489 if (wacom->wacom_wac.pad_input)
1490 input_unregister_device(wacom->wacom_wac.pad_input);
1444 wacom_destroy_battery(wacom); 1491 wacom_destroy_battery(wacom);
1445 wacom_destroy_leds(wacom); 1492 wacom_destroy_leds(wacom);
1446 usb_free_urb(wacom->irq); 1493 usb_free_urb(wacom->irq);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 977d05cd9e2e..4b16a34c95fb 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1489,8 +1489,11 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
1489 break; 1489 break;
1490 } 1490 }
1491 1491
1492 if (sync) 1492 if (sync) {
1493 input_sync(wacom_wac->input); 1493 input_sync(wacom_wac->input);
1494 if (wacom_wac->pad_input)
1495 input_sync(wacom_wac->pad_input);
1496 }
1494} 1497}
1495 1498
1496static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) 1499static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
@@ -1939,6 +1942,28 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
1939 return 0; 1942 return 0;
1940} 1943}
1941 1944
1945int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
1946 struct wacom_wac *wacom_wac)
1947{
1948 struct wacom_features *features = &wacom_wac->features;
1949
1950 input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
1951
1952 /* kept for making legacy xf86-input-wacom working with the wheels */
1953 __set_bit(ABS_MISC, input_dev->absbit);
1954
1955 /* kept for making legacy xf86-input-wacom accepting the pad */
1956 input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
1957 input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
1958
1959 switch (features->type) {
1960 default:
1961 /* no pad supported */
1962 return 1;
1963 }
1964 return 0;
1965}
1966
1942static const struct wacom_features wacom_features_0x00 = 1967static const struct wacom_features wacom_features_0x00 =
1943 { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 1968 { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255,
1944 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; 1969 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index b2c9a9c1b551..f48164c780f4 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -150,6 +150,7 @@ struct wacom_shared {
150 150
151struct wacom_wac { 151struct wacom_wac {
152 char name[WACOM_NAME_MAX]; 152 char name[WACOM_NAME_MAX];
153 char pad_name[WACOM_NAME_MAX];
153 unsigned char *data; 154 unsigned char *data;
154 int tool[2]; 155 int tool[2];
155 int id[2]; 156 int id[2];
@@ -157,6 +158,7 @@ struct wacom_wac {
157 struct wacom_features features; 158 struct wacom_features features;
158 struct wacom_shared *shared; 159 struct wacom_shared *shared;
159 struct input_dev *input; 160 struct input_dev *input;
161 struct input_dev *pad_input;
160 int pid; 162 int pid;
161 int battery_capacity; 163 int battery_capacity;
162 int num_contacts_left; 164 int num_contacts_left;