hid-letsketch.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021 Hans de Goede <[email protected]>
  4. *
  5. * Driver for the LetSketch / VSON WP9620N drawing tablet.
  6. * This drawing tablet is also sold under other brand names such as Case U,
  7. * presumably this driver will work for all of them. But it has only been
  8. * tested with a LetSketch WP9620N model.
  9. *
  10. * These tablets also work without a special HID driver, but then only part
  11. * of the active area works and both the pad and stylus buttons are hardwired
  12. * to special key-combos. E.g. the 2 stylus buttons send right mouse clicks /
  13. * resp. "e" key presses.
  14. *
  15. * This device has 4 USB interfaces:
  16. *
  17. * Interface 0 EP 0x81 bootclass mouse, rdesc len 18, report id 0x08,
  18. * Application(ff00.0001)
  19. * This interface sends raw event input reports in a custom format, but only
  20. * after doing the special dance from letsketch_probe(). After enabling this
  21. * interface the other 3 interfaces are disabled.
  22. *
  23. * Interface 1 EP 0x82 bootclass mouse, rdesc len 83, report id 0x0a, Tablet
  24. * This interface sends absolute events for the pen, including pressure,
  25. * but only for some part of the active area due to special "aspect ratio"
  26. * correction and only half by default since it assumes it will be used
  27. * with a phone in portraid mode, while using the tablet in landscape mode.
  28. * Also stylus + pad button events are not reported here.
  29. *
  30. * Interface 2 EP 0x83 bootclass keybd, rdesc len 64, report id none, Std Kbd
  31. * This interfaces send various hard-coded key-combos for the pad buttons
  32. * and "e" keypresses for the 2nd stylus button
  33. *
  34. * Interface 3 EP 0x84 bootclass mouse, rdesc len 75, report id 0x01, Std Mouse
  35. * This reports right-click mouse-button events for the 1st stylus button
  36. */
  37. #include <linux/device.h>
  38. #include <linux/input.h>
  39. #include <linux/hid.h>
  40. #include <linux/module.h>
  41. #include <linux/timer.h>
  42. #include <linux/usb.h>
  43. #include <asm/unaligned.h>
  44. #include "hid-ids.h"
  45. #define LETSKETCH_RAW_IF 0
  46. #define LETSKETCH_RAW_DATA_LEN 12
  47. #define LETSKETCH_RAW_REPORT_ID 8
  48. #define LETSKETCH_PAD_BUTTONS 5
  49. #define LETSKETCH_INFO_STR_IDX_BEGIN 0xc8
  50. #define LETSKETCH_INFO_STR_IDX_END 0xca
  51. #define LETSKETCH_GET_STRING_RETRIES 5
  52. struct letsketch_data {
  53. struct hid_device *hdev;
  54. struct input_dev *input_tablet;
  55. struct input_dev *input_tablet_pad;
  56. struct timer_list inrange_timer;
  57. };
  58. static int letsketch_open(struct input_dev *dev)
  59. {
  60. struct letsketch_data *data = input_get_drvdata(dev);
  61. return hid_hw_open(data->hdev);
  62. }
  63. static void letsketch_close(struct input_dev *dev)
  64. {
  65. struct letsketch_data *data = input_get_drvdata(dev);
  66. hid_hw_close(data->hdev);
  67. }
  68. static struct input_dev *letsketch_alloc_input_dev(struct letsketch_data *data)
  69. {
  70. struct input_dev *input;
  71. input = devm_input_allocate_device(&data->hdev->dev);
  72. if (!input)
  73. return NULL;
  74. input->id.bustype = data->hdev->bus;
  75. input->id.vendor = data->hdev->vendor;
  76. input->id.product = data->hdev->product;
  77. input->id.version = data->hdev->bus;
  78. input->phys = data->hdev->phys;
  79. input->uniq = data->hdev->uniq;
  80. input->open = letsketch_open;
  81. input->close = letsketch_close;
  82. input_set_drvdata(input, data);
  83. return input;
  84. }
  85. static int letsketch_setup_input_tablet(struct letsketch_data *data)
  86. {
  87. struct input_dev *input;
  88. input = letsketch_alloc_input_dev(data);
  89. if (!input)
  90. return -ENOMEM;
  91. input_set_abs_params(input, ABS_X, 0, 50800, 0, 0);
  92. input_set_abs_params(input, ABS_Y, 0, 31750, 0, 0);
  93. input_set_abs_params(input, ABS_PRESSURE, 0, 8192, 0, 0);
  94. input_abs_set_res(input, ABS_X, 240);
  95. input_abs_set_res(input, ABS_Y, 225);
  96. input_set_capability(input, EV_KEY, BTN_TOUCH);
  97. input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
  98. input_set_capability(input, EV_KEY, BTN_STYLUS);
  99. input_set_capability(input, EV_KEY, BTN_STYLUS2);
  100. /* All known brands selling this tablet use WP9620[N] as model name */
  101. input->name = "WP9620 Tablet";
  102. data->input_tablet = input;
  103. return input_register_device(data->input_tablet);
  104. }
  105. static int letsketch_setup_input_tablet_pad(struct letsketch_data *data)
  106. {
  107. struct input_dev *input;
  108. int i;
  109. input = letsketch_alloc_input_dev(data);
  110. if (!input)
  111. return -ENOMEM;
  112. for (i = 0; i < LETSKETCH_PAD_BUTTONS; i++)
  113. input_set_capability(input, EV_KEY, BTN_0 + i);
  114. /*
  115. * These are never send on the pad input_dev, but must be set
  116. * on the Pad to make udev / libwacom happy.
  117. */
  118. input_set_abs_params(input, ABS_X, 0, 1, 0, 0);
  119. input_set_abs_params(input, ABS_Y, 0, 1, 0, 0);
  120. input_set_capability(input, EV_KEY, BTN_STYLUS);
  121. input->name = "WP9620 Pad";
  122. data->input_tablet_pad = input;
  123. return input_register_device(data->input_tablet_pad);
  124. }
  125. static void letsketch_inrange_timeout(struct timer_list *t)
  126. {
  127. struct letsketch_data *data = from_timer(data, t, inrange_timer);
  128. struct input_dev *input = data->input_tablet;
  129. input_report_key(input, BTN_TOOL_PEN, 0);
  130. input_sync(input);
  131. }
  132. static int letsketch_raw_event(struct hid_device *hdev,
  133. struct hid_report *report,
  134. u8 *raw_data, int size)
  135. {
  136. struct letsketch_data *data = hid_get_drvdata(hdev);
  137. struct input_dev *input;
  138. int i;
  139. if (size != LETSKETCH_RAW_DATA_LEN || raw_data[0] != LETSKETCH_RAW_REPORT_ID)
  140. return 0;
  141. switch (raw_data[1] & 0xf0) {
  142. case 0x80: /* Pen data */
  143. input = data->input_tablet;
  144. input_report_key(input, BTN_TOOL_PEN, 1);
  145. input_report_key(input, BTN_TOUCH, raw_data[1] & 0x01);
  146. input_report_key(input, BTN_STYLUS, raw_data[1] & 0x02);
  147. input_report_key(input, BTN_STYLUS2, raw_data[1] & 0x04);
  148. input_report_abs(input, ABS_X,
  149. get_unaligned_le16(raw_data + 2));
  150. input_report_abs(input, ABS_Y,
  151. get_unaligned_le16(raw_data + 4));
  152. input_report_abs(input, ABS_PRESSURE,
  153. get_unaligned_le16(raw_data + 6));
  154. /*
  155. * There is no out of range event, so use a timer for this
  156. * when in range we get an event approx. every 8 ms.
  157. */
  158. mod_timer(&data->inrange_timer, jiffies + msecs_to_jiffies(100));
  159. break;
  160. case 0xe0: /* Pad data */
  161. input = data->input_tablet_pad;
  162. for (i = 0; i < LETSKETCH_PAD_BUTTONS; i++)
  163. input_report_key(input, BTN_0 + i, raw_data[4] == (i + 1));
  164. break;
  165. default:
  166. hid_warn(data->hdev, "Warning unknown data header: 0x%02x\n",
  167. raw_data[0]);
  168. return 0;
  169. }
  170. input_sync(input);
  171. return 0;
  172. }
  173. /*
  174. * The tablets magic handshake to put it in raw mode relies on getting
  175. * string descriptors. But the firmware is buggy and does not like it if
  176. * we do this too fast. Even if we go slow sometimes the usb_string() call
  177. * fails. Ignore errors and retry it a couple of times if necessary.
  178. */
  179. static int letsketch_get_string(struct usb_device *udev, int index, char *buf, int size)
  180. {
  181. int i, ret;
  182. for (i = 0; i < LETSKETCH_GET_STRING_RETRIES; i++) {
  183. usleep_range(5000, 7000);
  184. ret = usb_string(udev, index, buf, size);
  185. if (ret > 0)
  186. return 0;
  187. }
  188. dev_err(&udev->dev, "Max retries (%d) exceeded reading string descriptor %d\n",
  189. LETSKETCH_GET_STRING_RETRIES, index);
  190. return ret ? ret : -EIO;
  191. }
  192. static int letsketch_probe(struct hid_device *hdev, const struct hid_device_id *id)
  193. {
  194. struct device *dev = &hdev->dev;
  195. struct letsketch_data *data;
  196. struct usb_interface *intf;
  197. struct usb_device *udev;
  198. char buf[256];
  199. int i, ret;
  200. if (!hid_is_using_ll_driver(hdev, &usb_hid_driver))
  201. return -ENODEV;
  202. intf = to_usb_interface(hdev->dev.parent);
  203. if (intf->altsetting->desc.bInterfaceNumber != LETSKETCH_RAW_IF)
  204. return -ENODEV; /* Ignore the other interfaces */
  205. udev = interface_to_usbdev(intf);
  206. /*
  207. * Instead of using a set-feature request, or even a custom USB ctrl
  208. * message the tablet needs this elaborate magic reading of USB
  209. * string descriptors to kick it into raw mode. This is what the
  210. * Windows drivers are seen doing in an USB trace under Windows.
  211. */
  212. for (i = LETSKETCH_INFO_STR_IDX_BEGIN; i <= LETSKETCH_INFO_STR_IDX_END; i++) {
  213. ret = letsketch_get_string(udev, i, buf, sizeof(buf));
  214. if (ret)
  215. return ret;
  216. hid_info(hdev, "Device info: %s\n", buf);
  217. }
  218. for (i = 1; i <= 250; i++) {
  219. ret = letsketch_get_string(udev, i, buf, sizeof(buf));
  220. if (ret)
  221. return ret;
  222. }
  223. ret = letsketch_get_string(udev, 0x64, buf, sizeof(buf));
  224. if (ret)
  225. return ret;
  226. ret = letsketch_get_string(udev, LETSKETCH_INFO_STR_IDX_BEGIN, buf, sizeof(buf));
  227. if (ret)
  228. return ret;
  229. /*
  230. * The tablet should be in raw mode now, end with a final delay before
  231. * doing further IO to the device.
  232. */
  233. usleep_range(5000, 7000);
  234. ret = hid_parse(hdev);
  235. if (ret)
  236. return ret;
  237. data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
  238. if (!data)
  239. return -ENOMEM;
  240. data->hdev = hdev;
  241. timer_setup(&data->inrange_timer, letsketch_inrange_timeout, 0);
  242. hid_set_drvdata(hdev, data);
  243. ret = letsketch_setup_input_tablet(data);
  244. if (ret)
  245. return ret;
  246. ret = letsketch_setup_input_tablet_pad(data);
  247. if (ret)
  248. return ret;
  249. return hid_hw_start(hdev, HID_CONNECT_HIDRAW);
  250. }
  251. static const struct hid_device_id letsketch_devices[] = {
  252. { HID_USB_DEVICE(USB_VENDOR_ID_LETSKETCH, USB_DEVICE_ID_WP9620N) },
  253. { }
  254. };
  255. MODULE_DEVICE_TABLE(hid, letsketch_devices);
  256. static struct hid_driver letsketch_driver = {
  257. .name = "letsketch",
  258. .id_table = letsketch_devices,
  259. .probe = letsketch_probe,
  260. .raw_event = letsketch_raw_event,
  261. };
  262. module_hid_driver(letsketch_driver);
  263. MODULE_AUTHOR("Hans de Goede <[email protected]>");
  264. MODULE_LICENSE("GPL");