diff options
author | davidycchen <davidycchen@google.com> | 2021-12-20 17:13:30 +0800 |
---|---|---|
committer | davidycchen <davidycchen@google.com> | 2021-12-21 18:25:59 +0800 |
commit | f2bfef998a7497e947a4381f96abe9e789d781d1 (patch) | |
tree | 378131f0b4e1f29f4aef1ef0695722d5109d23b3 | |
parent | 96d884a4c6120e4a8e837f02f27079f0d993521d (diff) | |
download | synaptics_touch-f2bfef998a7497e947a4381f96abe9e789d781d1.tar.gz |
synaptics: synaptics: update driver version to 0118
Support two more testing
- PID$12: Abs. Raw
- PID$16: Trans Cap. Raw
Correct the sequence of suspend-reset especially RESET_ON_RESUME
enabled.
Sample code to parse the custom gesture data.
Enable RESET_ON_RESUME in default.
Bug: 211379827
Signed-off-by: davidycchen <davidycchen@google.com>
Change-Id: I888d0c68aa53020eb0e153105920b0fed133d8cb
-rw-r--r-- | syna_tcm2.c | 103 | ||||
-rw-r--r-- | syna_tcm2.h | 6 | ||||
-rw-r--r-- | syna_tcm2_sysfs.c | 10 | ||||
-rw-r--r-- | syna_tcm2_testing.c | 313 | ||||
-rw-r--r-- | syna_tcm2_testing_limits.h | 100 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_core_dev.h | 5 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_core_v1.c | 4 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_reflash.c | 12 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_romboot.c | 54 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_func_touch.c | 7 |
10 files changed, 566 insertions, 48 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c index a77bf58..2a11b05 100644 --- a/syna_tcm2.c +++ b/syna_tcm2.c @@ -128,6 +128,11 @@ static void syna_dev_reset_detected_cb(void *callback_data) return; } +#ifdef RESET_ON_RESUME + if (tcm->pwr_state != PWR_ON) + return; +#endif + if (ATOMIC_GET(tcm->helper.task) == HELP_NONE) { ATOMIC_SET(tcm->helper.task, HELP_RESET_DETECTED); @@ -157,7 +162,7 @@ static void syna_dev_helper_work(struct work_struct *work) switch (task) { case HELP_RESET_DETECTED: - LOGI("Reset caught, device mode 0x%x\n", tcm->tcm_dev->dev_mode); + LOGD("Reset caught (device mode:0x%x)\n", tcm->tcm_dev->dev_mode); break; default: break; @@ -324,23 +329,63 @@ static int syna_dev_parse_custom_gesture_cb(const unsigned char code, struct syna_tcm *tcm = (struct syna_tcm *)callback_data; unsigned int data; unsigned int bits; + unsigned int offset = *report_offset; + struct custom_gesture_data { + unsigned short x; + unsigned short y; + unsigned char major; + unsigned char minor; + } g_pos; bits = config[(*config_offset)++]; - syna_tcm_get_touch_data(report, report_size, *report_offset, bits, &data); - switch (data) { - case GESTURE_SINGLE_TAP: - LOGI("Gesture single tap detected\n"); - break; - case GESTURE_LONG_PRESS: - LOGI("Gesture long press detected\n"); - break; - default: - LOGW("Unknown gesture id %d\n", data); - break; - } + if (code == TOUCH_REPORT_GESTURE_ID) { + syna_tcm_get_touch_data(report, report_size, offset, bits, &data); + + switch (data) { + case GESTURE_SINGLE_TAP: + LOGI("Gesture single tap detected\n"); + break; + case GESTURE_LONG_PRESS: + LOGI("Gesture long press detected\n"); + break; + default: + LOGW("Unknown gesture id %d\n", data); + break; + } + + *report_offset += bits; + + } else if (code == TOUCH_REPORT_GESTURE_DATA) { + if (bits != (sizeof(struct custom_gesture_data) * 8)) { + LOGE("Invalid size of gesture data %d (expected:%d)\n", + bits, (int)(sizeof(struct custom_gesture_data) * 8)); + return -EINVAL; + } + + syna_tcm_get_touch_data(report, report_size, offset, 16, &data); + g_pos.x = (unsigned short)data; + offset += 16; + + syna_tcm_get_touch_data(report, report_size, offset, 16, &data); + g_pos.y = (unsigned short)data; + offset += 16; - report_offset += bits; + syna_tcm_get_touch_data(report, report_size, offset, 8, &data); + g_pos.major = (unsigned short)data; + offset += 8; + + syna_tcm_get_touch_data(report, report_size, offset, 8, &data); + g_pos.minor = (unsigned short)data; + offset += 8; + + *report_offset += bits; + + LOGI("Gesture data x:%d y:%d major:%d minor:%d\n", + g_pos.x, g_pos.y, g_pos.major, g_pos.minor); + } else { + return -EINVAL; + } return bits; } @@ -1118,6 +1163,7 @@ exit: pm_relax(&tcm->pdev->dev); } #endif +#if defined(POWER_ALIVE_AT_SUSPEND) && !defined(RESET_ON_RESUME) /** * syna_dev_enter_normal_sensing() * @@ -1154,6 +1200,8 @@ static int syna_dev_enter_normal_sensing(struct syna_tcm *tcm) return 0; } +#endif +#ifdef POWER_ALIVE_AT_SUSPEND /** * syna_dev_enter_lowpwr_sensing() * @@ -1191,10 +1239,9 @@ static int syna_dev_enter_lowpwr_sensing(struct syna_tcm *tcm) } } - tcm->pwr_state = LOW_PWR; - return 0; } +#endif static int syna_pinctrl_configure(struct syna_tcm *tcm, bool enable) { @@ -1242,6 +1289,7 @@ static int syna_dev_resume(struct device *dev) struct syna_tcm *tcm = dev_get_drvdata(dev); struct syna_hw_interface *hw_if = tcm->hw_if; bool irq_enabled = true; + unsigned char status; /* exit directly if device isn't in suspend state */ if (tcm->pwr_state == PWR_ON) @@ -1252,32 +1300,39 @@ static int syna_dev_resume(struct device *dev) syna_pinctrl_configure(tcm, true); #ifdef RESET_ON_RESUME + LOGI("Do reset on resume\n"); syna_pal_sleep_ms(RESET_ON_RESUME_DELAY_MS); if (hw_if->ops_hw_reset) { hw_if->ops_hw_reset(hw_if); + retval = syna_tcm_get_event_data(tcm->tcm_dev, + &status, NULL); + if ((retval < 0) || (status != REPORT_IDENTIFY)) { + LOGE("Fail to complete hw reset\n"); + goto exit; + } } else { retval = syna_tcm_reset(tcm->tcm_dev); if (retval < 0) { - LOGE("Fail to do reset\n"); + LOGE("Fail to do sw reset\n"); goto exit; } } #else +#ifdef POWER_ALIVE_AT_SUSPEND /* enter normal power mode */ retval = syna_dev_enter_normal_sensing(tcm); if (retval < 0) { LOGE("Fail to enter normal power mode\n"); goto exit; } - +#endif retval = syna_tcm_rezero(tcm->tcm_dev); if (retval < 0) { LOGE("Fail to rezero\n"); goto exit; } -#endif /* end of RESET_ON_RESUME */ - +#endif tcm->pwr_state = PWR_ON; LOGI("Prepare to set up application firmware\n"); @@ -1292,12 +1347,9 @@ static int syna_dev_resume(struct device *dev) retval = 0; LOGI("Device resumed (pwr_state:%d)\n", tcm->pwr_state); - exit: - /* once lpwg is enabled, irq should be enabled already. - * otherwise, set irq back to active mode. - */ - irq_enabled = (!tcm->lpwg_enabled); + /* set irq back to active mode if not enabled yet */ + irq_enabled = (!hw_if->bdata_attn.irq_enabled); /* enable irq */ if (irq_enabled && (hw_if->ops_enable_irq)) @@ -1349,6 +1401,7 @@ static int syna_dev_suspend(struct device *dev) LOGE("Fail to enter suspended power mode\n"); return retval; } + tcm->pwr_state = LOW_PWR; #else tcm->pwr_state = PWR_OFF; #endif diff --git a/syna_tcm2.h b/syna_tcm2.h index 40273a3..a03cb65 100644 --- a/syna_tcm2.h +++ b/syna_tcm2.h @@ -54,7 +54,7 @@ #define SYNAPTICS_TCM_DRIVER_ID (1 << 0) #define SYNAPTICS_TCM_DRIVER_VERSION 1 -#define SYNAPTICS_TCM_DRIVER_SUBVER "2.3" +#define SYNAPTICS_TCM_DRIVER_SUBVER "2.5" /** * @section: Driver Configurations @@ -101,7 +101,7 @@ * from suspend. * Set "disable" in default. */ -/* #define RESET_ON_RESUME */ +#define RESET_ON_RESUME /** * @brief ENABLE_WAKEUP_GESTURE @@ -257,7 +257,7 @@ /** * @brief ENABLE_HELPER - * Open if willing to do additional handling upon helper wokqueue + * Open if willing to do additional handling upon helper workqueue * * Set "disable" in default */ diff --git a/syna_tcm2_sysfs.c b/syna_tcm2_sysfs.c index b9206af..1028d55 100644 --- a/syna_tcm2_sysfs.c +++ b/syna_tcm2_sysfs.c @@ -501,6 +501,16 @@ static ssize_t syna_sysfs_reset_store(struct kobject *kobj, } tcm->hw_if->ops_hw_reset(tcm->hw_if); + + /* enable the interrupt to process the identify report + * after the hardware reset. + */ + if (!tcm->hw_if->bdata_attn.irq_enabled) { + tcm->hw_if->ops_enable_irq(tcm->hw_if, true); + /* disable it and back to original status */ + syna_pal_sleep_ms(100); + tcm->hw_if->ops_enable_irq(tcm->hw_if, false); + } } else { LOGW("Unknown option %d (1:sw / 2:hw)\n", input); retval = -EINVAL; diff --git a/syna_tcm2_testing.c b/syna_tcm2_testing.c index 7c8e057..be8fd36 100644 --- a/syna_tcm2_testing.c +++ b/syna_tcm2_testing.c @@ -106,7 +106,7 @@ static bool syna_testing_compare_byte_vector(unsigned char *data, * syna_testing_compare_frame() * * Sample code to compare the test result with limits - * by a lower-bound frame + * being formatted as a frame * * @param * [ in] data: target test data @@ -195,6 +195,112 @@ end_of_lower_bound_limit: } /** + * syna_testing_compare_list() + * + * Sample code to compare the test result with limits + * being formatted as a list + * + * @param + * [ in] data: target test data + * [ in] data_size: size of test data + * [ in] rows: the number of rows + * [ in] cols: the number of column + * [ in] limits_hi: upper-bound test limit + * [ in] limits_lo: lower-bound test limit + * + * @return + * on success, true; otherwise, return false + */ +static bool syna_testing_compare_list(unsigned char *data, + unsigned int data_size, int rows, int cols, + const int *limits_hi, const int *limits_lo) +{ + bool result = false; + int *data_ptr = NULL; + int limit; + int i; + + if (!data || (data_size == 0)) { + LOGE("Invalid test data\n"); + return false; + } + + if (data_size % (rows + cols) != 0) { + LOGE("Size mismatched, data:%d (exppected:%d * N)\n", + data_size, (rows + cols)); + result = false; + return false; + } + + if (rows > LIMIT_BOUNDARY) { + LOGE("Rows mismatched, rows:%d (exppected:%d)\n", + rows, LIMIT_BOUNDARY); + result = false; + return false; + } + + if (cols > LIMIT_BOUNDARY) { + LOGE("Columns mismatched, cols: %d (exppected:%d)\n", + cols, LIMIT_BOUNDARY); + result = false; + return false; + } + + result = true; + + if (!limits_hi) + goto end_of_upper_bound_limit; + + data_ptr = (int *)&data[0]; + for (i = 0; i < cols; i++) { + limit = limits_hi[i]; + if (*data_ptr > limit) { + LOGE("Fail on cols-%2d=%5d, limits_hi:%4d\n", + i, *data_ptr, limit); + result = false; + } + data_ptr++; + } + for (i = 0; i < rows; i++) { + limit = limits_hi[LIMIT_BOUNDARY + i]; + if (*data_ptr > limit) { + LOGE("Fail on row-%2d=%5d, limits_hi:%4d\n", + i, *data_ptr, limit); + result = false; + } + data_ptr++; + } + +end_of_upper_bound_limit: + + if (!limits_lo) + goto end_of_lower_bound_limit; + + data_ptr = (int *)&data[0]; + for (i = 0; i < cols; i++) { + limit = limits_lo[i]; + if (*data_ptr < limit) { + LOGE("Fail on cols-%2d=%5d, limits_lo:%4d\n", + i, *data_ptr, limit); + result = false; + } + data_ptr++; + } + for (i = 0; i < rows; i++) { + limit = limits_lo[LIMIT_BOUNDARY + i]; + if (*data_ptr < limit) { + LOGE("Fail on row-%2d=%5d, limits_lo:%4d\n", + i, *data_ptr, limit); + result = false; + } + data_ptr++; + } + +end_of_lower_bound_limit: + return result; +} + +/** * syna_testing_device_id() * * Sample code to ensure the device id is expected @@ -827,6 +933,209 @@ exit: static struct kobj_attribute kobj_attr_pt11 = __ATTR(pt11, 0444, syna_testing_pt11_show, NULL); +/** + * syna_testing_pt12() + * + * Sample code to perform PT12 testing + * + * @param + * [ in] tcm: the driver handle + * + * @return + * on success, 0; otherwise, negative value on error. + */ +static int syna_testing_pt12(struct syna_tcm *tcm, struct tcm_buffer *test_data) +{ + int retval; + bool result = false; + + LOGI("Start testing\n"); + + retval = syna_tcm_run_production_test(tcm->tcm_dev, + TEST_PID18_HYBRID_ABS_RAW, + test_data); + if (retval < 0) { + LOGE("Fail to run test %d\n", TEST_PID18_HYBRID_ABS_RAW); + result = false; + goto exit; + } + + result = syna_testing_compare_list(test_data->buf, + test_data->data_length, + tcm->tcm_dev->rows, + tcm->tcm_dev->cols, + (const int *)&pt12_limits[0], + NULL); + +exit: + LOGI("Result = %s\n", (result)?"pass":"fail"); + + return ((result) ? 0 : -1); +} + +/** + * syna_testing_pt12_show() + * + * Attribute to show the result of PT12 test to the console. + * + * @param + * [ in] kobj: an instance of kobj + * [ in] attr: an instance of kobj attribute structure + * [out] buf: string buffer shown on console + * + * @return + * on success, number of characters being output; + * otherwise, negative value on error. + */ +static ssize_t syna_testing_pt12_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int retval, i; + unsigned int count = 0; + struct syna_tcm *tcm = g_tcm_ptr; + struct tcm_buffer test_data; + int *data_ptr = NULL; + + if (!tcm->is_connected) { + count = snprintf(buf, PAGE_SIZE, + "Device is NOT connected\n"); + goto exit; + } + + syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, true); + + syna_tcm_buf_init(&test_data); + + retval = syna_testing_pt12(tcm, &test_data); + + count = snprintf(buf, PAGE_SIZE, + "TEST PT$12: %s\n", (retval < 0) ? "fail" : "pass"); + + count += scnprintf(buf + count, PAGE_SIZE - count, "%d %d\n", + tcm->tcm_dev->cols, tcm->tcm_dev->rows); + + data_ptr = (int *)&(test_data.buf[0]); + for (i = 0; i < tcm->tcm_dev->cols; i++) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%d ", + data_ptr[i]); + } + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + for (i = 0; i < tcm->tcm_dev->rows; i++) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%d ", + data_ptr[tcm->tcm_dev->cols + i]); + } + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + + syna_tcm_buf_release(&test_data); + + syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, false); +exit: + return count; +} + +static struct kobj_attribute kobj_attr_pt12 = + __ATTR(pt12, 0444, syna_testing_pt12_show, NULL); + +/** + * syna_testing_pt16() + * + * Sample code to perform PT16 testing + * + * @param + * [ in] tcm: the driver handle + * + * @return + * on success, 0; otherwise, negative value on error. + */ +static int syna_testing_pt16(struct syna_tcm *tcm, struct tcm_buffer *test_data) +{ + int retval; + bool result = false; + + LOGI("Start testing\n"); + + retval = syna_tcm_run_production_test(tcm->tcm_dev, + TEST_PID22_TRANS_CAP_RAW, + test_data); + if (retval < 0) { + LOGE("Fail to run test %d\n", TEST_PID22_TRANS_CAP_RAW); + result = false; + goto exit; + } + + result = syna_testing_compare_frame(test_data->buf, + test_data->data_length, + tcm->tcm_dev->rows, + tcm->tcm_dev->cols, + (const short *)&pt16_hi_limits[0], + (const short *)&pt16_lo_limits[0]); + +exit: + LOGI("Result = %s\n", (result)?"pass":"fail"); + + return ((result) ? 0 : -1); +} + +/** + * syna_testing_pt16_show() + * + * Attribute to show the result of PT11 test to the console. + * + * @param + * [ in] kobj: an instance of kobj + * [ in] attr: an instance of kobj attribute structure + * [out] buf: string buffer shown on console + * + * @return + * on success, number of characters being output; + * otherwise, negative value on error. + */ +static ssize_t syna_testing_pt16_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int retval, i, j; + short *data_ptr = NULL; + unsigned int count = 0; + struct syna_tcm *tcm = g_tcm_ptr; + struct tcm_buffer test_data; + + if (!tcm->is_connected) { + count = snprintf(buf, PAGE_SIZE, + "Device is NOT connected\n"); + goto exit; + } + + syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, true); + + syna_tcm_buf_init(&test_data); + + retval = syna_testing_pt16(tcm, &test_data); + + count = snprintf(buf, PAGE_SIZE, + "TEST PT$16: %s\n", (retval < 0) ? "fail" : "pass"); + + count += scnprintf(buf + count, PAGE_SIZE - count, "%d %d\n", + tcm->tcm_dev->cols, tcm->tcm_dev->rows); + + data_ptr = (short *)&(test_data.buf[0]); + for (i = 0; i < tcm->tcm_dev->rows; i++) { + for (j = 0; j < tcm->tcm_dev->cols; j++) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%d ", + data_ptr[i * tcm->tcm_dev->cols + j]); + } + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + } + + syna_tcm_buf_release(&test_data); + + syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, false); +exit: + return count; +} + +static struct kobj_attribute kobj_attr_pt16 = + __ATTR(pt16, 0444, syna_testing_pt16_show, NULL); + /* * declaration of sysfs attributes */ @@ -837,6 +1146,8 @@ static struct attribute *attrs[] = { &kobj_attr_pt0a.attr, &kobj_attr_pt10.attr, &kobj_attr_pt11.attr, + &kobj_attr_pt12.attr, + &kobj_attr_pt16.attr, NULL, }; diff --git a/syna_tcm2_testing_limits.h b/syna_tcm2_testing_limits.h index c8ef469..7fce00f 100644 --- a/syna_tcm2_testing_limits.h +++ b/syna_tcm2_testing_limits.h @@ -413,4 +413,104 @@ static const short pt11_lo_limits[LIMIT_BOUNDARY * LIMIT_BOUNDARY] = { /* 39 */ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, }; +/** + * @section test limit for PT12 testing + */ +static const int pt12_limits[LIMIT_BOUNDARY + LIMIT_BOUNDARY] = { +/* 00 01 02 03 04 05 06 07 08 09 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 */ +/* 00 */ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, +/* 01 */ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, +}; + +/** + * @section test limit for PT16 testing + */ +static const short pt16_hi_limits[LIMIT_BOUNDARY * LIMIT_BOUNDARY] = { +/* 00 01 02 03 04 05 06 07 08 09 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 */ +/* 00 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 01 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 02 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 03 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 04 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 05 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 06 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 07 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 08 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 09 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 10 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 11 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 12 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 13 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 14 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 15 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 16 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 17 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 18 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 19 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 20 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 21 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 22 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 23 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 24 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 25 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 26 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 27 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 28 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 29 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 30 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 31 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 32 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 33 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 34 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 35 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 36 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 37 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 38 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +/* 39 */ 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, +}; + +static const short pt16_lo_limits[LIMIT_BOUNDARY * LIMIT_BOUNDARY] = { +/* 00 01 02 03 04 05 06 07 08 09 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 */ +/* 00 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 01 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 02 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 03 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 04 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 05 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 06 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 07 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 08 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 09 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 10 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 11 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 12 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 13 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 14 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 15 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 16 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 17 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 18 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 19 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 20 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 21 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 22 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 23 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 24 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 25 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 26 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 27 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 28 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 29 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 30 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 31 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 32 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 33 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 34 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 35 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 36 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 37 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 38 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +/* 39 */ 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, +}; + #endif /* end of _SYNAPTICS_TCM2_TESTING_LIMITS_H_ */ diff --git a/tcm/synaptics_touchcom_core_dev.h b/tcm/synaptics_touchcom_core_dev.h index 1b0eb2c..1728830 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 0x0115 +#define SYNA_TCM_CORE_LIB_VERSION 0x0118 /** @@ -335,6 +335,7 @@ enum tcm_test_code { TEST_PID01_TRX_TRX_SHORTS = 0x01, TEST_PID02_TRX_SENSOR_OPENS = 0x02, TEST_PID03_TRX_GROUND_SHORTS = 0x03, + TEST_PID04_GPIO_SHORTS = 0x04, TEST_PID05_FULL_RAW_CAP = 0x05, TEST_PID06_EE_SHORT = 0x06, TEST_PID07_DYNAMIC_RANGE = 0x07, @@ -348,7 +349,9 @@ enum tcm_test_code { TEST_PID16_SENSOR_SPEED = 0x10, TEST_PID17_ADC_RANGE = 0x11, TEST_PID18_HYBRID_ABS_RAW = 0x12, + TEST_PID22_TRANS_CAP_RAW = 0x16, TEST_PID29_HYBRID_ABS_NOISE = 0x1D, + TEST_PID30_BSC_CALIB = 0x1E, TEST_PID_MAX, }; diff --git a/tcm/synaptics_touchcom_core_v1.c b/tcm/synaptics_touchcom_core_v1.c index 75d4c4a..17a7ca4 100644 --- a/tcm/synaptics_touchcom_core_v1.c +++ b/tcm/synaptics_touchcom_core_v1.c @@ -190,13 +190,15 @@ static void syna_tcm_v1_dispatch_report(struct tcm_dev *tcm_dev) syna_pal_completion_complete(cmd_completion); goto exit; default: - LOGN("Device has been reset\n"); + LOGN("Get unexpected 0x%02X report at command 0x%02X\n", + REPORT_IDENTIFY, tcm_msg->command); ATOMIC_SET(tcm_msg->command_status, CMD_STATE_ERROR); syna_pal_completion_complete(cmd_completion); goto exit; } } else { + LOGN("Device has been reset\n"); /* invoke callback to handle unexpected reset if doesn't * result from command */ diff --git a/tcm/synaptics_touchcom_func_reflash.c b/tcm/synaptics_touchcom_func_reflash.c index dff17cc..5115b73 100644 --- a/tcm/synaptics_touchcom_func_reflash.c +++ b/tcm/synaptics_touchcom_func_reflash.c @@ -1978,6 +1978,7 @@ int syna_tcm_do_fw_update(struct tcm_dev *tcm_dev, int retval; enum update_area type = UPDATE_NONE; struct tcm_reflash_data_blob reflash_data; + int app_status; if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); @@ -2008,6 +2009,17 @@ int syna_tcm_do_fw_update(struct tcm_dev *tcm_dev, ATOMIC_SET(tcm_dev->firmware_flashing, 1); + app_status = syna_pal_le2_to_uint(tcm_dev->app_info.status); + + /* to forcedly update the firmware and config + * - flag of 'force_reflash' has been set + * - device stays in bootloader + * - app firmware doesn't run properly + */ + force_reflash = force_reflash || + (IS_BOOTLOADER_MODE(tcm_dev->dev_mode)) || + (IS_APP_FW_MODE(tcm_dev->dev_mode) && (app_status != APP_STATUS_OK)); + if (force_reflash) { type = UPDATE_FIRMWARE_CONFIG; goto reflash; diff --git a/tcm/synaptics_touchcom_func_romboot.c b/tcm/synaptics_touchcom_func_romboot.c index 9ad30ad..782bb0f 100644 --- a/tcm/synaptics_touchcom_func_romboot.c +++ b/tcm/synaptics_touchcom_func_romboot.c @@ -1189,15 +1189,17 @@ int syna_tcm_romboot_do_ihex_update(struct tcm_dev *tcm_dev, return _EINVAL; } - romboot_data = syna_pal_mem_alloc(1, sizeof(*romboot_data)); + if (flash_size == 0) + flash_size = ihex_size + 4096; + + romboot_data = syna_pal_mem_alloc(1, + sizeof(struct tcm_romboot_data_blob)); if (!romboot_data) { - LOGE("Fail to allocate buffer for romboot_data\n"); + LOGE("Fail to allocate romboot data blob\n"); + return _ENOMEM; } - if (flash_size == 0) - flash_size = ihex_size + 4096; - romboot_data->bdata = ihex; romboot_data->bdata_size = ihex_size; syna_pal_mem_set(&romboot_data->ihex_info, 0x00, @@ -1210,6 +1212,7 @@ int syna_tcm_romboot_do_ihex_update(struct tcm_dev *tcm_dev, if (!ihex_info->bin) { LOGE("Fail to allocate buffer for ihex data\n"); syna_pal_mem_free((void *)romboot_data); + return _ENOMEM; } @@ -1358,9 +1361,12 @@ int syna_tcm_romboot_do_multichip_reflash(struct tcm_dev *tcm_dev, struct block_data *block; struct app_config_header *header; unsigned int image_fw_id; + unsigned char *image_config_id; + unsigned char *device_config_id; unsigned int erase_delay_ms = (wait_delay_ms >> 16) & 0xFFFF; unsigned int wr_delay_ms = wait_delay_ms & 0xFFFF; bool has_tool_boot_cfg = false; + bool reflash_required = false; if (!tcm_dev) { LOGE("Invalid tcm device handle\n"); @@ -1372,16 +1378,15 @@ int syna_tcm_romboot_do_multichip_reflash(struct tcm_dev *tcm_dev, return _EINVAL; } - LOGN("Prepare to do reflash\n"); - - romboot_data = syna_pal_mem_alloc(1, sizeof(*romboot_data)); + romboot_data = syna_pal_mem_alloc(1, + sizeof(struct tcm_romboot_data_blob)); if (!romboot_data) { - LOGE("Fail to allocate buffer for romboot_data\n"); + LOGE("Fail to allocate romboot data blob\n"); + return _ENOMEM; } - syna_pal_mem_set(romboot_data, 0x00, - sizeof(struct tcm_romboot_data_blob)); + LOGN("Prepare to do reflash\n"); syna_tcm_buf_init(&romboot_data->out); @@ -1410,7 +1415,30 @@ int syna_tcm_romboot_do_multichip_reflash(struct tcm_dev *tcm_dev, LOGN("Device firmware ID: %d, image build id: %d\n", tcm_dev->packrat_number, image_fw_id); - if ((image_fw_id <= tcm_dev->packrat_number) && !force_reflash) { + if (image_fw_id != tcm_dev->packrat_number) { + LOGN("Image build ID and device fw ID mismatched\n"); + reflash_required = true; + } + + image_config_id = header->customer_config_id; + device_config_id = tcm_dev->app_info.customer_config_id; + + for (idx = 0; idx < MAX_SIZE_CONFIG_ID; idx++) { + if (image_config_id[idx] != device_config_id[idx]) { + LOGN("Different Config ID\n"); + reflash_required = true; + } + } + /* to start the process of firmware update + * - fw ID or config ID is mismatched + * - device stays in rom-bootloader + * - flag of 'force_reflash' has been set + */ + reflash_required = reflash_required || + (IS_ROM_BOOTLOADER_MODE(tcm_dev->dev_mode)) || + force_reflash; + + if (!reflash_required) { LOGN("No need to do reflash\n"); retval = 0; goto exit; @@ -1534,7 +1562,7 @@ exit: syna_tcm_buf_release(&romboot_data->out); - syna_pal_mem_free((void *)romboot_data); + syna_pal_mem_free(romboot_data); return retval; } diff --git a/tcm/synaptics_touchcom_func_touch.c b/tcm/synaptics_touchcom_func_touch.c index 8639fbc..d4fd617 100644 --- a/tcm/synaptics_touchcom_func_touch.c +++ b/tcm/synaptics_touchcom_func_touch.c @@ -178,7 +178,7 @@ static int syna_tcm_get_gesture_data(const unsigned char *report, syna_pal_le2_to_uint(gesture_data->tap_y)); break; default: - LOGW("Unknown gesture_id:%d\n", gesture_id); + LOGD("Unknown gesture_id:%d\n", gesture_id); break; } @@ -437,10 +437,9 @@ int syna_tcm_parse_touch_report(struct tcm_dev *tcm_dev, touch_data->num_of_active_objects = data; offset += bits; if (touch_data->num_of_active_objects == 0) { - if (end_of_foreach == 0) { - LOGE("Invalid end_foreach\n"); + if (end_of_foreach == 0) return 0; - } + idx = end_of_foreach; } break; |