blob: 289616669f48fe77a3ee63ff2335332b2ee220bd [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/* Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/sched.h>
15#include <linux/slab.h>
16#include <linux/miscdevice.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/input/mt.h>
20#include <linux/syscalls.h>
21#include "usfcdev.h"
22
23#define UNDEF_ID 0xffffffff
24#define SLOT_CMD_ID 0
25#define MAX_RETRIES 10
26
27enum usdev_event_status {
28 USFCDEV_EVENT_ENABLED,
29 USFCDEV_EVENT_DISABLING,
30 USFCDEV_EVENT_DISABLED,
31};
32
33struct usfcdev_event {
34 bool (*match_cb)(uint16_t, struct input_dev *dev);
35 bool registered_event;
36 bool interleaved;
37 enum usdev_event_status event_status;
38};
39static struct usfcdev_event s_usfcdev_events[MAX_EVENT_TYPE_NUM];
40
41struct usfcdev_input_command {
42 unsigned int type;
43 unsigned int code;
44 unsigned int value;
45};
46
47static long s_usf_pid;
48
49static bool usfcdev_filter(struct input_handle *handle,
50 unsigned int type, unsigned int code, int value);
51static bool usfcdev_match(struct input_handler *handler,
52 struct input_dev *dev);
53static int usfcdev_connect(struct input_handler *handler,
54 struct input_dev *dev,
55 const struct input_device_id *id);
56static void usfcdev_disconnect(struct input_handle *handle);
57
58static const struct input_device_id usfc_tsc_ids[] = {
59 {
60 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
61 INPUT_DEVICE_ID_MATCH_KEYBIT |
62 INPUT_DEVICE_ID_MATCH_ABSBIT,
63 .evbit = { BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY) },
64 .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
65 /* assumption: ABS_X & ABS_Y are in the same long */
66 .absbit = { [BIT_WORD(ABS_X)] = BIT_MASK(ABS_X) |
67 BIT_MASK(ABS_Y) },
68 },
69 {
70 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
71 INPUT_DEVICE_ID_MATCH_KEYBIT |
72 INPUT_DEVICE_ID_MATCH_ABSBIT,
73 .evbit = { BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY) },
74 .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
75 /* assumption: MT_.._X & MT_.._Y are in the same long */
76 .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
77 BIT_MASK(ABS_MT_POSITION_X) |
78 BIT_MASK(ABS_MT_POSITION_Y) },
79 },
80 { } /* Terminating entry */
81};
82
83MODULE_DEVICE_TABLE(input, usfc_tsc_ids);
84
85static struct input_handler s_usfc_handlers[MAX_EVENT_TYPE_NUM] = {
86 { /* TSC handler */
87 .filter = usfcdev_filter,
88 .match = usfcdev_match,
89 .connect = usfcdev_connect,
90 .disconnect = usfcdev_disconnect,
91 /* .minor can be used as index in the container, */
92 /* because .fops isn't supported */
93 .minor = TSC_EVENT_TYPE_IND,
94 .name = "usfc_tsc_handler",
95 .id_table = usfc_tsc_ids,
96 },
97};
98
99/*
100 * For each event type, there are a number conflicting devices (handles)
101 * The first registered device (primary) is real TSC device; it's mandatory
102 * Optionally, later registered devices are simulated ones.
103 * They are dynamically managed
104 * The primary device's handles are stored in the below static array
105 */
106static struct input_handle s_usfc_primary_handles[MAX_EVENT_TYPE_NUM] = {
107 { /* TSC handle */
108 .handler = &s_usfc_handlers[TSC_EVENT_TYPE_IND],
109 .name = "usfc_tsc_handle",
110 },
111};
112
113static struct usfcdev_input_command initial_clear_cmds[] = {
114 {EV_ABS, ABS_PRESSURE, 0},
115 {EV_KEY, BTN_TOUCH, 0},
116};
117
118static struct usfcdev_input_command slot_clear_cmds[] = {
119 {EV_ABS, ABS_MT_SLOT, 0},
120 {EV_ABS, ABS_MT_TRACKING_ID, UNDEF_ID},
121};
122
123static struct usfcdev_input_command no_filter_cmds[] = {
124 {EV_ABS, ABS_MT_SLOT, 0},
125 {EV_ABS, ABS_MT_TRACKING_ID, UNDEF_ID},
126 {EV_SYN, SYN_REPORT, 0},
127};
128
129static bool usfcdev_match(struct input_handler *handler, struct input_dev *dev)
130{
131 bool rc = false;
132 int ind = handler->minor;
133
134 pr_debug("%s: name=[%s]; ind=%d\n", __func__, dev->name, ind);
135
136 if (s_usfcdev_events[ind].registered_event &&
137 s_usfcdev_events[ind].match_cb) {
138 rc = (*s_usfcdev_events[ind].match_cb)((uint16_t)ind, dev);
139 pr_debug("%s: [%s]; rc=%d\n", __func__, dev->name, rc);
140 }
141 return rc;
142}
143
144static int usfcdev_connect(struct input_handler *handler, struct input_dev *dev,
145 const struct input_device_id *id)
146{
147 int ret = 0;
148 uint16_t ind = handler->minor;
149 struct input_handle *usfc_handle = NULL;
150
151 if (s_usfc_primary_handles[ind].dev == NULL) {
152 pr_debug("%s: primary device; ind=%d\n",
153 __func__,
154 ind);
155 usfc_handle = &s_usfc_primary_handles[ind];
156 } else {
157 pr_debug("%s: secondary device; ind=%d\n",
158 __func__,
159 ind);
160 usfc_handle = kzalloc(sizeof(struct input_handle),
161 GFP_KERNEL);
162 if (!usfc_handle)
163 return -ENOMEM;
164
165 usfc_handle->handler = &s_usfc_handlers[ind];
166 usfc_handle->name = s_usfc_primary_handles[ind].name;
167 }
168 usfc_handle->dev = dev;
169 ret = input_register_handle(usfc_handle);
170 pr_debug("%s: name=[%s]; ind=%d; dev=0x%pK\n",
171 __func__,
172 dev->name,
173 ind,
174 usfc_handle->dev);
175 if (ret)
176 pr_err("%s: input_register_handle[%d] failed: ret=%d\n",
177 __func__,
178 ind,
179 ret);
180 else {
181 ret = input_open_device(usfc_handle);
182 if (ret) {
183 pr_err("%s: input_open_device[%d] failed: ret=%d\n",
184 __func__,
185 ind,
186 ret);
187 input_unregister_handle(usfc_handle);
188 } else
189 pr_debug("%s: device[%d] is opened\n",
190 __func__,
191 ind);
192 }
193
194 return ret;
195}
196
197static void usfcdev_disconnect(struct input_handle *handle)
198{
199 int ind = handle->handler->minor;
200
201 input_close_device(handle);
202 input_unregister_handle(handle);
203 pr_debug("%s: handle[%d], name=[%s] is disconnected\n",
204 __func__,
205 ind,
206 handle->dev->name);
207 if (s_usfc_primary_handles[ind].dev == handle->dev)
208 s_usfc_primary_handles[ind].dev = NULL;
209 else
210 kfree(handle);
211}
212
213static bool usfcdev_filter(struct input_handle *handle,
214 unsigned int type, unsigned int code, int value)
215{
216 uint16_t i = 0;
217 uint16_t ind = (uint16_t)handle->handler->minor;
218 bool rc = (s_usfcdev_events[ind].event_status != USFCDEV_EVENT_ENABLED);
219
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530220 if (s_usf_pid == current->pid) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530221 /* Pass events from usfcdev driver */
222 rc = false;
223 pr_debug("%s: event_type=%d; type=%d; code=%d; val=%d",
224 __func__,
225 ind,
226 type,
227 code,
228 value);
229 } else if (s_usfcdev_events[ind].event_status ==
230 USFCDEV_EVENT_DISABLING) {
231 uint32_t u_value = value;
232
233 s_usfcdev_events[ind].interleaved = true;
234 /* Pass events for freeing slots from TSC driver */
235 for (i = 0; i < ARRAY_SIZE(no_filter_cmds); ++i) {
236 if ((no_filter_cmds[i].type == type) &&
237 (no_filter_cmds[i].code == code) &&
238 (no_filter_cmds[i].value <= u_value)) {
239 rc = false;
240 pr_debug("%s: no_filter_cmds[%d]; %d",
241 __func__,
242 i,
243 no_filter_cmds[i].value);
244 break;
245 }
246 }
247 }
248
249 return rc;
250}
251
252bool usfcdev_register(
253 uint16_t event_type_ind,
254 bool (*match_cb)(uint16_t, struct input_dev *dev))
255{
256 int ret = 0;
257 bool rc = false;
258
259 if ((event_type_ind >= MAX_EVENT_TYPE_NUM) || !match_cb) {
260 pr_err("%s: wrong input: event_type_ind=%d; match_cb=0x%pK\n",
261 __func__,
262 event_type_ind,
263 match_cb);
264 return false;
265 }
266
267 if (s_usfcdev_events[event_type_ind].registered_event) {
268 pr_info("%s: handler[%d] was already registered\n",
269 __func__,
270 event_type_ind);
271 return true;
272 }
273
274 s_usfcdev_events[event_type_ind].registered_event = true;
275 s_usfcdev_events[event_type_ind].match_cb = match_cb;
276 s_usfcdev_events[event_type_ind].event_status = USFCDEV_EVENT_ENABLED;
277 ret = input_register_handler(&s_usfc_handlers[event_type_ind]);
278 if (!ret) {
279 rc = true;
280 pr_debug("%s: handler[%d] was registered\n",
281 __func__,
282 event_type_ind);
283 } else {
284 s_usfcdev_events[event_type_ind].registered_event = false;
285 s_usfcdev_events[event_type_ind].match_cb = NULL;
286 pr_err("%s: handler[%d] registration failed: ret=%d\n",
287 __func__,
288 event_type_ind,
289 ret);
290 }
291
292 return rc;
293}
294
295void usfcdev_unregister(uint16_t event_type_ind)
296{
297 if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
298 pr_err("%s: wrong input: event_type_ind=%d\n",
299 __func__,
300 event_type_ind);
301 return;
302 }
303 if (s_usfcdev_events[event_type_ind].registered_event) {
304 input_unregister_handler(&s_usfc_handlers[event_type_ind]);
305 pr_debug("%s: handler[%d] was unregistered\n",
306 __func__,
307 event_type_ind);
308 s_usfcdev_events[event_type_ind].registered_event = false;
309 s_usfcdev_events[event_type_ind].match_cb = NULL;
310 s_usfcdev_events[event_type_ind].event_status =
311 USFCDEV_EVENT_ENABLED;
312
313 }
314}
315
316static inline void usfcdev_send_cmd(
317 struct input_dev *dev,
318 struct usfcdev_input_command cmd)
319{
320 input_event(dev, cmd.type, cmd.code, cmd.value);
321}
322
323static void usfcdev_clean_dev(uint16_t event_type_ind)
324{
325 struct input_dev *dev = NULL;
326 int i;
327 int j;
328 int retries = 0;
329
330 if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
331 pr_err("%s: wrong input: event_type_ind=%d\n",
332 __func__,
333 event_type_ind);
334 return;
335 }
336 /* Only primary device must exist */
337 dev = s_usfc_primary_handles[event_type_ind].dev;
338 if (dev == NULL) {
339 pr_err("%s: NULL primary device\n",
340 __func__);
341 return;
342 }
343
344 for (i = 0; i < ARRAY_SIZE(initial_clear_cmds); i++)
345 usfcdev_send_cmd(dev, initial_clear_cmds[i]);
346 input_sync(dev);
347
348 /* Send commands to free all slots */
349 for (i = 0; i < dev->mt->num_slots; i++) {
350 s_usfcdev_events[event_type_ind].interleaved = false;
351 if (input_mt_get_value(&dev->mt->slots[i],
352 ABS_MT_TRACKING_ID) < 0) {
353 pr_debug("%s: skipping slot %d",
354 __func__, i);
355 continue;
356 }
357 slot_clear_cmds[SLOT_CMD_ID].value = i;
358 for (j = 0; j < ARRAY_SIZE(slot_clear_cmds); j++)
359 usfcdev_send_cmd(dev, slot_clear_cmds[j]);
360
361 if (s_usfcdev_events[event_type_ind].interleaved) {
362 pr_debug("%s: interleaved(%d): slot(%d)",
363 __func__, i, dev->mt->slot);
364 if (retries++ < MAX_RETRIES) {
365 --i;
366 continue;
367 }
368 pr_warn("%s: index(%d) reached max retires",
369 __func__, i);
370 }
371
372 retries = 0;
373 input_sync(dev);
374 }
375}
376
377bool usfcdev_set_filter(uint16_t event_type_ind, bool filter)
378{
379 bool rc = true;
380
381 if (event_type_ind >= MAX_EVENT_TYPE_NUM) {
382 pr_err("%s: wrong input: event_type_ind=%d\n",
383 __func__,
384 event_type_ind);
385 return false;
386 }
387
388 if (s_usfcdev_events[event_type_ind].registered_event) {
389
390 pr_debug("%s: event_type[%d]; filter=%d\n",
391 __func__,
392 event_type_ind,
393 filter
394 );
395 if (filter) {
396 s_usfcdev_events[event_type_ind].event_status =
397 USFCDEV_EVENT_DISABLING;
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530398 s_usf_pid = current->pid;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530399 usfcdev_clean_dev(event_type_ind);
400 s_usfcdev_events[event_type_ind].event_status =
401 USFCDEV_EVENT_DISABLED;
402 } else
403 s_usfcdev_events[event_type_ind].event_status =
404 USFCDEV_EVENT_ENABLED;
405 } else {
406 pr_err("%s: event_type[%d] isn't registered\n",
407 __func__,
408 event_type_ind);
409 rc = false;
410 }
411
412 return rc;
413}