summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/stm/fts_lib/ftsGesture.c')
-rw-r--r--drivers/input/touchscreen/stm/fts_lib/ftsGesture.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c
new file mode 100644
index 000000000000..904c2ef8c90c
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c
@@ -0,0 +1,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;
+}