aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tablet/wacom_sys.c
diff options
context:
space:
mode:
authorChris Bagwell <chris@cnpbagwell.com>2012-03-26 02:26:20 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-03-26 02:32:59 -0400
commit16bf288c4be67b68c3fcb6561ff145702cb7bd22 (patch)
tree9ae5f770afa5812ebdb2f2b381cb1477a59f4f85 /drivers/input/tablet/wacom_sys.c
parentd3825d51c3eddb8a3c7d1281f27181aff6db19b8 (diff)
Input: wacom - create inputs when wireless connect
When a tablet connect or disconnect is detected, schedule work queue to register or unregister related input devices. When a wireless tablet connects, it reports same USB PID used if tablet is connected with USB cable. Use this to update features values, set input capabilities, and then register device. From there, the Pen and Touch interfaces will reuse the existing tablet's IRQ routines. Its possible that 1 receiver is shared with 2 tablets with different PID (small and medium Bamboo for example) so the input is unregister at disconnect to better support this case. Signed-off-by: Chris Bagwell <chris@cnpbagwell.com> Tested-by: Jason Gerecke <killertofu@gmail.com> Acked-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r--drivers/input/tablet/wacom_sys.c91
1 files changed, 82 insertions, 9 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index d8cc9ce165ff..2fc77053960f 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -167,6 +167,19 @@ static void wacom_close(struct input_dev *dev)
167 usb_autopm_put_interface(wacom->intf); 167 usb_autopm_put_interface(wacom->intf);
168} 168}
169 169
170/*
171 * Static values for max X/Y and resolution of Pen interface is stored in
172 * features. This mean physical size of active area can be computed.
173 * This is useful to do when Pen and Touch have same active area of tablet.
174 * This means for Touch device, we only need to find max X/Y value and we
175 * have enough information to compute resolution of touch.
176 */
177static void wacom_set_phy_from_res(struct wacom_features *features)
178{
179 features->x_phy = (features->x_max * 100) / features->x_resolution;
180 features->y_phy = (features->y_max * 100) / features->y_resolution;
181}
182
170static int wacom_parse_logical_collection(unsigned char *report, 183static int wacom_parse_logical_collection(unsigned char *report,
171 struct wacom_features *features) 184 struct wacom_features *features)
172{ 185{
@@ -178,15 +191,7 @@ static int wacom_parse_logical_collection(unsigned char *report,
178 features->pktlen = WACOM_PKGLEN_BBTOUCH3; 191 features->pktlen = WACOM_PKGLEN_BBTOUCH3;
179 features->device_type = BTN_TOOL_FINGER; 192 features->device_type = BTN_TOOL_FINGER;
180 193
181 /* 194 wacom_set_phy_from_res(features);
182 * Stylus and Touch have same active area
183 * so compute physical size based on stylus
184 * data before its overwritten.
185 */
186 features->x_phy =
187 (features->x_max * features->x_resolution) / 100;
188 features->y_phy =
189 (features->y_max * features->y_resolution) / 100;
190 195
191 features->x_max = features->y_max = 196 features->x_max = features->y_max =
192 get_unaligned_le16(&report[10]); 197 get_unaligned_le16(&report[10]);
@@ -869,6 +874,72 @@ static int wacom_register_input(struct wacom *wacom)
869 return error; 874 return error;
870} 875}
871 876
877static void wacom_wireless_work(struct work_struct *work)
878{
879 struct wacom *wacom = container_of(work, struct wacom, work);
880 struct usb_device *usbdev = wacom->usbdev;
881 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
882
883 /*
884 * Regardless if this is a disconnect or a new tablet,
885 * remove any existing input devices.
886 */
887
888 /* Stylus interface */
889 wacom = usb_get_intfdata(usbdev->config->interface[1]);
890 if (wacom->wacom_wac.input)
891 input_unregister_device(wacom->wacom_wac.input);
892 wacom->wacom_wac.input = 0;
893
894 /* Touch interface */
895 wacom = usb_get_intfdata(usbdev->config->interface[2]);
896 if (wacom->wacom_wac.input)
897 input_unregister_device(wacom->wacom_wac.input);
898 wacom->wacom_wac.input = 0;
899
900 if (wacom_wac->pid == 0) {
901 printk(KERN_INFO "wacom: wireless tablet disconnected\n");
902 } else {
903 const struct usb_device_id *id = wacom_ids;
904
905 printk(KERN_INFO
906 "wacom: wireless tablet connected with PID %x\n",
907 wacom_wac->pid);
908
909 while (id->match_flags) {
910 if (id->idVendor == USB_VENDOR_ID_WACOM &&
911 id->idProduct == wacom_wac->pid)
912 break;
913 id++;
914 }
915
916 if (!id->match_flags) {
917 printk(KERN_INFO
918 "wacom: ignorning unknown PID.\n");
919 return;
920 }
921
922 /* Stylus interface */
923 wacom = usb_get_intfdata(usbdev->config->interface[1]);
924 wacom_wac = &wacom->wacom_wac;
925 wacom_wac->features =
926 *((struct wacom_features *)id->driver_info);
927 wacom_wac->features.device_type = BTN_TOOL_PEN;
928 wacom_register_input(wacom);
929
930 /* Touch interface */
931 wacom = usb_get_intfdata(usbdev->config->interface[2]);
932 wacom_wac = &wacom->wacom_wac;
933 wacom_wac->features =
934 *((struct wacom_features *)id->driver_info);
935 wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
936 wacom_wac->features.device_type = BTN_TOOL_FINGER;
937 wacom_set_phy_from_res(&wacom_wac->features);
938 wacom_wac->features.x_max = wacom_wac->features.y_max = 4096;
939 wacom_register_input(wacom);
940 }
941}
942
872static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) 943static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
873{ 944{
874 struct usb_device *dev = interface_to_usbdev(intf); 945 struct usb_device *dev = interface_to_usbdev(intf);
@@ -907,6 +978,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
907 wacom->usbdev = dev; 978 wacom->usbdev = dev;
908 wacom->intf = intf; 979 wacom->intf = intf;
909 mutex_init(&wacom->lock); 980 mutex_init(&wacom->lock);
981 INIT_WORK(&wacom->work, wacom_wireless_work);
910 usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); 982 usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
911 strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); 983 strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
912 984
@@ -977,6 +1049,7 @@ static void wacom_disconnect(struct usb_interface *intf)
977 usb_set_intfdata(intf, NULL); 1049 usb_set_intfdata(intf, NULL);
978 1050
979 usb_kill_urb(wacom->irq); 1051 usb_kill_urb(wacom->irq);
1052 cancel_work_sync(&wacom->work);
980 if (wacom->wacom_wac.input) 1053 if (wacom->wacom_wac.input)
981 input_unregister_device(wacom->wacom_wac.input); 1054 input_unregister_device(wacom->wacom_wac.input);
982 wacom_destroy_leds(wacom); 1055 wacom_destroy_leds(wacom);