diff options
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 91 |
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 | */ | ||
177 | static 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 | |||
170 | static int wacom_parse_logical_collection(unsigned char *report, | 183 | static 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 | ||
877 | static 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 | |||
872 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 943 | static 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); |