hid-udraw-ps3.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * HID driver for THQ PS3 uDraw tablet
  3. *
  4. * Copyright (C) 2016 Red Hat Inc. All Rights Reserved
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/device.h>
  16. #include <linux/hid.h>
  17. #include <linux/module.h>
  18. #include "hid-ids.h"
  19. MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
  20. MODULE_DESCRIPTION("PS3 uDraw tablet driver");
  21. MODULE_LICENSE("GPL");
  22. /*
  23. * Protocol information from:
  24. * http://brandonw.net/udraw/
  25. * and the source code of:
  26. * https://vvvv.org/contribution/udraw-hid
  27. */
  28. /*
  29. * The device is setup with multiple input devices:
  30. * - the touch area which works as a touchpad
  31. * - the tablet area which works as a touchpad/drawing tablet
  32. * - a joypad with a d-pad, and 7 buttons
  33. * - an accelerometer device
  34. */
  35. enum {
  36. TOUCH_NONE,
  37. TOUCH_PEN,
  38. TOUCH_FINGER,
  39. TOUCH_TWOFINGER
  40. };
  41. enum {
  42. AXIS_X,
  43. AXIS_Y,
  44. AXIS_Z
  45. };
  46. /*
  47. * Accelerometer min/max values
  48. * in order, X, Y and Z
  49. */
  50. static struct {
  51. int min;
  52. int max;
  53. } accel_limits[] = {
  54. [AXIS_X] = { 490, 534 },
  55. [AXIS_Y] = { 490, 534 },
  56. [AXIS_Z] = { 492, 536 }
  57. };
  58. #define DEVICE_NAME "THQ uDraw Game Tablet for PS3"
  59. /* resolution in pixels */
  60. #define RES_X 1920
  61. #define RES_Y 1080
  62. /* size in mm */
  63. #define WIDTH 160
  64. #define HEIGHT 90
  65. #define PRESSURE_OFFSET 113
  66. #define MAX_PRESSURE (255 - PRESSURE_OFFSET)
  67. struct udraw {
  68. struct input_dev *joy_input_dev;
  69. struct input_dev *touch_input_dev;
  70. struct input_dev *pen_input_dev;
  71. struct input_dev *accel_input_dev;
  72. struct hid_device *hdev;
  73. /*
  74. * The device's two-finger support is pretty unreliable, as
  75. * the device could report a single touch when the two fingers
  76. * are too close together, and the distance between fingers, even
  77. * though reported is not in the same unit as the touches.
  78. *
  79. * We'll make do without it, and try to report the first touch
  80. * as reliably as possible.
  81. */
  82. int last_one_finger_x;
  83. int last_one_finger_y;
  84. int last_two_finger_x;
  85. int last_two_finger_y;
  86. };
  87. static int clamp_accel(int axis, int offset)
  88. {
  89. axis = clamp(axis,
  90. accel_limits[offset].min,
  91. accel_limits[offset].max);
  92. axis = (axis - accel_limits[offset].min) /
  93. ((accel_limits[offset].max -
  94. accel_limits[offset].min) * 0xFF);
  95. return axis;
  96. }
  97. static int udraw_raw_event(struct hid_device *hdev, struct hid_report *report,
  98. u8 *data, int len)
  99. {
  100. struct udraw *udraw = hid_get_drvdata(hdev);
  101. int touch;
  102. int x, y, z;
  103. if (len != 27)
  104. return 0;
  105. if (data[11] == 0x00)
  106. touch = TOUCH_NONE;
  107. else if (data[11] == 0x40)
  108. touch = TOUCH_PEN;
  109. else if (data[11] == 0x80)
  110. touch = TOUCH_FINGER;
  111. else
  112. touch = TOUCH_TWOFINGER;
  113. /* joypad */
  114. input_report_key(udraw->joy_input_dev, BTN_WEST, data[0] & 1);
  115. input_report_key(udraw->joy_input_dev, BTN_SOUTH, !!(data[0] & 2));
  116. input_report_key(udraw->joy_input_dev, BTN_EAST, !!(data[0] & 4));
  117. input_report_key(udraw->joy_input_dev, BTN_NORTH, !!(data[0] & 8));
  118. input_report_key(udraw->joy_input_dev, BTN_SELECT, !!(data[1] & 1));
  119. input_report_key(udraw->joy_input_dev, BTN_START, !!(data[1] & 2));
  120. input_report_key(udraw->joy_input_dev, BTN_MODE, !!(data[1] & 16));
  121. x = y = 0;
  122. switch (data[2]) {
  123. case 0x0:
  124. y = -127;
  125. break;
  126. case 0x1:
  127. y = -127;
  128. x = 127;
  129. break;
  130. case 0x2:
  131. x = 127;
  132. break;
  133. case 0x3:
  134. y = 127;
  135. x = 127;
  136. break;
  137. case 0x4:
  138. y = 127;
  139. break;
  140. case 0x5:
  141. y = 127;
  142. x = -127;
  143. break;
  144. case 0x6:
  145. x = -127;
  146. break;
  147. case 0x7:
  148. y = -127;
  149. x = -127;
  150. break;
  151. default:
  152. break;
  153. }
  154. input_report_abs(udraw->joy_input_dev, ABS_X, x);
  155. input_report_abs(udraw->joy_input_dev, ABS_Y, y);
  156. input_sync(udraw->joy_input_dev);
  157. /* For pen and touchpad */
  158. x = y = 0;
  159. if (touch != TOUCH_NONE) {
  160. if (data[15] != 0x0F)
  161. x = data[15] * 256 + data[17];
  162. if (data[16] != 0x0F)
  163. y = data[16] * 256 + data[18];
  164. }
  165. if (touch == TOUCH_FINGER) {
  166. /* Save the last one-finger touch */
  167. udraw->last_one_finger_x = x;
  168. udraw->last_one_finger_y = y;
  169. udraw->last_two_finger_x = -1;
  170. udraw->last_two_finger_y = -1;
  171. } else if (touch == TOUCH_TWOFINGER) {
  172. /*
  173. * We have a problem because x/y is the one for the
  174. * second finger but we want the first finger given
  175. * to user-space otherwise it'll look as if it jumped.
  176. *
  177. * See the udraw struct definition for why this was
  178. * implemented this way.
  179. */
  180. if (udraw->last_two_finger_x == -1) {
  181. /* Save the position of the 2nd finger */
  182. udraw->last_two_finger_x = x;
  183. udraw->last_two_finger_y = y;
  184. x = udraw->last_one_finger_x;
  185. y = udraw->last_one_finger_y;
  186. } else {
  187. /*
  188. * Offset the 2-finger coords using the
  189. * saved data from the first finger
  190. */
  191. x = x - (udraw->last_two_finger_x
  192. - udraw->last_one_finger_x);
  193. y = y - (udraw->last_two_finger_y
  194. - udraw->last_one_finger_y);
  195. }
  196. }
  197. /* touchpad */
  198. if (touch == TOUCH_FINGER || touch == TOUCH_TWOFINGER) {
  199. input_report_key(udraw->touch_input_dev, BTN_TOUCH, 1);
  200. input_report_key(udraw->touch_input_dev, BTN_TOOL_FINGER,
  201. touch == TOUCH_FINGER);
  202. input_report_key(udraw->touch_input_dev, BTN_TOOL_DOUBLETAP,
  203. touch == TOUCH_TWOFINGER);
  204. input_report_abs(udraw->touch_input_dev, ABS_X, x);
  205. input_report_abs(udraw->touch_input_dev, ABS_Y, y);
  206. } else {
  207. input_report_key(udraw->touch_input_dev, BTN_TOUCH, 0);
  208. input_report_key(udraw->touch_input_dev, BTN_TOOL_FINGER, 0);
  209. input_report_key(udraw->touch_input_dev, BTN_TOOL_DOUBLETAP, 0);
  210. }
  211. input_sync(udraw->touch_input_dev);
  212. /* pen */
  213. if (touch == TOUCH_PEN) {
  214. int level;
  215. level = clamp(data[13] - PRESSURE_OFFSET,
  216. 0, MAX_PRESSURE);
  217. input_report_key(udraw->pen_input_dev, BTN_TOUCH, (level != 0));
  218. input_report_key(udraw->pen_input_dev, BTN_TOOL_PEN, 1);
  219. input_report_abs(udraw->pen_input_dev, ABS_PRESSURE, level);
  220. input_report_abs(udraw->pen_input_dev, ABS_X, x);
  221. input_report_abs(udraw->pen_input_dev, ABS_Y, y);
  222. } else {
  223. input_report_key(udraw->pen_input_dev, BTN_TOUCH, 0);
  224. input_report_key(udraw->pen_input_dev, BTN_TOOL_PEN, 0);
  225. input_report_abs(udraw->pen_input_dev, ABS_PRESSURE, 0);
  226. }
  227. input_sync(udraw->pen_input_dev);
  228. /* accel */
  229. x = (data[19] + (data[20] << 8));
  230. x = clamp_accel(x, AXIS_X);
  231. y = (data[21] + (data[22] << 8));
  232. y = clamp_accel(y, AXIS_Y);
  233. z = (data[23] + (data[24] << 8));
  234. z = clamp_accel(z, AXIS_Z);
  235. input_report_abs(udraw->accel_input_dev, ABS_X, x);
  236. input_report_abs(udraw->accel_input_dev, ABS_Y, y);
  237. input_report_abs(udraw->accel_input_dev, ABS_Z, z);
  238. input_sync(udraw->accel_input_dev);
  239. /* let hidraw and hiddev handle the report */
  240. return 0;
  241. }
  242. static int udraw_open(struct input_dev *dev)
  243. {
  244. struct udraw *udraw = input_get_drvdata(dev);
  245. return hid_hw_open(udraw->hdev);
  246. }
  247. static void udraw_close(struct input_dev *dev)
  248. {
  249. struct udraw *udraw = input_get_drvdata(dev);
  250. hid_hw_close(udraw->hdev);
  251. }
  252. static struct input_dev *allocate_and_setup(struct hid_device *hdev,
  253. const char *name)
  254. {
  255. struct input_dev *input_dev;
  256. input_dev = devm_input_allocate_device(&hdev->dev);
  257. if (!input_dev)
  258. return NULL;
  259. input_dev->name = name;
  260. input_dev->phys = hdev->phys;
  261. input_dev->dev.parent = &hdev->dev;
  262. input_dev->open = udraw_open;
  263. input_dev->close = udraw_close;
  264. input_dev->uniq = hdev->uniq;
  265. input_dev->id.bustype = hdev->bus;
  266. input_dev->id.vendor = hdev->vendor;
  267. input_dev->id.product = hdev->product;
  268. input_dev->id.version = hdev->version;
  269. input_set_drvdata(input_dev, hid_get_drvdata(hdev));
  270. return input_dev;
  271. }
  272. static bool udraw_setup_touch(struct udraw *udraw,
  273. struct hid_device *hdev)
  274. {
  275. struct input_dev *input_dev;
  276. input_dev = allocate_and_setup(hdev, DEVICE_NAME " Touchpad");
  277. if (!input_dev)
  278. return false;
  279. input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
  280. input_set_abs_params(input_dev, ABS_X, 0, RES_X, 1, 0);
  281. input_abs_set_res(input_dev, ABS_X, RES_X / WIDTH);
  282. input_set_abs_params(input_dev, ABS_Y, 0, RES_Y, 1, 0);
  283. input_abs_set_res(input_dev, ABS_Y, RES_Y / HEIGHT);
  284. set_bit(BTN_TOUCH, input_dev->keybit);
  285. set_bit(BTN_TOOL_FINGER, input_dev->keybit);
  286. set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
  287. set_bit(INPUT_PROP_POINTER, input_dev->propbit);
  288. udraw->touch_input_dev = input_dev;
  289. return true;
  290. }
  291. static bool udraw_setup_pen(struct udraw *udraw,
  292. struct hid_device *hdev)
  293. {
  294. struct input_dev *input_dev;
  295. input_dev = allocate_and_setup(hdev, DEVICE_NAME " Pen");
  296. if (!input_dev)
  297. return false;
  298. input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
  299. input_set_abs_params(input_dev, ABS_X, 0, RES_X, 1, 0);
  300. input_abs_set_res(input_dev, ABS_X, RES_X / WIDTH);
  301. input_set_abs_params(input_dev, ABS_Y, 0, RES_Y, 1, 0);
  302. input_abs_set_res(input_dev, ABS_Y, RES_Y / HEIGHT);
  303. input_set_abs_params(input_dev, ABS_PRESSURE,
  304. 0, MAX_PRESSURE, 0, 0);
  305. set_bit(BTN_TOUCH, input_dev->keybit);
  306. set_bit(BTN_TOOL_PEN, input_dev->keybit);
  307. set_bit(INPUT_PROP_POINTER, input_dev->propbit);
  308. udraw->pen_input_dev = input_dev;
  309. return true;
  310. }
  311. static bool udraw_setup_accel(struct udraw *udraw,
  312. struct hid_device *hdev)
  313. {
  314. struct input_dev *input_dev;
  315. input_dev = allocate_and_setup(hdev, DEVICE_NAME " Accelerometer");
  316. if (!input_dev)
  317. return false;
  318. input_dev->evbit[0] = BIT(EV_ABS);
  319. /* 1G accel is reported as ~256, so clamp to 2G */
  320. input_set_abs_params(input_dev, ABS_X, -512, 512, 0, 0);
  321. input_set_abs_params(input_dev, ABS_Y, -512, 512, 0, 0);
  322. input_set_abs_params(input_dev, ABS_Z, -512, 512, 0, 0);
  323. set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit);
  324. udraw->accel_input_dev = input_dev;
  325. return true;
  326. }
  327. static bool udraw_setup_joypad(struct udraw *udraw,
  328. struct hid_device *hdev)
  329. {
  330. struct input_dev *input_dev;
  331. input_dev = allocate_and_setup(hdev, DEVICE_NAME " Joypad");
  332. if (!input_dev)
  333. return false;
  334. input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
  335. set_bit(BTN_SOUTH, input_dev->keybit);
  336. set_bit(BTN_NORTH, input_dev->keybit);
  337. set_bit(BTN_EAST, input_dev->keybit);
  338. set_bit(BTN_WEST, input_dev->keybit);
  339. set_bit(BTN_SELECT, input_dev->keybit);
  340. set_bit(BTN_START, input_dev->keybit);
  341. set_bit(BTN_MODE, input_dev->keybit);
  342. input_set_abs_params(input_dev, ABS_X, -127, 127, 0, 0);
  343. input_set_abs_params(input_dev, ABS_Y, -127, 127, 0, 0);
  344. udraw->joy_input_dev = input_dev;
  345. return true;
  346. }
  347. static int udraw_probe(struct hid_device *hdev, const struct hid_device_id *id)
  348. {
  349. struct udraw *udraw;
  350. int ret;
  351. udraw = devm_kzalloc(&hdev->dev, sizeof(struct udraw), GFP_KERNEL);
  352. if (!udraw)
  353. return -ENOMEM;
  354. udraw->hdev = hdev;
  355. udraw->last_two_finger_x = -1;
  356. udraw->last_two_finger_y = -1;
  357. hid_set_drvdata(hdev, udraw);
  358. ret = hid_parse(hdev);
  359. if (ret) {
  360. hid_err(hdev, "parse failed\n");
  361. return ret;
  362. }
  363. if (!udraw_setup_joypad(udraw, hdev) ||
  364. !udraw_setup_touch(udraw, hdev) ||
  365. !udraw_setup_pen(udraw, hdev) ||
  366. !udraw_setup_accel(udraw, hdev)) {
  367. hid_err(hdev, "could not allocate interfaces\n");
  368. return -ENOMEM;
  369. }
  370. ret = input_register_device(udraw->joy_input_dev) ||
  371. input_register_device(udraw->touch_input_dev) ||
  372. input_register_device(udraw->pen_input_dev) ||
  373. input_register_device(udraw->accel_input_dev);
  374. if (ret) {
  375. hid_err(hdev, "failed to register interfaces\n");
  376. return ret;
  377. }
  378. ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW | HID_CONNECT_DRIVER);
  379. if (ret) {
  380. hid_err(hdev, "hw start failed\n");
  381. return ret;
  382. }
  383. return 0;
  384. }
  385. static const struct hid_device_id udraw_devices[] = {
  386. { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
  387. { }
  388. };
  389. MODULE_DEVICE_TABLE(hid, udraw_devices);
  390. static struct hid_driver udraw_driver = {
  391. .name = "hid-udraw",
  392. .id_table = udraw_devices,
  393. .raw_event = udraw_raw_event,
  394. .probe = udraw_probe,
  395. };
  396. module_hid_driver(udraw_driver);