diff options
Diffstat (limited to 'tcm')
-rw-r--r-- | tcm/synaptics_touchcom_core_dev.h | 166 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_core_v1.c | 131 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_core_v2.c | 135 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_base.c | 100 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_base.h | 27 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_reflash.c | 2 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_touch.c | 45 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_touch.h | 13 |
8 files changed, 429 insertions, 190 deletions
diff --git a/tcm/synaptics_touchcom_core_dev.h b/tcm/synaptics_touchcom_core_dev.h index f877af1..1b0eb2c 100644 --- a/tcm/synaptics_touchcom_core_dev.h +++ b/tcm/synaptics_touchcom_core_dev.h @@ -44,7 +44,7 @@ #include "syna_tcm2_platform.h" -#define SYNA_TCM_CORE_LIB_VERSION 0x0113 +#define SYNA_TCM_CORE_LIB_VERSION 0x0115 /** @@ -532,9 +532,10 @@ struct tcm_touch_data_blob { }; /** - * @section: Callback function used for custom entity parsing in touch report + * @section: Callback function used to parse custom touch entity * - * Allow to implement the custom handling for"new" custom entity in touch report + * Allow to invoke the customized implementation to parse touch data inside + * touch report. * * @param * [ in] code: the code of current touch entity @@ -545,20 +546,21 @@ struct tcm_touch_data_blob { * [in/out] report_offset: offset of current position in touch report, * the updated position should be returned. * [ in] report_size: size of given touch report - * [ in] callback_data: pointer to caller data passed to callback function + * [ in] callback_data: pointer to caller data * * @return * on success, 0 or positive value; otherwise, negative value on error. */ -typedef int (*tcm_touch_data_parse_callback_t) (const unsigned char code, +typedef int (*tcm_custom_touch_entity_callback_t) (const unsigned char code, const unsigned char *config, unsigned int *config_offset, const unsigned char *report, unsigned int *report_offset, unsigned int report_size, void *callback_data); /** - * @section: Callback function used for custom gesture parsing in touch report + * @section: Callback function used to parse custom gesture data * - * Allow to implement the custom handling for gesture data. + * Allow to invoke the customized implementation to get gesture data inside + * touch report. * * @param * [ in] code: the code of current touch entity @@ -569,17 +571,31 @@ typedef int (*tcm_touch_data_parse_callback_t) (const unsigned char code, * [in/out] report_offset: offset of current position in touch report, * the updated position should be returned. * [ in] report_size: size of given touch report - * [ in] callback_data: pointer to caller data passed to callback function + * [ in] callback_data: pointer to caller data * * @return * on success, 0 or positive value; otherwise, negative value on error. */ -typedef int (*tcm_gesture_parse_callback_t) (const unsigned char code, +typedef int (*tcm_custom_gesture_callback_t) (const unsigned char code, const unsigned char *config, unsigned int *config_offset, const unsigned char *report, unsigned int *report_offset, unsigned int report_size, void *callback_data); /** + * @section: Callback function being invoked once getting a reset + * + * Allow to invoke the customized implementation to handle the unexpected reset + * including self-reset, external reset, and so on. + * + * @param + * [ in] callback_data: pointer to caller data + * + * @return + * none. + */ +typedef void (*tcm_reset_occurrence_callback_t) (void *callback_data); + +/** * @section: TouchComm Message Handling Wrapper * * The structure contains the essential buffers and parameters to implement @@ -622,6 +638,11 @@ struct tcm_message_data_blob { */ bool predict_reads; unsigned int predict_length; + + /* variables for the crc appended + */ + bool has_crc; + unsigned short crc_bytes; }; /** @@ -723,11 +744,16 @@ struct tcm_dev { /* callbacks * custom_touch_data_parse_func: custom touch data entity parsing * custom_gesture_parse_func : custom gesture data entity parsing + * cb_custom_touch_entity: callback to parse custom touch entity + * cb_custom_gesture : callback to parse custom gesture + * cb_reset_occurrence : callback once reset occurrence */ - tcm_touch_data_parse_callback_t custom_touch_data_parse_func; - void *cbdata_touch_data_parse; - tcm_gesture_parse_callback_t custom_gesture_parse_func; - void *cbdata_gesture_parse; + tcm_custom_touch_entity_callback_t cb_custom_touch_entity; + void *cbdata_touch_entity; + tcm_custom_gesture_callback_t cb_custom_gesture; + void *cbdata_gesture; + tcm_reset_occurrence_callback_t cb_reset_occurrence; + void *cbdata_reset; }; /* end of structure syna_tcm_dev */ @@ -1100,5 +1126,119 @@ static inline int syna_tcm_write(struct tcm_dev *tcm_dev, return hw_if->ops_write_data(hw_if, wr_data, wr_len); } +/** + * @section: CRC Calculation Function + * + * @brief: syna_tcm_crc6 + * Return the crc-6 calculated + * + * @brief: syna_tcm_crc16 + * Return the crc-16 calculated + */ + +/** + * syna_tcm_crc6() + * + * Calculate the crc-6 with polynomial and return + * + * @param + * [ in] p: byte array for the calculation + * [ in] bits: number of bits + * + * @return + * the crc-6 value + */ +static inline unsigned char syna_tcm_crc6(unsigned char *p, + unsigned int bits) +{ + unsigned short r = 0x003F << 2; + unsigned short x; + static unsigned short crc6_table[16] = { + 0, 268, 536, 788, 1072, 1340, 1576, 1828, + 2144, 2412, 2680, 2932, 3152, 3420, 3656, 3908 + }; + + for (; bits > 8; bits -= 8) { + r ^= *p++; + r = (r << 4) ^ crc6_table[r >> 4]; + r = (r << 4) ^ crc6_table[r >> 4]; + } + + if (bits > 0) { + x = *p; + while (bits--) { + if (x & 0x80) + r ^= 0x80; + + x <<= 1; + r <<= 1; + if (r & 0x100) + r ^= (0x03 << 2); + } + } + + return (unsigned char)((r >> 2) & 0x3F); +} +/** + * syna_tcm_crc16() + * + * Calculate the crc-16 for TouchCom packet. + * + * @param + * [ in] p: byte array for the calculation + * [ in] len: length in bytes + * [ in] val: the initial value given + * + * @return + * the crc-16 value + */ +static inline unsigned short syna_tcm_crc16(unsigned char *p, + unsigned int len, unsigned short val) +{ + unsigned short r = val; + static unsigned short crc16_table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 + }; + + if (len == 0) + return r; + + while (len--) + r = (r << 8) ^ crc16_table[(r >> 8) ^ *p++]; + + return r; +} + #endif /* end of _SYNAPTICS_TOUCHCOM_CORE_DEV_H_ */ diff --git a/tcm/synaptics_touchcom_core_v1.c b/tcm/synaptics_touchcom_core_v1.c index e18d8ee..75d4c4a 100644 --- a/tcm/synaptics_touchcom_core_v1.c +++ b/tcm/synaptics_touchcom_core_v1.c @@ -184,7 +184,6 @@ static void syna_tcm_v1_dispatch_report(struct tcm_dev *tcm_dev) case CMD_RUN_APPLICATION_FIRMWARE: case CMD_ENTER_PRODUCTION_TEST_MODE: case CMD_ROMBOOT_RUN_BOOTLOADER_FIRMWARE: - tcm_msg->status_report_code = STATUS_OK; tcm_msg->response_code = STATUS_OK; ATOMIC_SET(tcm_msg->command_status, CMD_STATE_IDLE); @@ -197,6 +196,12 @@ static void syna_tcm_v1_dispatch_report(struct tcm_dev *tcm_dev) syna_pal_completion_complete(cmd_completion); goto exit; } + } else { + /* invoke callback to handle unexpected reset if doesn't + * result from command + */ + if (tcm_dev->cb_reset_occurrence) + tcm_dev->cb_reset_occurrence(tcm_dev->cbdata_reset); } } @@ -321,12 +326,13 @@ exit: * '0' means to read the message header only * [in/out] buf: pointer to a buffer which is stored the retrieved data * [out] buf_size: size of the buffer pointed + * [ in] extra_crc: flag to read in extra crc bytes * * @return * on success, 0 or positive value; otherwise, negative value on error. */ static int syna_tcm_v1_read(struct tcm_dev *tcm_dev, unsigned int rd_length, - unsigned char *buf, unsigned int buf_size) + unsigned char *buf, unsigned int buf_size, bool extra_crc) { int retval; unsigned int max_rd_size; @@ -391,17 +397,21 @@ exit: * [ in] tcm_dev: the device handle * [ in] command: command code * [ in] payload: data payload if any - * [ in] payload_len: length of data payload if have any + * [ in] payload_len: length of data payload if any + * [ in] crc_append: flag to send extra crc bytes + * [ in] extra_crc: two bytes crc value * * @return * on success, 0 or positive value; otherwise, negative value on error. */ static int syna_tcm_v1_write(struct tcm_dev *tcm_dev, unsigned char command, - unsigned char *payload, unsigned int payload_len) + unsigned char *payload, unsigned int payload_len, + bool extra_crc, unsigned short crc) { int retval = 0; struct tcm_message_data_blob *tcm_msg = NULL; - int size; + int size, buf_size; + unsigned char crc16[2] = { 0 }; if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); @@ -413,7 +423,15 @@ static int syna_tcm_v1_write(struct tcm_dev *tcm_dev, unsigned char command, syna_tcm_buf_lock(&tcm_msg->out); /* allocate the space storing the written data */ - retval = syna_tcm_buf_alloc(&tcm_msg->out, payload_len + 3); + buf_size = payload_len + 3; + if (extra_crc) { + crc16[0] = (unsigned char) crc & 0xff; + crc16[1] = (unsigned char) (crc >> 8); + + buf_size += 2; + } + + retval = syna_tcm_buf_alloc(&tcm_msg->out, buf_size); if (retval < 0) { LOGE("Fail to allocate memory for internal buf.out\n"); goto exit; @@ -461,6 +479,22 @@ static int syna_tcm_v1_write(struct tcm_dev *tcm_dev, unsigned char command, } } + /* append the crc16 value at the end */ + if (extra_crc) { + retval = syna_pal_mem_cpy(&tcm_msg->out.buf[size], + tcm_msg->out.buf_size - size, + crc16, + sizeof(crc16), + sizeof(crc16) + ); + if (retval < 0) { + LOGE("Fail to append crc16\n"); + goto exit; + } + + size += 2; + } + /* write command packet to the device */ retval = syna_tcm_write(tcm_dev, tcm_msg->out.buf, @@ -503,6 +537,7 @@ static int syna_tcm_v1_continued_read(struct tcm_dev *tcm_dev, unsigned int total_length; unsigned int remaining_length; struct tcm_message_data_blob *tcm_msg = NULL; + bool last = false; if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); @@ -524,6 +559,12 @@ static int syna_tcm_v1_continued_read(struct tcm_dev *tcm_dev, /* length to read, remember a padding at the end */ remaining_length = length + 1; + /* read extra crc if supported */ + if (tcm_msg->has_crc) { + total_length += 2; + remaining_length += 2; + } + syna_tcm_buf_lock(&tcm_msg->in); /* in case the current buf.in is smaller than requested size */ @@ -556,6 +597,8 @@ static int syna_tcm_v1_continued_read(struct tcm_dev *tcm_dev, else xfer_length = remaining_length; + last = ((idx + 1) == chunks); + if (xfer_length == 1) { tcm_msg->in.buf[offset] = TCM_V1_MESSAGE_PADDING; offset += xfer_length; @@ -576,14 +619,16 @@ static int syna_tcm_v1_continued_read(struct tcm_dev *tcm_dev, retval = syna_tcm_v1_read(tcm_dev, xfer_length + 2, tcm_msg->temp.buf, - tcm_msg->temp.buf_size - ); + tcm_msg->temp.buf_size, + (tcm_msg->has_crc) && last); if (retval < 0) { LOGE("Fail to read %d bytes from device\n", xfer_length + 2); goto exit; } + tcm_msg->temp.data_length = xfer_length + 2; + /* check the data content */ code = tcm_msg->temp.buf[1]; @@ -608,7 +653,14 @@ static int syna_tcm_v1_continued_read(struct tcm_dev *tcm_dev, offset += xfer_length; remaining_length -= xfer_length; } + /* copy crc bytes which are followed by EOM (0x5a) */ + offset = MESSAGE_HEADER_SIZE + tcm_msg->payload_length; + if (tcm_msg->has_crc) { + tcm_msg->crc_bytes = (unsigned short)syna_pal_le2_to_uint( + &tcm_msg->in.buf[offset + 1]); /* skip EOM */ + LOGD("CRC to read: 0x%04X\n", tcm_msg->crc_bytes); + } exit: syna_tcm_buf_unlock(&tcm_msg->temp); syna_tcm_buf_unlock(&tcm_msg->in); @@ -656,6 +708,8 @@ static int syna_tcm_v1_read_message(struct tcm_dev *tcm_dev, if (status_report_code) *status_report_code = STATUS_INVALID; + tcm_msg->crc_bytes = 0; + syna_pal_mutex_lock(rw_mutex); syna_tcm_buf_lock(&tcm_msg->in); @@ -682,8 +736,8 @@ static int syna_tcm_v1_read_message(struct tcm_dev *tcm_dev, retval = syna_tcm_v1_read(tcm_dev, len, tcm_msg->in.buf, - tcm_msg->in.buf_size - ); + tcm_msg->in.buf_size, + false); if (retval < 0) { LOGE("Fail to read message header from device\n"); syna_tcm_buf_unlock(&tcm_msg->in); @@ -769,8 +823,7 @@ do_dispatch: default: LOGE("Incorrect Status code, 0x%02x\n", tcm_msg->status_report_code); - retval = _EIO; - goto exit; + break; } } @@ -850,6 +903,9 @@ static int syna_tcm_v1_write_message(struct tcm_dev *tcm_dev, syna_pal_completion_t *cmd_completion = NULL; bool has_irq_ctrl = false; bool in_polling = false; + bool last = false; + unsigned char tmp; + unsigned short crc16 = 0xFFFF; if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); @@ -891,6 +947,21 @@ static int syna_tcm_v1_write_message(struct tcm_dev *tcm_dev, remaining_length = payload_len; + LOGD("Command: 0x%02x, payload len: %d\n", command, payload_len); + + /* calculate the crc if supported */ + if (tcm_msg->has_crc) { + crc16 = syna_tcm_crc16(&command, 1, crc16); + tmp = (unsigned char)payload_len & 0xff; + crc16 = syna_tcm_crc16(&tmp, 1, crc16); + tmp = (unsigned char)(payload_len >> 8) & 0xff; + crc16 = syna_tcm_crc16(&tmp, 1, crc16); + if (payload_len > 0) + crc16 = syna_tcm_crc16(payload, payload_len, crc16); + + LOGD("CRC to write: 0x%04X\n", crc16); + } + /* available space for payload = total size - command byte */ if (tcm_dev->max_wr_size == 0) chunk_space = remaining_length; @@ -900,8 +971,6 @@ static int syna_tcm_v1_write_message(struct tcm_dev *tcm_dev, chunks = syna_pal_ceil_div(remaining_length, chunk_space); chunks = chunks == 0 ? 1 : chunks; - LOGD("Command: 0x%02x, payload len: %d\n", command, payload_len); - /* send out command packets * * separate into several sub-packets if the overall size is over @@ -913,16 +982,22 @@ static int syna_tcm_v1_write_message(struct tcm_dev *tcm_dev, else xfer_length = remaining_length; + last = ((idx + 1) == chunks); + if (idx == 0) { retval = syna_tcm_v1_write(tcm_dev, tcm_msg->command, &payload[0], - xfer_length); + xfer_length, + (tcm_msg->has_crc) && last, + crc16); } else { retval = syna_tcm_v1_write(tcm_dev, CMD_CONTINUE_WRITE, &payload[idx * chunk_space], - xfer_length); + xfer_length, + (tcm_msg->has_crc) && last, + crc16); } if (retval < 0) { @@ -997,16 +1072,15 @@ check_response: } /* copy response code to the caller */ + LOGD("Received code 0x%02x\n", + tcm_msg->status_report_code); if (resp_code) - *resp_code = tcm_msg->response_code; + *resp_code = tcm_msg->status_report_code; - if (tcm_msg->response_code != STATUS_OK) { - LOGE("Error code 0x%02x of command 0x%02x\n", - tcm_msg->response_code, tcm_msg->command); + if (tcm_msg->response_code != STATUS_OK) retval = _EIO; - } else { + else retval = 0; - } exit: tcm_msg->command = CMD_NONE; @@ -1062,11 +1136,16 @@ int syna_tcm_v1_detect(struct tcm_dev *tcm_dev, unsigned char *data, if (header->marker != TCM_V1_MESSAGE_MARKER) return _ENODEV; + /* assume having crc appended, will determine whether feature + * is enabled or not + */ + tcm_msg->has_crc = true; + tcm_dev->msg_data.crc_bytes = 0x5a5a; + /* after initially powering on, the identify report should be the * first packet */ if (header->code == REPORT_IDENTIFY) { - payload_length = syna_pal_le2_to_uint(header->length); tcm_msg->payload_length = payload_length; @@ -1122,6 +1201,12 @@ int syna_tcm_v1_detect(struct tcm_dev *tcm_dev, unsigned char *data, /* expose the read / write operations */ tcm_dev->read_message = syna_tcm_v1_read_message; tcm_dev->write_message = syna_tcm_v1_write_message; + /* if all crc bytes belong to EOM, crc feature is yet enabled */ + if (tcm_dev->msg_data.crc_bytes == 0x5a5a) + tcm_msg->has_crc = false; + + LOGI("Message CRC appending is %s\n", + (tcm_msg->has_crc) ? "enabled" : "disabled"); return retval; } diff --git a/tcm/synaptics_touchcom_core_v2.c b/tcm/synaptics_touchcom_core_v2.c index c3f0d56..edfeecb 100644 --- a/tcm/synaptics_touchcom_core_v2.c +++ b/tcm/synaptics_touchcom_core_v2.c @@ -68,115 +68,6 @@ static int syna_tcm_v2_execute_cmd_request(struct tcm_dev *tcm_dev, unsigned int payload_length); /** - * @section: Lookup table for checksum calculation - * - * @subsection: crc6_table - * lookup table for crc6 calculation - * - * @subsection: crc16_table - * lookup table for crc16 calculation - */ -static unsigned short crc6_table[16] = { - 0, 268, 536, 788, 1072, 1340, 1576, 1828, - 2144, 2412, 2680, 2932, 3152, 3420, 3656, 3908 -}; - -static unsigned short crc16_table[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; - -/** - * syna_tcm_v2_crc6() - * - * Calculate the crc-6 with polynomial for TouchCom v2 header. - * - * @param - * [ in] p: byte array for the calculation - * [ in] bits: number of bits - * - * @return - * the crc-6 value - */ -static unsigned char syna_tcm_v2_crc6(unsigned char *p, unsigned int bits) -{ - unsigned short r = 0x003F << 2; - unsigned short x; - - for (; bits > 8; bits -= 8) { - r ^= *p++; - r = (r << 4) ^ crc6_table[r >> 4]; - r = (r << 4) ^ crc6_table[r >> 4]; - } - - if (bits > 0) { - x = *p; - while (bits--) { - if (x & 0x80) - r ^= 0x80; - - x <<= 1; - r <<= 1; - if (r & 0x100) - r ^= (0x03 << 2); - } - } - - return (unsigned char)((r >> 2) & 0x3F); -} -/** - * syna_tcm_v2_crc6() - * - * Calculate the crc-16 for TouchCom v2 packet. - * - * @param - * [ in] p: byte array for the calculation - * [ in] len: length in bytes - * - * @return - * the crc-16 value - */ -static unsigned short syna_tcm_v2_crc16(unsigned char *p, unsigned int len) -{ - unsigned short r = 0xFFFF; - - while (len--) - r = (r << 8) ^ crc16_table[(r >> 8) ^ *p++]; - - return r; -} - -/** * syna_tcm_v2_set_max_read_size() * * Configure the max length for message reading. @@ -379,6 +270,12 @@ static void syna_tcm_v2_dispatch_report(struct tcm_dev *tcm_dev) syna_pal_completion_complete(cmd_completion); goto exit; } + } else { + /* invoke callback to handle unexpected reset if doesn't + * result from command + */ + if (tcm_dev->cb_reset_occurrence) + tcm_dev->cb_reset_occurrence(tcm_dev->cbdata_reset); } } @@ -517,6 +414,7 @@ static int syna_tcm_v2_read(struct tcm_dev *tcm_dev, unsigned int rd_length, int max_rd_size; int xfer_len; unsigned char crc6 = 0; + unsigned short crc16 = 0xFFFF; struct tcm_message_data_blob *tcm_msg = NULL; if (!tcm_dev) { @@ -558,7 +456,7 @@ static int syna_tcm_v2_read(struct tcm_dev *tcm_dev, unsigned int rd_length, header = (struct tcm_v2_message_header *)tcm_msg->temp.buf; /* check header crc always */ - crc6 = syna_tcm_v2_crc6(header->data, BITS_IN_MESSAGE_HEADER); + crc6 = syna_tcm_crc6(header->data, BITS_IN_MESSAGE_HEADER); if (crc6 != 0) { LOGE("Invalid header crc: 0x%02x\n", (header->byte3 & 0x3f)); @@ -569,7 +467,8 @@ static int syna_tcm_v2_read(struct tcm_dev *tcm_dev, unsigned int rd_length, #ifdef CHECK_PACKET_CRC /* check packet crc */ if (rd_length > 0) { - if (syna_tcm_v2_crc16(&tcm_msg->temp.buf[0], xfer_len) != 0) { + crc16 = syna_tcm_crc16(&tcm_msg->temp.buf[0], xfer_len, 0xFFFF); + if (crc16 != 0) { LOGE("Invalid packet crc: %02x %02x\n", tcm_msg->temp.buf[xfer_len - 2], tcm_msg->temp.buf[xfer_len - 1]); @@ -577,6 +476,9 @@ static int syna_tcm_v2_read(struct tcm_dev *tcm_dev, unsigned int rd_length, tcm_msg->status_report_code = STATUS_PACKET_CORRUPTED; goto exit; } + + tcm_msg->crc_bytes = tcm_msg->temp.buf[xfer_len - 2] + + (tcm_msg->temp.buf[xfer_len - 1] << 8); } #endif @@ -666,7 +568,7 @@ static int syna_tcm_v2_write(struct tcm_dev *tcm_dev, unsigned char command, header->length[1] = (unsigned char)(payload_len >> 8); header->byte3 = ((HOST_PRIMARY & 0x01) << 7); header->byte3 |= ((tcm_msg->seq_toggle++ & 0x01) << 6); - header->byte3 |= syna_tcm_v2_crc6(header->data, bits); + header->byte3 |= syna_tcm_crc6(header->data, bits); /* copy payload, if any */ if (payload_len) { @@ -682,7 +584,7 @@ static int syna_tcm_v2_write(struct tcm_dev *tcm_dev, unsigned char command, } /* append packet crc */ - crc16 = syna_tcm_v2_crc16(&tcm_msg->out.buf[0], size); + crc16 = syna_tcm_crc16(&tcm_msg->out.buf[0], size, 0xFFFF); tcm_msg->out.buf[size] = (unsigned char)((crc16 >> 8) & 0xFF); tcm_msg->out.buf[size + 1] = (unsigned char)(crc16 & 0xFF); } @@ -1154,6 +1056,8 @@ static int syna_tcm_v2_read_message(struct tcm_dev *tcm_dev, if (status_report_code) *status_report_code = STATUS_INVALID; + tcm_msg->crc_bytes = 0; + syna_pal_mutex_lock(rw_mutex); /* request a command */ @@ -1422,7 +1326,7 @@ int syna_tcm_v2_detect(struct tcm_dev *tcm_dev, unsigned char *data, return _EINVAL; } - if (syna_tcm_v2_crc6(data, BITS_IN_MESSAGE_HEADER) != 0) + if (syna_tcm_crc6(data, BITS_IN_MESSAGE_HEADER) != 0) return _ENODEV; /* send an identify command to identify the device */ @@ -1441,5 +1345,8 @@ int syna_tcm_v2_detect(struct tcm_dev *tcm_dev, unsigned char *data, tcm_dev->read_message = syna_tcm_v2_read_message; tcm_dev->write_message = syna_tcm_v2_write_message; + tcm_dev->msg_data.has_crc = true; + tcm_dev->msg_data.crc_bytes = 0xffff; + return retval; } diff --git a/tcm/synaptics_touchcom_func_base.c b/tcm/synaptics_touchcom_func_base.c index 8c9d0b2..df9afb1 100644 --- a/tcm/synaptics_touchcom_func_base.c +++ b/tcm/synaptics_touchcom_func_base.c @@ -1636,7 +1636,7 @@ exit: */ int syna_tcm_send_command(struct tcm_dev *tcm_dev, unsigned char command, unsigned char *payload, - unsigned int payload_length, unsigned char *resp_code, + unsigned int payload_length, unsigned char *code, struct tcm_buffer *resp, unsigned int delay_ms_resp) { int retval = 0; @@ -1646,7 +1646,7 @@ int syna_tcm_send_command(struct tcm_dev *tcm_dev, return _EINVAL; } - if (!resp_code) { + if (!code) { LOGE("Invalid parameter\n"); return _EINVAL; } @@ -1655,21 +1655,49 @@ int syna_tcm_send_command(struct tcm_dev *tcm_dev, command, payload, payload_length, - resp_code, + code, delay_ms_resp); - if (retval < 0) { - LOGE("Fail to send command 0x%02x\n", - command); + + LOGD("Status code returned: 0x%02x\n", *code); + + /* exit if no buffer provided */ + if (!resp) goto exit; + + /* if gathering a report, copy to the user buffer */ + if ((*code >= REPORT_IDENTIFY) && (*code != STATUS_INVALID)) { + if (tcm_dev->report_buf.data_length == 0) + goto exit; + + syna_tcm_buf_lock(&tcm_dev->report_buf); + + if (syna_tcm_buf_copy(resp, &tcm_dev->report_buf) < 0) { + LOGE("Fail to copy data, report type: %x\n", + *code); + syna_tcm_buf_unlock(&tcm_dev->report_buf); + retval = _ENOMEM; + goto exit; + } + + syna_tcm_buf_unlock(&tcm_dev->report_buf); } - /* response data returned */ - if ((resp != NULL) && (tcm_dev->resp_buf.data_length > 0)) { - retval = syna_tcm_buf_copy(resp, &tcm_dev->resp_buf); - if (retval < 0) { - LOGE("Fail to copy resp data\n"); + /* if gathering a response, copy to the user buffer */ + if ((*code > STATUS_IDLE) && (*code <= STATUS_ERROR)) { + if (tcm_dev->resp_buf.data_length == 0) + goto exit; + + syna_tcm_buf_lock(&tcm_dev->resp_buf); + + if (syna_tcm_buf_copy(resp, &tcm_dev->resp_buf) < 0) { + LOGE("Fail to copy resp data, status code: %x\n", + *code); + syna_tcm_buf_unlock(&tcm_dev->resp_buf); + retval = _ENOMEM; goto exit; } + + syna_tcm_buf_unlock(&tcm_dev->resp_buf); } exit: @@ -1705,3 +1733,53 @@ int syna_tcm_enable_predict_reading(struct tcm_dev *tcm_dev, bool en) return 0; } +/** + * syna_tcm_get_message_crc() + * + * this function is used to return the crc of message retrieved previously + * + * @param + * [ in] tcm_dev: the device handle + * + * @return + * 2 bytes crc value + */ +unsigned short syna_tcm_get_message_crc(struct tcm_dev *tcm_dev) +{ + if (!tcm_dev) { + LOGE("Invalid tcm device handle\n"); + return _EINVAL; + } + + return tcm_dev->msg_data.crc_bytes; +} + +/** + * syna_tcm_set_reset_occurrence_callback() + * + * Set up callback function once an unexpected reset received + * + * @param + * [ in] tcm_dev: the device handle + * [ in] p_cb: the pointer of callback function + * [ in] p_cbdata: pointer to caller data + * + * @return + * on success, 0 or positive value; otherwise, negative value on error. + */ +int syna_tcm_set_reset_occurrence_callback(struct tcm_dev *tcm_dev, + tcm_reset_occurrence_callback_t p_cb, void *p_cbdata) +{ + if (!tcm_dev) { + LOGE("Invalid tcm device handle\n"); + return _EINVAL; + } + + tcm_dev->cb_reset_occurrence = p_cb; + tcm_dev->cbdata_reset = p_cbdata; + + LOGI("enabled\n"); + + return 0; +} + diff --git a/tcm/synaptics_touchcom_func_base.h b/tcm/synaptics_touchcom_func_base.h index 391aace..bdf3e18 100644 --- a/tcm/synaptics_touchcom_func_base.h +++ b/tcm/synaptics_touchcom_func_base.h @@ -428,6 +428,33 @@ int syna_tcm_send_command(struct tcm_dev *tcm_dev, * on success, 0 or positive value; otherwise, negative value on error. */ int syna_tcm_enable_predict_reading(struct tcm_dev *tcm_dev, bool en); +/** + * syna_tcm_get_message_crc() + * + * this function is used to return the crc of message retrieved previously + * + * @param + * [ in] tcm_dev: the device handle + * + * @return + * 2 bytes crc value + */ +unsigned short syna_tcm_get_message_crc(struct tcm_dev *tcm_dev); +/** + * syna_tcm_set_reset_occurrence_callback() + * + * Set up callback function once an unexpected reset received + * + * @param + * [ in] tcm_dev: the device handle + * [ in] p_cb: the pointer of callback function + * [ in] p_cbdata: pointer to caller data + * + * @return + * on success, 0 or positive value; otherwise, negative value on error. + */ +int syna_tcm_set_reset_occurrence_callback(struct tcm_dev *tcm_dev, + tcm_reset_occurrence_callback_t p_cb, void *p_cbdata); #endif /* end of _SYNAPTICS_TOUCHCOM_BASE_FUNCS_H_ */ diff --git a/tcm/synaptics_touchcom_func_reflash.c b/tcm/synaptics_touchcom_func_reflash.c index ca7f712..dff17cc 100644 --- a/tcm/synaptics_touchcom_func_reflash.c +++ b/tcm/synaptics_touchcom_func_reflash.c @@ -219,7 +219,7 @@ int syna_tcm_compare_image_id_info(struct tcm_dev *tcm_dev, device_fw_id, image_fw_id); if (image_fw_id != device_fw_id) { - LOGN("Image build ID is different from device fw ID\n"); + LOGN("Image build ID and device fw ID mismatched\n"); result = UPDATE_FIRMWARE_CONFIG; goto exit; } diff --git a/tcm/synaptics_touchcom_func_touch.c b/tcm/synaptics_touchcom_func_touch.c index f390d0c..8639fbc 100644 --- a/tcm/synaptics_touchcom_func_touch.c +++ b/tcm/synaptics_touchcom_func_touch.c @@ -166,6 +166,7 @@ static int syna_tcm_get_gesture_data(const unsigned char *report, switch (gesture_id) { case GESTURE_ID_DOUBLE_TAP: case GESTURE_ID_ACTIVE_TAP_AND_HOLD: + case GESTURE_ID_ACTIVE_SINGLE_TAP: LOGD("Tap info: (%d, %d)\n", syna_pal_le2_to_uint(gesture_data->tap_x), syna_pal_le2_to_uint(gesture_data->tap_y)); @@ -455,11 +456,11 @@ int syna_tcm_parse_touch_report(struct tcm_dev *tcm_dev, offset += bits; break; case TOUCH_REPORT_GESTURE_ID: - if (tcm_dev->custom_gesture_parse_func) { - retval = tcm_dev->custom_gesture_parse_func( + if (tcm_dev->cb_custom_gesture) { + retval = tcm_dev->cb_custom_gesture( TOUCH_REPORT_GESTURE_ID, config_data, &idx, report, &offset, report_size, - tcm_dev->cbdata_gesture_parse); + tcm_dev->cbdata_gesture); } else { bits = config_data[idx++]; retval = syna_tcm_get_touch_data(report, @@ -473,11 +474,11 @@ int syna_tcm_parse_touch_report(struct tcm_dev *tcm_dev, } break; case TOUCH_REPORT_GESTURE_DATA: - if (tcm_dev->custom_gesture_parse_func) { - retval = tcm_dev->custom_gesture_parse_func( + if (tcm_dev->cb_custom_gesture) { + retval = tcm_dev->cb_custom_gesture( TOUCH_REPORT_GESTURE_DATA, config_data, &idx, report, &offset, report_size, - tcm_dev->cbdata_gesture_parse); + tcm_dev->cbdata_gesture); } else { bits = config_data[idx++]; retval = syna_tcm_get_gesture_data(report, @@ -626,11 +627,11 @@ int syna_tcm_parse_touch_report(struct tcm_dev *tcm_dev, break; default: /* use custom parsing method, if registered */ - if (tcm_dev->custom_touch_data_parse_func) { - retval = tcm_dev->custom_touch_data_parse_func( + if (tcm_dev->cb_custom_touch_entity) { + retval = tcm_dev->cb_custom_touch_entity( code, config_data, &idx, report, &offset, report_size, - tcm_dev->cbdata_touch_data_parse); + tcm_dev->cbdata_touch_entity); if (retval >= 0) continue; } @@ -812,7 +813,7 @@ exit: } /** - * syna_tcm_set_custom_touch_data_parsing_callback() + * syna_tcm_set_custom_touch_entity_callback() * * Set up callback function to handle custom touch data. * @@ -822,21 +823,21 @@ exit: * @param * [ in] tcm_dev: the device handle * [ in] p_cb: the callback function pointer - * [ in] p_cbdata: pointer to caller data passed to callback function + * [ in] p_cbdata: pointer to caller data * * @return * on success, 0 or positive value; otherwise, negative value on error. */ -int syna_tcm_set_custom_touch_data_parsing_callback(struct tcm_dev *tcm_dev, - tcm_touch_data_parse_callback_t p_cb, void *p_cbdata) +int syna_tcm_set_custom_touch_entity_callback(struct tcm_dev *tcm_dev, + tcm_custom_touch_entity_callback_t p_cb, void *p_cbdata) { if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); return _EINVAL; } - tcm_dev->custom_touch_data_parse_func = p_cb; - tcm_dev->cbdata_touch_data_parse = p_cbdata; + tcm_dev->cb_custom_touch_entity = p_cb; + tcm_dev->cbdata_touch_entity = p_cbdata; LOGI("enabled\n"); @@ -844,10 +845,10 @@ int syna_tcm_set_custom_touch_data_parsing_callback(struct tcm_dev *tcm_dev, } /** - * syna_tcm_set_custom_gesture_parsing_callback() + * syna_tcm_set_custom_gesture_callback() * - * Set up callback function to handle the gesture data defined as the following - * code entities + * Set up callback function to handle the gesture data defined as the + * following code entities * - TOUCH_REPORT_GESTURE_ID * - TOUCH_REPORT_GESTURE_DATA * @@ -859,16 +860,16 @@ int syna_tcm_set_custom_touch_data_parsing_callback(struct tcm_dev *tcm_dev, * @return * on success, 0 or positive value; otherwise, negative value on error. */ -int syna_tcm_set_custom_gesture_parsing_callback(struct tcm_dev *tcm_dev, - tcm_gesture_parse_callback_t p_cb, void *p_cbdata) +int syna_tcm_set_custom_gesture_callback(struct tcm_dev *tcm_dev, + tcm_custom_gesture_callback_t p_cb, void *p_cbdata) { if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); return _EINVAL; } - tcm_dev->custom_gesture_parse_func = p_cb; - tcm_dev->cbdata_gesture_parse = p_cbdata; + tcm_dev->cb_custom_gesture = p_cb; + tcm_dev->cbdata_gesture = p_cbdata; LOGI("enabled\n"); diff --git a/tcm/synaptics_touchcom_func_touch.h b/tcm/synaptics_touchcom_func_touch.h index eb63c05..cafb956 100644 --- a/tcm/synaptics_touchcom_func_touch.h +++ b/tcm/synaptics_touchcom_func_touch.h @@ -67,6 +67,7 @@ enum gesture_classification { GESTURE_ID_NONE = 0, GESTURE_ID_DOUBLE_TAP = 1, GESTURE_ID_SWIPE = 2, + GESTURE_ID_ACTIVE_SINGLE_TAP = 6, GESTURE_ID_ACTIVE_TAP_AND_HOLD = 7, }; @@ -194,7 +195,7 @@ int syna_tcm_get_touch_data(const unsigned char *report, unsigned int bits, unsigned int *data); /** - * syna_tcm_set_custom_touch_data_parsing_callback() + * syna_tcm_set_custom_touch_entity_callback() * * Set up callback function to handle custom touch data. * @@ -209,11 +210,11 @@ int syna_tcm_get_touch_data(const unsigned char *report, * @return * on success, 0 or positive value; otherwise, negative value on error. */ -int syna_tcm_set_custom_touch_data_parsing_callback(struct tcm_dev *tcm_dev, - tcm_touch_data_parse_callback_t p_cb, void *p_cbdata); +int syna_tcm_set_custom_touch_entity_callback(struct tcm_dev *tcm_dev, + tcm_custom_touch_entity_callback_t p_cb, void *p_cbdata); /** - * syna_tcm_set_custom_gesture_parsing_callback() + * syna_tcm_set_custom_gesture_callback() * * Set up callback function to handle the gesture data defined as the following * code entities @@ -228,8 +229,8 @@ int syna_tcm_set_custom_touch_data_parsing_callback(struct tcm_dev *tcm_dev, * @return * on success, 0 or positive value; otherwise, negative value on error. */ -int syna_tcm_set_custom_gesture_parsing_callback(struct tcm_dev *tcm_dev, - tcm_gesture_parse_callback_t p_cb, void *p_cbdata); +int syna_tcm_set_custom_gesture_callback(struct tcm_dev *tcm_dev, + tcm_custom_gesture_callback_t p_cb, void *p_cbdata); #endif /* end of _SYNAPTICS_TOUCHCOM_TOUCH_FUNCS_H_ */ |