summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c
blob: 904c2ef8c90c969d49c120d00db293a9c2e0b40b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
/*
  *
  **************************************************************************
  **                        STMicroelectronics				 **
  **************************************************************************
  **                        marco.cali@st.com				**
  **************************************************************************
  *                                                                        *
  *                     FTS Gesture Utilities				**
  *                                                                        *
  **************************************************************************
  **************************************************************************
  *
  */

/*!
  * \file ftsGesture.c
  * \brief Contains all the functions and variable to handle the Gesture
  * Detection features
  */

#include "ftsSoftware.h"
#include "ftsCore.h"
#include "ftsError.h"
#include "ftsGesture.h"
#include "ftsIO.h"
#include "ftsTime.h"
#include "ftsTool.h"

/* /< store the gesture bitmask which the host want to enable.
 * If bit set 1 the corresponding gesture will be detected in Gesture Mode */
static u8 gesture_mask[GESTURE_MASK_SIZE] = { 0 };
/* /< store the x coordinates of the points draw by the user
 * when a gesture is detected */
u16 gesture_coordinates_x[GESTURE_MAX_COORDS_PAIRS_REPORT] = { 0 };
/* /< store the y coordinates of the points draw by the user
 * when a gesture is detected */
u16 gesture_coordinates_y[GESTURE_MAX_COORDS_PAIRS_REPORT] = { 0 };
/* /< number of coordinates pairs (points) reported with the detected gesture */
int gesture_coords_reported = ERROR_OP_NOT_ALLOW;
static u8 refreshGestureMask;	/* /< flag which indicate if there is
				 * the need to set the gesture mask in the FW */
struct mutex gestureMask_mutex;	/* /< mutex used to control access on gesture
				 * shared variables */

/**
  * Update the gesture mask stored in the driver and have to be used in gesture
  * mode
  * @param mask pointer to a byte array which store the gesture mask update
  * that want to be performed.
  * @param size dimension in byte of mask. This size can be <=
  * GESTURE_MASK_SIZE.
  * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos
  * and starting from the less significant byte.
  * @param en 0 = enable the gestures set in mask, 1 = disable the gestures set
  * in mask
  * @return OK if success or an error code which specify the type of error
  */
int updateGestureMask(u8 *mask, int size, int en)
{
	u8 temp;
	int i;

	if (mask != NULL) {
		if (size <= GESTURE_MASK_SIZE) {
			if (en == FEAT_ENABLE) {
				mutex_lock(&gestureMask_mutex);
				pr_info("updateGestureMask: setting gesture mask to enable...\n");
				if (mask != NULL)
					for (i = 0; i < size; i++)
						gesture_mask[i] =
							gesture_mask[i] |
							mask[i];
				/* back up of the gesture enabled */
				refreshGestureMask = 1;
				pr_info("updateGestureMask: gesture mask to enable SET!\n");
				mutex_unlock(&gestureMask_mutex);
				return OK;
			} else if (en == FEAT_DISABLE) {
				mutex_lock(&gestureMask_mutex);
				pr_info("updateGestureMask: setting gesture mask to disable...\n");
				for (i = 0; i < size; i++) {
					temp = gesture_mask[i] ^ mask[i];
					/* enabled XOR disabled */
					gesture_mask[i] = temp &
							  gesture_mask[i];
					/* temp AND enabled
					 * disable the gestures that were
					 * enabled */
				}
				pr_info("updateGestureMask: gesture mask to disable SET!\n");
				refreshGestureMask = 1;
				mutex_unlock(&gestureMask_mutex);
				return OK;
			} else {
				pr_err("updateGestureMask: Enable parameter Invalid! %d != %d or %d ERROR %08X",
					en,
					FEAT_DISABLE, FEAT_ENABLE,
					ERROR_OP_NOT_ALLOW);
				return ERROR_OP_NOT_ALLOW;
			}
		} else {
			pr_err("updateGestureMask: Size not valid! %d > %d ERROR %08X\n",
				size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW);
			return ERROR_OP_NOT_ALLOW;
		}
	} else {
		pr_err("updateGestureMask: Mask NULL! ERROR %08X\n",
			ERROR_OP_NOT_ALLOW);
		return ERROR_OP_NOT_ALLOW;
	}
}

