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