blob: 2810d42a2f4e720f3720355b10045b7488b4fb23 [file] [log] [blame]
/*
*
**************************************************************************
** 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("%s: Enable parameter Invalid! %d != %d or %d ERROR %08X\n",
__func__,
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_enableInterrupt(false);
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(true);
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;
}