/**
  * Enable in the FW the gesture mask to be used in gesture mode
  * @param mask pointer to a byte array which store the gesture mask update
  * that want to be sent to the FW, if NULL, will be used gesture_mask
  * set previously without any changes.
  * @param size dimension in byte of mask. This size can be <=
  * GESTURE_MASK_SIZE.
  * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos and
  * starting from the less significant byte.
  * @return OK if success or an error code which specify the type of error
  */
int enableGesture(u8 *mask, int size)
{
	int i, res;

	pr_info("Trying to enable gesture...\n");

	if (size <= GESTURE_MASK_SIZE) {
		mutex_lock(&gestureMask_mutex);
		if (mask != NULL)
			for (i = 0; i < size; i++)
				gesture_mask[i] = gesture_mask[i] | mask[i];
		/* back up of the gesture enabled */

		res = setFeatures(FEAT_SEL_GESTURE, gesture_mask,
				  GESTURE_MASK_SIZE);
		if (res < OK) {
			pr_err("enableGesture: ERROR %08X\n", res);
			goto END;
		}

		pr_info("enableGesture DONE!\n");
		res = OK;

END:
		mutex_unlock(&gestureMask_mutex);
		return res;
	} else {
		pr_err("enableGesture: Size not valid! %d > %d ERROR %08X\n",
			size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW);
		return ERROR_OP_NOT_ALLOW;
	}
}

/**
  * Disable in the FW the gesture mask to be used in gesture mode
  * @param mask pointer to a byte array which store the gesture mask update that
  * want to be sent to the FW, if NULL, all the gestures will be disabled.
  * @param size dimension in byte of mask. This size can be <=
  * GESTURE_MASK_SIZE.
  * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos and
  * starting from the less significant byte.
  * @return OK if success or an error code which specify the type of error
  */
int disableGesture(u8 *mask, int size)
{
	u8 temp;
	int i, res;
	u8 *pointer;


	pr_info("Trying to disable gesture...\n");


	if (size <= GESTURE_MASK_SIZE) {
		mutex_lock(&gestureMask_mutex);
		if (mask != NULL) {
			for (i = 0; i < size; i++) {
				temp = gesture_mask[i] ^ mask[i];
				/* enabled mask XOR disabled mask */
				gesture_mask[i] = temp & gesture_mask[i];
				/* temp AND enabled
				 * disable the gestures that are specified and
				 * previously enabled */
			}

			pointer = gesture_mask;
		} else {
			i = 0;	/* if NULL is passed disable all the possible
				 * gestures */
			pointer = (u8 *)&i;
		}

		res = setFeatures(FEAT_SEL_GESTURE, pointer, GESTURE_MASK_SIZE);
		if (res < OK) {
			pr_err("disableGesture: ERROR %08X\n", res);
			goto END;
		}

		pr_info("disableGesture DONE!\n");

		res = OK;

END:
		mutex_unlock(&gestureMask_mutex);
		return res;
	} else {
		pr_err("disableGesture: Size not valid! %d > %d ERROR %08X\n",
			size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW);
		return ERROR_OP_NOT_ALLOW;
	}
}

/**
  * Perform all the steps required to put the chip in gesture mode
  * @param reload if set to 1, before entering in gesture mode it will re-enable
  * in the FW the last defined gesture mask
  * @return OK if success or an error code which specify the type of error
  */
int enterGestureMode(int reload)
{
	int res, ret;

	res = fts_disableInterrupt();
	if (res < OK) {
		pr_err("enterGestureMode: ERROR %08X\n",
			res | ERROR_DISABLE_INTER);
		return res | ERROR_DISABLE_INTER;
	}

	if (reload == 1 || refreshGestureMask == 1) {
		res = enableGesture(NULL, 0);
		if (res < OK) {
			pr_err("enterGestureMode: enableGesture ERROR %08X\n",
				res);
			goto END;
		}

		refreshGestureMask = 0;
	}

	res = setScanMode(SCAN_MODE_LOW_POWER, 0);
	if (res < OK) {
		pr_err("enterGestureMode: enter gesture mode ERROR %08X\n",
			res);
		goto END;
	}

	res = OK;
END:
	ret = fts_enableInterrupt();
	if (ret < OK) {
		pr_err("enterGestureMode: fts_enableInterrupt ERROR %08X\n",
			res | ERROR_ENABLE_INTER);
		res |= ret | ERROR_ENABLE_INTER;
	}


	return res;
}

