1 /* 2 * Input Multitouch Library 3 * 4 * Copyright (c) 2008-2010 Henrik Rydberg 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 */ 10 11 #include <linux/input/mt.h> 12 #include <linux/export.h> 13 #include <linux/slab.h> 14 15 #define TRKID_SGN ((TRKID_MAX + 1) >> 1) 16 17 static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) 18 { 19 if (dev->absinfo && test_bit(src, dev->absbit)) { 20 dev->absinfo[dst] = dev->absinfo[src]; 21 dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); 22 } 23 } 24 25 /** 26 * input_mt_init_slots() - initialize MT input slots 27 * @dev: input device supporting MT events and finger tracking 28 * @num_slots: number of slots used by the device 29 * @flags: mt tasks to handle in core 30 * 31 * This function allocates all necessary memory for MT slot handling 32 * in the input device, prepares the ABS_MT_SLOT and 33 * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. 34 * Depending on the flags set, it also performs pointer emulation and 35 * frame synchronization. 36 * 37 * May be called repeatedly. Returns -EINVAL if attempting to 38 * reinitialize with a different number of slots. 39 */ 40 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, 41 unsigned int flags) 42 { 43 struct input_mt *mt = dev->mt; 44 int i; 45 46 if (!num_slots) 47 return 0; 48 if (mt) 49 return mt->num_slots != num_slots ? -EINVAL : 0; 50 51 mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL); 52 if (!mt) 53 goto err_mem; 54 55 mt->num_slots = num_slots; 56 mt->flags = flags; 57 input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); 58 input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); 59 60 if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) { 61 __set_bit(EV_KEY, dev->evbit); 62 __set_bit(BTN_TOUCH, dev->keybit); 63 64 copy_abs(dev, ABS_X, ABS_MT_POSITION_X); 65 copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y); 66 copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE); 67 } 68 if (flags & INPUT_MT_POINTER) { 69 __set_bit(BTN_TOOL_FINGER, dev->keybit); 70 __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); 71 if (num_slots >= 3) 72 __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); 73 if (num_slots >= 4) 74 __set_bit(BTN_TOOL_QUADTAP, dev->keybit); 75 if (num_slots >= 5) 76 __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); 77 __set_bit(INPUT_PROP_POINTER, dev->propbit); 78 } 79 if (flags & INPUT_MT_DIRECT) 80 __set_bit(INPUT_PROP_DIRECT, dev->propbit); 81 if (flags & INPUT_MT_TRACK) { 82 unsigned int n2 = num_slots * num_slots; 83 mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL); 84 if (!mt->red) 85 goto err_mem; 86 } 87 88 /* Mark slots as 'unused' */ 89 for (i = 0; i < num_slots; i++) 90 input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); 91 92 dev->mt = mt; 93 return 0; 94 err_mem: 95 kfree(mt); 96 return -ENOMEM; 97 } 98 EXPORT_SYMBOL(input_mt_init_slots); 99 100 /** 101 * input_mt_destroy_slots() - frees the MT slots of the input device 102 * @dev: input device with allocated MT slots 103 * 104 * This function is only needed in error path as the input core will 105 * automatically free the MT slots when the device is destroyed. 106 */ 107 void input_mt_destroy_slots(struct input_dev *dev) 108 { 109 if (dev->mt) { 110 kfree(dev->mt->red); 111 kfree(dev->mt); 112 } 113 dev->mt = NULL; 114 } 115 EXPORT_SYMBOL(input_mt_destroy_slots); 116 117 /** 118 * input_mt_report_slot_state() - report contact state 119 * @dev: input device with allocated MT slots 120 * @tool_type: the tool type to use in this slot 121 * @active: true if contact is active, false otherwise 122 * 123 * Reports a contact via ABS_MT_TRACKING_ID, and optionally 124 * ABS_MT_TOOL_TYPE. If active is true and the slot is currently 125 * inactive, or if the tool type is changed, a new tracking id is 126 * assigned to the slot. The tool type is only reported if the 127 * corresponding absbit field is set. 128 */ 129 void input_mt_report_slot_state(struct input_dev *dev, 130 unsigned int tool_type, bool active) 131 { 132 struct input_mt *mt = dev->mt; 133 struct input_mt_slot *slot; 134 int id; 135 136 if (!mt) 137 return; 138 139 slot = &mt->slots[mt->slot]; 140 slot->frame = mt->frame; 141 142 if (!active) { 143 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); 144 return; 145 } 146 147 id = input_mt_get_value(slot, ABS_MT_TRACKING_ID); 148 if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type) 149 id = input_mt_new_trkid(mt); 150 151 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id); 152 input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type); 153 } 154 EXPORT_SYMBOL(input_mt_report_slot_state); 155 156 /** 157 * input_mt_report_finger_count() - report contact count 158 * @dev: input device with allocated MT slots 159 * @count: the number of contacts 160 * 161 * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, 162 * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP. 163 * 164 * The input core ensures only the KEY events already setup for 165 * this device will produce output. 166 */ 167 void input_mt_report_finger_count(struct input_dev *dev, int count) 168 { 169 input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1); 170 input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2); 171 input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3); 172 input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4); 173 input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5); 174 } 175 EXPORT_SYMBOL(input_mt_report_finger_count); 176 177 /** 178 * input_mt_report_pointer_emulation() - common pointer emulation 179 * @dev: input device with allocated MT slots 180 * @use_count: report number of active contacts as finger count 181 * 182 * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and 183 * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true. 184 * 185 * The input core ensures only the KEY and ABS axes already setup for 186 * this device will produce output. 187 */ 188 void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) 189 { 190 struct input_mt *mt = dev->mt; 191 struct input_mt_slot *oldest; 192 int oldid, count, i; 193 194 if (!mt) 195 return; 196 197 oldest = NULL; 198 oldid = mt->trkid; 199 count = 0; 200 201 for (i = 0; i < mt->num_slots; ++i) { 202 struct input_mt_slot *ps = &mt->slots[i]; 203 int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); 204 205 if (id < 0) 206 continue; 207 if ((id - oldid) & TRKID_SGN) { 208 oldest = ps; 209 oldid = id; 210 } 211 count++; 212 } 213 214 input_event(dev, EV_KEY, BTN_TOUCH, count > 0); 215 if (use_count) 216 input_mt_report_finger_count(dev, count); 217 218 if (oldest) { 219 int x = input_mt_get_value(oldest, ABS_MT_POSITION_X); 220 int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y); 221 222 input_event(dev, EV_ABS, ABS_X, x); 223 input_event(dev, EV_ABS, ABS_Y, y); 224 225 if (test_bit(ABS_MT_PRESSURE, dev->absbit)) { 226 int p = input_mt_get_value(oldest, ABS_MT_PRESSURE); 227 input_event(dev, EV_ABS, ABS_PRESSURE, p); 228 } 229 } else { 230 if (test_bit(ABS_MT_PRESSURE, dev->absbit)) 231 input_event(dev, EV_ABS, ABS_PRESSURE, 0); 232 } 233 } 234 EXPORT_SYMBOL(input_mt_report_pointer_emulation); 235 236 /** 237 * input_mt_sync_frame() - synchronize mt frame 238 * @dev: input device with allocated MT slots 239 * 240 * Close the frame and prepare the internal state for a new one. 241 * Depending on the flags, marks unused slots as inactive and performs 242 * pointer emulation. 243 */ 244 void input_mt_sync_frame(struct input_dev *dev) 245 { 246 struct input_mt *mt = dev->mt; 247 struct input_mt_slot *s; 248 249 if (!mt) 250 return; 251 252 if (mt->flags & INPUT_MT_DROP_UNUSED) { 253 for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { 254 if (input_mt_is_used(mt, s)) 255 continue; 256 input_mt_slot(dev, s - mt->slots); 257 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); 258 } 259 } 260 261 input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER)); 262 263 mt->frame++; 264 } 265 EXPORT_SYMBOL(input_mt_sync_frame); 266 267 static int adjust_dual(int *begin, int step, int *end, int eq) 268 { 269 int f, *p, s, c; 270 271 if (begin == end) 272 return 0; 273 274 f = *begin; 275 p = begin + step; 276 s = p == end ? f + 1 : *p; 277 278 for (; p != end; p += step) 279 if (*p < f) 280 s = f, f = *p; 281 else if (*p < s) 282 s = *p; 283 284 c = (f + s + 1) / 2; 285 if (c == 0 || (c > 0 && !eq)) 286 return 0; 287 if (s < 0) 288 c *= 2; 289 290 for (p = begin; p != end; p += step) 291 *p -= c; 292 293 return (c < s && s <= 0) || (f >= 0 && f < c); 294 } 295 296 static void find_reduced_matrix(int *w, int nr, int nc, int nrc) 297 { 298 int i, k, sum; 299 300 for (k = 0; k < nrc; k++) { 301 for (i = 0; i < nr; i++) 302 adjust_dual(w + i, nr, w + i + nrc, nr <= nc); 303 sum = 0; 304 for (i = 0; i < nrc; i += nr) 305 sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr); 306 if (!sum) 307 break; 308 } 309 } 310 311 static int input_mt_set_matrix(struct input_mt *mt, 312 const struct input_mt_pos *pos, int num_pos) 313 { 314 const struct input_mt_pos *p; 315 struct input_mt_slot *s; 316 int *w = mt->red; 317 int x, y; 318 319 for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { 320 if (!input_mt_is_active(s)) 321 continue; 322 x = input_mt_get_value(s, ABS_MT_POSITION_X); 323 y = input_mt_get_value(s, ABS_MT_POSITION_Y); 324 for (p = pos; p != pos + num_pos; p++) { 325 int dx = x - p->x, dy = y - p->y; 326 *w++ = dx * dx + dy * dy; 327 } 328 } 329 330 return w - mt->red; 331 } 332 333 static void input_mt_set_slots(struct input_mt *mt, 334 int *slots, int num_pos) 335 { 336 struct input_mt_slot *s; 337 int *w = mt->red, *p; 338 339 for (p = slots; p != slots + num_pos; p++) 340 *p = -1; 341 342 for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { 343 if (!input_mt_is_active(s)) 344 continue; 345 for (p = slots; p != slots + num_pos; p++) 346 if (*w++ < 0) 347 *p = s - mt->slots; 348 } 349 350 for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { 351 if (input_mt_is_active(s)) 352 continue; 353 for (p = slots; p != slots + num_pos; p++) 354 if (*p < 0) { 355 *p = s - mt->slots; 356 break; 357 } 358 } 359 } 360 361 /** 362 * input_mt_assign_slots() - perform a best-match assignment 363 * @dev: input device with allocated MT slots 364 * @slots: the slot assignment to be filled 365 * @pos: the position array to match 366 * @num_pos: number of positions 367 * 368 * Performs a best match against the current contacts and returns 369 * the slot assignment list. New contacts are assigned to unused 370 * slots. 371 * 372 * Returns zero on success, or negative error in case of failure. 373 */ 374 int input_mt_assign_slots(struct input_dev *dev, int *slots, 375 const struct input_mt_pos *pos, int num_pos) 376 { 377 struct input_mt *mt = dev->mt; 378 int nrc; 379 380 if (!mt || !mt->red) 381 return -ENXIO; 382 if (num_pos > mt->num_slots) 383 return -EINVAL; 384 if (num_pos < 1) 385 return 0; 386 387 nrc = input_mt_set_matrix(mt, pos, num_pos); 388 find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc); 389 input_mt_set_slots(mt, slots, num_pos); 390 391 return 0; 392 } 393 EXPORT_SYMBOL(input_mt_assign_slots); 394 395 /** 396 * input_mt_get_slot_by_key() - return slot matching key 397 * @dev: input device with allocated MT slots 398 * @key: the key of the sought slot 399 * 400 * Returns the slot of the given key, if it exists, otherwise 401 * set the key on the first unused slot and return. 402 * 403 * If no available slot can be found, -1 is returned. 404 */ 405 int input_mt_get_slot_by_key(struct input_dev *dev, int key) 406 { 407 struct input_mt *mt = dev->mt; 408 struct input_mt_slot *s; 409 410 if (!mt) 411 return -1; 412 413 for (s = mt->slots; s != mt->slots + mt->num_slots; s++) 414 if (input_mt_is_active(s) && s->key == key) 415 return s - mt->slots; 416 417 for (s = mt->slots; s != mt->slots + mt->num_slots; s++) 418 if (!input_mt_is_active(s)) { 419 s->key = key; 420 return s - mt->slots; 421 } 422 423 return -1; 424 } 425 EXPORT_SYMBOL(input_mt_get_slot_by_key); 426