1 /* 2 * HID driver for N-Trig touchscreens 3 * 4 * Copyright (c) 2008 Rafi Rubin 5 * Copyright (c) 2009 Stephane Chatty 6 * 7 */ 8 9 /* 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the Free 12 * Software Foundation; either version 2 of the License, or (at your option) 13 * any later version. 14 */ 15 16 #include <linux/device.h> 17 #include <linux/hid.h> 18 #include <linux/module.h> 19 20 #include "hid-ids.h" 21 22 #define NTRIG_DUPLICATE_USAGES 0x001 23 24 #define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ 25 EV_KEY, (c)) 26 27 struct ntrig_data { 28 /* Incoming raw values for a single contact */ 29 __u16 x, y, w, h; 30 __u16 id; 31 __u8 confidence; 32 33 bool reading_mt; 34 __u8 first_contact_confidence; 35 36 __u8 mt_footer[4]; 37 __u8 mt_foot_count; 38 }; 39 40 /* 41 * this driver is aimed at two firmware versions in circulation: 42 * - dual pen/finger single touch 43 * - finger multitouch, pen not working 44 */ 45 46 static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, 47 struct hid_field *field, struct hid_usage *usage, 48 unsigned long **bit, int *max) 49 { 50 /* No special mappings needed for the pen and single touch */ 51 if (field->physical) 52 return 0; 53 54 switch (usage->hid & HID_USAGE_PAGE) { 55 case HID_UP_GENDESK: 56 switch (usage->hid) { 57 case HID_GD_X: 58 hid_map_usage(hi, usage, bit, max, 59 EV_ABS, ABS_MT_POSITION_X); 60 input_set_abs_params(hi->input, ABS_X, 61 field->logical_minimum, 62 field->logical_maximum, 0, 0); 63 return 1; 64 case HID_GD_Y: 65 hid_map_usage(hi, usage, bit, max, 66 EV_ABS, ABS_MT_POSITION_Y); 67 input_set_abs_params(hi->input, ABS_Y, 68 field->logical_minimum, 69 field->logical_maximum, 0, 0); 70 return 1; 71 } 72 return 0; 73 74 case HID_UP_DIGITIZER: 75 switch (usage->hid) { 76 /* we do not want to map these for now */ 77 case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */ 78 case HID_DG_INPUTMODE: 79 case HID_DG_DEVICEINDEX: 80 case HID_DG_CONTACTMAX: 81 return -1; 82 83 /* width/height mapped on TouchMajor/TouchMinor/Orientation */ 84 case HID_DG_WIDTH: 85 hid_map_usage(hi, usage, bit, max, 86 EV_ABS, ABS_MT_TOUCH_MAJOR); 87 return 1; 88 case HID_DG_HEIGHT: 89 hid_map_usage(hi, usage, bit, max, 90 EV_ABS, ABS_MT_TOUCH_MINOR); 91 input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 92 0, 1, 0, 0); 93 return 1; 94 } 95 return 0; 96 97 case 0xff000000: 98 /* we do not want to map these: no input-oriented meaning */ 99 return -1; 100 } 101 102 return 0; 103 } 104 105 static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, 106 struct hid_field *field, struct hid_usage *usage, 107 unsigned long **bit, int *max) 108 { 109 /* No special mappings needed for the pen and single touch */ 110 if (field->physical) 111 return 0; 112 113 if (usage->type == EV_KEY || usage->type == EV_REL 114 || usage->type == EV_ABS) 115 clear_bit(usage->code, *bit); 116 117 return 0; 118 } 119 120 /* 121 * this function is called upon all reports 122 * so that we can filter contact point information, 123 * decide whether we are in multi or single touch mode 124 * and call input_mt_sync after each point if necessary 125 */ 126 static int ntrig_event (struct hid_device *hid, struct hid_field *field, 127 struct hid_usage *usage, __s32 value) 128 { 129 struct input_dev *input = field->hidinput->input; 130 struct ntrig_data *nd = hid_get_drvdata(hid); 131 132 /* No special handling needed for the pen */ 133 if (field->application == HID_DG_PEN) 134 return 0; 135 136 if (hid->claimed & HID_CLAIMED_INPUT) { 137 switch (usage->hid) { 138 case 0xff000001: 139 /* Tag indicating the start of a multitouch group */ 140 nd->reading_mt = 1; 141 nd->first_contact_confidence = 0; 142 break; 143 case HID_DG_CONFIDENCE: 144 nd->confidence = value; 145 break; 146 case HID_GD_X: 147 nd->x = value; 148 /* Clear the contact footer */ 149 nd->mt_foot_count = 0; 150 break; 151 case HID_GD_Y: 152 nd->y = value; 153 break; 154 case HID_DG_CONTACTID: 155 nd->id = value; 156 break; 157 case HID_DG_WIDTH: 158 nd->w = value; 159 break; 160 case HID_DG_HEIGHT: 161 nd->h = value; 162 /* 163 * when in single touch mode, this is the last 164 * report received in a finger event. We want 165 * to emit a normal (X, Y) position 166 */ 167 if (!nd->reading_mt) { 168 input_report_key(input, BTN_TOOL_DOUBLETAP, 169 (nd->confidence != 0)); 170 input_event(input, EV_ABS, ABS_X, nd->x); 171 input_event(input, EV_ABS, ABS_Y, nd->y); 172 } 173 break; 174 case 0xff000002: 175 /* 176 * we receive this when the device is in multitouch 177 * mode. The first of the three values tagged with 178 * this usage tells if the contact point is real 179 * or a placeholder 180 */ 181 182 /* Shouldn't get more than 4 footer packets, so skip */ 183 if (nd->mt_foot_count >= 4) 184 break; 185 186 nd->mt_footer[nd->mt_foot_count++] = value; 187 188 /* if the footer isn't complete break */ 189 if (nd->mt_foot_count != 4) 190 break; 191 192 /* Pen activity signal, trigger end of touch. */ 193 if (nd->mt_footer[2]) { 194 nd->confidence = 0; 195 break; 196 } 197 198 /* If the contact was invalid */ 199 if (!(nd->confidence && nd->mt_footer[0]) 200 || nd->w <= 250 201 || nd->h <= 190) { 202 nd->confidence = 0; 203 break; 204 } 205 206 /* emit a normal (X, Y) for the first point only */ 207 if (nd->id == 0) { 208 nd->first_contact_confidence = nd->confidence; 209 input_event(input, EV_ABS, ABS_X, nd->x); 210 input_event(input, EV_ABS, ABS_Y, nd->y); 211 } 212 input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); 213 input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); 214 if (nd->w > nd->h) { 215 input_event(input, EV_ABS, 216 ABS_MT_ORIENTATION, 1); 217 input_event(input, EV_ABS, 218 ABS_MT_TOUCH_MAJOR, nd->w); 219 input_event(input, EV_ABS, 220 ABS_MT_TOUCH_MINOR, nd->h); 221 } else { 222 input_event(input, EV_ABS, 223 ABS_MT_ORIENTATION, 0); 224 input_event(input, EV_ABS, 225 ABS_MT_TOUCH_MAJOR, nd->h); 226 input_event(input, EV_ABS, 227 ABS_MT_TOUCH_MINOR, nd->w); 228 } 229 input_mt_sync(field->hidinput->input); 230 break; 231 232 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ 233 if (!nd->reading_mt) 234 break; 235 236 nd->reading_mt = 0; 237 238 if (nd->first_contact_confidence) { 239 switch (value) { 240 case 0: /* for single touch devices */ 241 case 1: 242 input_report_key(input, 243 BTN_TOOL_DOUBLETAP, 1); 244 break; 245 case 2: 246 input_report_key(input, 247 BTN_TOOL_TRIPLETAP, 1); 248 break; 249 case 3: 250 default: 251 input_report_key(input, 252 BTN_TOOL_QUADTAP, 1); 253 } 254 input_report_key(input, BTN_TOUCH, 1); 255 } else { 256 input_report_key(input, 257 BTN_TOOL_DOUBLETAP, 0); 258 input_report_key(input, 259 BTN_TOOL_TRIPLETAP, 0); 260 input_report_key(input, 261 BTN_TOOL_QUADTAP, 0); 262 } 263 break; 264 265 default: 266 /* fallback to the generic hidinput handling */ 267 return 0; 268 } 269 } 270 271 /* we have handled the hidinput part, now remains hiddev */ 272 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) 273 hid->hiddev_hid_event(hid, field, usage, value); 274 275 return 1; 276 } 277 278 static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) 279 { 280 int ret; 281 struct ntrig_data *nd; 282 struct hid_input *hidinput; 283 struct input_dev *input; 284 285 if (id->driver_data) 286 hdev->quirks |= HID_QUIRK_MULTI_INPUT; 287 288 nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); 289 if (!nd) { 290 dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); 291 return -ENOMEM; 292 } 293 294 nd->reading_mt = 0; 295 hid_set_drvdata(hdev, nd); 296 297 ret = hid_parse(hdev); 298 if (ret) { 299 dev_err(&hdev->dev, "parse failed\n"); 300 goto err_free; 301 } 302 303 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); 304 if (ret) { 305 dev_err(&hdev->dev, "hw start failed\n"); 306 goto err_free; 307 } 308 309 310 list_for_each_entry(hidinput, &hdev->inputs, list) { 311 input = hidinput->input; 312 switch (hidinput->report->field[0]->application) { 313 case HID_DG_PEN: 314 input->name = "N-Trig Pen"; 315 break; 316 case HID_DG_TOUCHSCREEN: 317 __clear_bit(BTN_TOOL_PEN, input->keybit); 318 /* 319 * A little something special to enable 320 * two and three finger taps. 321 */ 322 __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); 323 __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); 324 __set_bit(BTN_TOOL_QUADTAP, input->keybit); 325 /* 326 * The physical touchscreen (single touch) 327 * input has a value for physical, whereas 328 * the multitouch only has logical input 329 * fields. 330 */ 331 input->name = 332 (hidinput->report->field[0] 333 ->physical) ? 334 "N-Trig Touchscreen" : 335 "N-Trig MultiTouch"; 336 break; 337 } 338 } 339 340 return 0; 341 err_free: 342 kfree(nd); 343 return ret; 344 } 345 346 static void ntrig_remove(struct hid_device *hdev) 347 { 348 hid_hw_stop(hdev); 349 kfree(hid_get_drvdata(hdev)); 350 } 351 352 static const struct hid_device_id ntrig_devices[] = { 353 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN), 354 .driver_data = NTRIG_DUPLICATE_USAGES }, 355 { } 356 }; 357 MODULE_DEVICE_TABLE(hid, ntrig_devices); 358 359 static const struct hid_usage_id ntrig_grabbed_usages[] = { 360 { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, 361 { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 } 362 }; 363 364 static struct hid_driver ntrig_driver = { 365 .name = "ntrig", 366 .id_table = ntrig_devices, 367 .probe = ntrig_probe, 368 .remove = ntrig_remove, 369 .input_mapping = ntrig_input_mapping, 370 .input_mapped = ntrig_input_mapped, 371 .usage_table = ntrig_grabbed_usages, 372 .event = ntrig_event, 373 }; 374 375 static int __init ntrig_init(void) 376 { 377 return hid_register_driver(&ntrig_driver); 378 } 379 380 static void __exit ntrig_exit(void) 381 { 382 hid_unregister_driver(&ntrig_driver); 383 } 384 385 module_init(ntrig_init); 386 module_exit(ntrig_exit); 387 MODULE_LICENSE("GPL"); 388