/**
  * Check if one or more Gesture IDs are currently enabled in gesture_mask
  * @return FEAT_ENABLE if one or more gesture ids are enabled, FEAT_DISABLE if
  * all the gesture ids are currently disabled
  */
int isAnyGestureActive(void)
{
	int res = 0;

	while (res < (GESTURE_MASK_SIZE - 1) && gesture_mask[res] == 0)
		/* -1 because in any case the last gesture mask byte will
		 * be evaluated with the following if */
		res++;

	if (gesture_mask[res] != 0) {
		pr_info("%s: Active Gestures Found! gesture_mask[%d] = %02X !\n",
			__func__, res, gesture_mask[res]);
		return FEAT_ENABLE;
	} else {
		pr_info("%s: All Gestures Disabled!\n", __func__);
		return FEAT_DISABLE;
	}
}


/**
  * Read from the frame buffer the gesture coordinates pairs of the points draw
  * by an user when a gesture is detected
  * @param event pointer to a byte array which contains the gesture event
  * reported
  * by the fw when a gesture is detected
  * @return OK if success or an error code which specify the type of error
  */
int readGestureCoords(u8 *event)
{
	int i = 0;
	u64 address = 0;
	int res;

	u8 val[GESTURE_MAX_COORDS_PAIRS_REPORT * 4];

	/* the max coordinates to read are GESTURE_COORDS_REPORT_MAX*4
	 * (because each coordinate is a short(*2) and we have x and y) */


	if (event[0] == EVT_ID_USER_REPORT &&
	    event[1] == EVT_TYPE_USER_GESTURE) {
		address = (event[4] << 8) | event[3]; /* Offset in framebuff */
		gesture_coords_reported = event[5];	/* number of pairs
							 * coords reported */
		if (gesture_coords_reported > GESTURE_MAX_COORDS_PAIRS_REPORT) {
			pr_err("%s:  FW reported more than %d points for the gestures! Decreasing to %d\n",
				__func__, gesture_coords_reported,
				GESTURE_MAX_COORDS_PAIRS_REPORT);
			gesture_coords_reported =
				GESTURE_MAX_COORDS_PAIRS_REPORT;
		}

		pr_info("%s: Offset: %llx , coords pairs = %d\n",
			 __func__, address, gesture_coords_reported);

		res = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address,
					val, (gesture_coords_reported * 2 * 2),
					DUMMY_FRAMEBUFFER);
		/* *2 because each coord is made by 2 bytes,
		 * *2 because there are x and y */
		if (res < OK) {
			pr_err("%s: Cannot read the coordinates! ERROR %08X\n",
				__func__, res);
			gesture_coords_reported = ERROR_OP_NOT_ALLOW;
			return res;
		}

		/* all the points of the gesture are stored in val */
		for (i = 0; i < gesture_coords_reported; i++) {
			gesture_coordinates_x[i] =
				(((u16)val[i * 2 + 1]) & 0x0F) << 8 |
				(((u16)val[i * 2]) & 0xFF);
			gesture_coordinates_y[i] =
				(((u16)val[gesture_coords_reported *
					2 + i * 2 + 1]) & 0x0F) << 8 |
				(((u16)val[gesture_coords_reported *
					2 + i * 2]) & 0xFF);
		}


		pr_info("%s: Reading Gesture Coordinates DONE!\n", __func__);
		return OK;
	} else {
		pr_err("%s: The event passsed as argument is invalid! ERROR %08X\n",
			__func__, ERROR_OP_NOT_ALLOW);
		return ERROR_OP_NOT_ALLOW;
	}
}

/**
  * Return the coordinates of the points stored during the last detected gesture
  * @param x output parameter which will store the address of the array
  * containing the x coordinates
  * @param y output parameter which will store the address of the array
  * containing the y coordinates
  * @return the number of points (x,y) stored and therefore the size of the x
  * and y array returned.
  */
int getGestureCoords(u16 **x, u16 **y)
{
	*x = gesture_coordinates_x;
	*y = gesture_coordinates_y;
	pr_info("%s: Number of gesture coordinates pairs returned = %d\n",
		__func__, gesture_coords_reported);
	return gesture_coords_reported;
}