diff options
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 231 |
1 files changed, 200 insertions, 31 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index ca28066dc81e..0d269212931e 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 * 100) / features->x_resolution; | ||
188 | features->y_phy = | ||
189 | (features->y_max * 100) / features->y_resolution; | ||
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]); |
@@ -422,6 +427,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
422 | report_id, rep_data, 4, 1); | 427 | report_id, rep_data, 4, 1); |
423 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); | 428 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); |
424 | } else if (features->type != TABLETPC && | 429 | } else if (features->type != TABLETPC && |
430 | features->type != WIRELESS && | ||
425 | features->device_type == BTN_TOOL_PEN) { | 431 | features->device_type == BTN_TOOL_PEN) { |
426 | do { | 432 | do { |
427 | rep_data[0] = 2; | 433 | rep_data[0] = 2; |
@@ -454,6 +460,21 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | |||
454 | features->pressure_fuzz = 0; | 460 | features->pressure_fuzz = 0; |
455 | features->distance_fuzz = 0; | 461 | features->distance_fuzz = 0; |
456 | 462 | ||
463 | /* | ||
464 | * The wireless device HID is basic and layout conflicts with | ||
465 | * other tablets (monitor and touch interface can look like pen). | ||
466 | * Skip the query for this type and modify defaults based on | ||
467 | * interface number. | ||
468 | */ | ||
469 | if (features->type == WIRELESS) { | ||
470 | if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { | ||
471 | features->device_type = 0; | ||
472 | } else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) { | ||
473 | features->device_type = BTN_TOOL_DOUBLETAP; | ||
474 | features->pktlen = WACOM_PKGLEN_BBTOUCH3; | ||
475 | } | ||
476 | } | ||
477 | |||
457 | /* only Tablet PCs and Bamboo P&T need to retrieve the info */ | 478 | /* only Tablet PCs and Bamboo P&T need to retrieve the info */ |
458 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && | 479 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && |
459 | (features->type != BAMBOO_PT)) | 480 | (features->type != BAMBOO_PT)) |
@@ -822,6 +843,152 @@ static void wacom_destroy_leds(struct wacom *wacom) | |||
822 | } | 843 | } |
823 | } | 844 | } |
824 | 845 | ||
846 | static enum power_supply_property wacom_battery_props[] = { | ||
847 | POWER_SUPPLY_PROP_CAPACITY | ||
848 | }; | ||
849 | |||
850 | static int wacom_battery_get_property(struct power_supply *psy, | ||
851 | enum power_supply_property psp, | ||
852 | union power_supply_propval *val) | ||
853 | { | ||
854 | struct wacom *wacom = container_of(psy, struct wacom, battery); | ||
855 | int ret = 0; | ||
856 | |||
857 | switch (psp) { | ||
858 | case POWER_SUPPLY_PROP_CAPACITY: | ||
859 | val->intval = | ||
860 | wacom->wacom_wac.battery_capacity * 100 / 31; | ||
861 | break; | ||
862 | default: | ||
863 | ret = -EINVAL; | ||
864 | break; | ||
865 | } | ||
866 | |||
867 | return ret; | ||
868 | } | ||
869 | |||
870 | static int wacom_initialize_battery(struct wacom *wacom) | ||
871 | { | ||
872 | int error = 0; | ||
873 | |||
874 | if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) { | ||
875 | wacom->battery.properties = wacom_battery_props; | ||
876 | wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); | ||
877 | wacom->battery.get_property = wacom_battery_get_property; | ||
878 | wacom->battery.name = "wacom_battery"; | ||
879 | wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
880 | wacom->battery.use_for_apm = 0; | ||
881 | |||
882 | error = power_supply_register(&wacom->usbdev->dev, | ||
883 | &wacom->battery); | ||
884 | } | ||
885 | |||
886 | return error; | ||
887 | } | ||
888 | |||
889 | static void wacom_destroy_battery(struct wacom *wacom) | ||
890 | { | ||
891 | if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) | ||
892 | power_supply_unregister(&wacom->battery); | ||
893 | } | ||
894 | |||
895 | static int wacom_register_input(struct wacom *wacom) | ||
896 | { | ||
897 | struct input_dev *input_dev; | ||
898 | struct usb_interface *intf = wacom->intf; | ||
899 | struct usb_device *dev = interface_to_usbdev(intf); | ||
900 | struct wacom_wac *wacom_wac = &(wacom->wacom_wac); | ||
901 | int error; | ||
902 | |||
903 | input_dev = input_allocate_device(); | ||
904 | if (!input_dev) | ||
905 | return -ENOMEM; | ||
906 | |||
907 | input_dev->name = wacom_wac->name; | ||
908 | input_dev->dev.parent = &intf->dev; | ||
909 | input_dev->open = wacom_open; | ||
910 | input_dev->close = wacom_close; | ||
911 | usb_to_input_id(dev, &input_dev->id); | ||
912 | input_set_drvdata(input_dev, wacom); | ||
913 | |||
914 | wacom_wac->input = input_dev; | ||
915 | wacom_setup_input_capabilities(input_dev, wacom_wac); | ||
916 | |||
917 | error = input_register_device(input_dev); | ||
918 | if (error) { | ||
919 | input_free_device(input_dev); | ||
920 | wacom_wac->input = NULL; | ||
921 | } | ||
922 | |||
923 | return error; | ||
924 | } | ||
925 | |||
926 | static void wacom_wireless_work(struct work_struct *work) | ||
927 | { | ||
928 | struct wacom *wacom = container_of(work, struct wacom, work); | ||
929 | struct usb_device *usbdev = wacom->usbdev; | ||
930 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
931 | |||
932 | /* | ||
933 | * Regardless if this is a disconnect or a new tablet, | ||
934 | * remove any existing input devices. | ||
935 | */ | ||
936 | |||
937 | /* Stylus interface */ | ||
938 | wacom = usb_get_intfdata(usbdev->config->interface[1]); | ||
939 | if (wacom->wacom_wac.input) | ||
940 | input_unregister_device(wacom->wacom_wac.input); | ||
941 | wacom->wacom_wac.input = 0; | ||
942 | |||
943 | /* Touch interface */ | ||
944 | wacom = usb_get_intfdata(usbdev->config->interface[2]); | ||
945 | if (wacom->wacom_wac.input) | ||
946 | input_unregister_device(wacom->wacom_wac.input); | ||
947 | wacom->wacom_wac.input = 0; | ||
948 | |||
949 | if (wacom_wac->pid == 0) { | ||
950 | printk(KERN_INFO "wacom: wireless tablet disconnected\n"); | ||
951 | } else { | ||
952 | const struct usb_device_id *id = wacom_ids; | ||
953 | |||
954 | printk(KERN_INFO | ||
955 | "wacom: wireless tablet connected with PID %x\n", | ||
956 | wacom_wac->pid); | ||
957 | |||
958 | while (id->match_flags) { | ||
959 | if (id->idVendor == USB_VENDOR_ID_WACOM && | ||
960 | id->idProduct == wacom_wac->pid) | ||
961 | break; | ||
962 | id++; | ||
963 | } | ||
964 | |||
965 | if (!id->match_flags) { | ||
966 | printk(KERN_INFO | ||
967 | "wacom: ignorning unknown PID.\n"); | ||
968 | return; | ||
969 | } | ||
970 | |||
971 | /* Stylus interface */ | ||
972 | wacom = usb_get_intfdata(usbdev->config->interface[1]); | ||
973 | wacom_wac = &wacom->wacom_wac; | ||
974 | wacom_wac->features = | ||
975 | *((struct wacom_features *)id->driver_info); | ||
976 | wacom_wac->features.device_type = BTN_TOOL_PEN; | ||
977 | wacom_register_input(wacom); | ||
978 | |||
979 | /* Touch interface */ | ||
980 | wacom = usb_get_intfdata(usbdev->config->interface[2]); | ||
981 | wacom_wac = &wacom->wacom_wac; | ||
982 | wacom_wac->features = | ||
983 | *((struct wacom_features *)id->driver_info); | ||
984 | wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3; | ||
985 | wacom_wac->features.device_type = BTN_TOOL_FINGER; | ||
986 | wacom_set_phy_from_res(&wacom_wac->features); | ||
987 | wacom_wac->features.x_max = wacom_wac->features.y_max = 4096; | ||
988 | wacom_register_input(wacom); | ||
989 | } | ||
990 | } | ||
991 | |||
825 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 992 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
826 | { | 993 | { |
827 | struct usb_device *dev = interface_to_usbdev(intf); | 994 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -829,18 +996,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
829 | struct wacom *wacom; | 996 | struct wacom *wacom; |
830 | struct wacom_wac *wacom_wac; | 997 | struct wacom_wac *wacom_wac; |
831 | struct wacom_features *features; | 998 | struct wacom_features *features; |
832 | struct input_dev *input_dev; | ||
833 | int error; | 999 | int error; |
834 | 1000 | ||
835 | if (!id->driver_info) | 1001 | if (!id->driver_info) |
836 | return -EINVAL; | 1002 | return -EINVAL; |
837 | 1003 | ||
838 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | 1004 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); |
839 | input_dev = input_allocate_device(); | 1005 | if (!wacom) |
840 | if (!wacom || !input_dev) { | 1006 | return -ENOMEM; |
841 | error = -ENOMEM; | ||
842 | goto fail1; | ||
843 | } | ||
844 | 1007 | ||
845 | wacom_wac = &wacom->wacom_wac; | 1008 | wacom_wac = &wacom->wacom_wac; |
846 | wacom_wac->features = *((struct wacom_features *)id->driver_info); | 1009 | wacom_wac->features = *((struct wacom_features *)id->driver_info); |
@@ -866,11 +1029,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
866 | wacom->usbdev = dev; | 1029 | wacom->usbdev = dev; |
867 | wacom->intf = intf; | 1030 | wacom->intf = intf; |
868 | mutex_init(&wacom->lock); | 1031 | mutex_init(&wacom->lock); |
1032 | INIT_WORK(&wacom->work, wacom_wireless_work); | ||
869 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | 1033 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); |
870 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | 1034 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); |
871 | 1035 | ||
872 | wacom_wac->input = input_dev; | ||
873 | |||
874 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | 1036 | endpoint = &intf->cur_altsetting->endpoint[0].desc; |
875 | 1037 | ||
876 | /* Retrieve the physical and logical size for OEM devices */ | 1038 | /* Retrieve the physical and logical size for OEM devices */ |
@@ -894,15 +1056,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
894 | goto fail3; | 1056 | goto fail3; |
895 | } | 1057 | } |
896 | 1058 | ||
897 | input_dev->name = wacom_wac->name; | ||
898 | input_dev->dev.parent = &intf->dev; | ||
899 | input_dev->open = wacom_open; | ||
900 | input_dev->close = wacom_close; | ||
901 | usb_to_input_id(dev, &input_dev->id); | ||
902 | input_set_drvdata(input_dev, wacom); | ||
903 | |||
904 | wacom_setup_input_capabilities(input_dev, wacom_wac); | ||
905 | |||
906 | usb_fill_int_urb(wacom->irq, dev, | 1059 | usb_fill_int_urb(wacom->irq, dev, |
907 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | 1060 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), |
908 | wacom_wac->data, features->pktlen, | 1061 | wacom_wac->data, features->pktlen, |
@@ -914,22 +1067,34 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
914 | if (error) | 1067 | if (error) |
915 | goto fail4; | 1068 | goto fail4; |
916 | 1069 | ||
917 | error = input_register_device(input_dev); | 1070 | error = wacom_initialize_battery(wacom); |
918 | if (error) | 1071 | if (error) |
919 | goto fail5; | 1072 | goto fail5; |
920 | 1073 | ||
1074 | if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { | ||
1075 | error = wacom_register_input(wacom); | ||
1076 | if (error) | ||
1077 | goto fail6; | ||
1078 | } | ||
1079 | |||
921 | /* Note that if query fails it is not a hard failure */ | 1080 | /* Note that if query fails it is not a hard failure */ |
922 | wacom_query_tablet_data(intf, features); | 1081 | wacom_query_tablet_data(intf, features); |
923 | 1082 | ||
924 | usb_set_intfdata(intf, wacom); | 1083 | usb_set_intfdata(intf, wacom); |
1084 | |||
1085 | if (features->quirks & WACOM_QUIRK_MONITOR) { | ||
1086 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) | ||
1087 | goto fail5; | ||
1088 | } | ||
1089 | |||
925 | return 0; | 1090 | return 0; |
926 | 1091 | ||
1092 | fail6: wacom_destroy_battery(wacom); | ||
927 | fail5: wacom_destroy_leds(wacom); | 1093 | fail5: wacom_destroy_leds(wacom); |
928 | fail4: wacom_remove_shared_data(wacom_wac); | 1094 | fail4: wacom_remove_shared_data(wacom_wac); |
929 | fail3: usb_free_urb(wacom->irq); | 1095 | fail3: usb_free_urb(wacom->irq); |
930 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); | 1096 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); |
931 | fail1: input_free_device(input_dev); | 1097 | fail1: kfree(wacom); |
932 | kfree(wacom); | ||
933 | return error; | 1098 | return error; |
934 | } | 1099 | } |
935 | 1100 | ||
@@ -940,7 +1105,10 @@ static void wacom_disconnect(struct usb_interface *intf) | |||
940 | usb_set_intfdata(intf, NULL); | 1105 | usb_set_intfdata(intf, NULL); |
941 | 1106 | ||
942 | usb_kill_urb(wacom->irq); | 1107 | usb_kill_urb(wacom->irq); |
943 | input_unregister_device(wacom->wacom_wac.input); | 1108 | cancel_work_sync(&wacom->work); |
1109 | if (wacom->wacom_wac.input) | ||
1110 | input_unregister_device(wacom->wacom_wac.input); | ||
1111 | wacom_destroy_battery(wacom); | ||
944 | wacom_destroy_leds(wacom); | 1112 | wacom_destroy_leds(wacom); |
945 | usb_free_urb(wacom->irq); | 1113 | usb_free_urb(wacom->irq); |
946 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, | 1114 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, |
@@ -972,7 +1140,8 @@ static int wacom_resume(struct usb_interface *intf) | |||
972 | wacom_query_tablet_data(intf, features); | 1140 | wacom_query_tablet_data(intf, features); |
973 | wacom_led_control(wacom); | 1141 | wacom_led_control(wacom); |
974 | 1142 | ||
975 | if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) | 1143 | if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR) |
1144 | && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) | ||
976 | rv = -EIO; | 1145 | rv = -EIO; |
977 | 1146 | ||
978 | mutex_unlock(&wacom->lock); | 1147 | mutex_unlock(&wacom->lock); |