ftsCompensation.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * FTS Capacitive touch screen controller (FingerTipS)
  4. *
  5. * Copyright (C) 2016-2019, STMicroelectronics Limited.
  6. * Authors: AMG(Analog Mems Group) <[email protected]>
  7. *
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License version 2 as published by
  11. * the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. * more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along with
  19. * this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. *
  23. **************************************************************************
  24. ** STMicroelectronics **
  25. **************************************************************************
  26. ** [email protected] **
  27. **************************************************************************
  28. * *
  29. * FTS functions for getting Initialization Data *
  30. * *
  31. **************************************************************************
  32. **************************************************************************
  33. */
  34. #include <linux/init.h>
  35. #include <linux/errno.h>
  36. #include <linux/platform_device.h>
  37. #include <linux/kernel.h>
  38. #include <linux/module.h>
  39. #include <linux/slab.h>
  40. #include <linux/string.h>
  41. #include <stdarg.h>
  42. #include <linux/input.h>
  43. #include <linux/interrupt.h>
  44. #include <linux/serio.h>
  45. #include <linux/time.h>
  46. #include <linux/pm.h>
  47. #include <linux/delay.h>
  48. #include <linux/ctype.h>
  49. #include <linux/gpio.h>
  50. #include <linux/i2c.h>
  51. #include <linux/i2c-dev.h>
  52. #include <linux/fs.h>
  53. #include <linux/uaccess.h>
  54. #include <linux/power_supply.h>
  55. #include <linux/firmware.h>
  56. #include <linux/regulator/consumer.h>
  57. #include <linux/of_gpio.h>
  58. //#include <linux/sec_sysfs.h>
  59. #include "ftsCrossCompile.h"
  60. #include "ftsCompensation.h"
  61. #include "ftsError.h"
  62. #include "ftsFrame.h"
  63. #include "ftsHardware.h"
  64. #include "ftsIO.h"
  65. #include "ftsSoftware.h"
  66. #include "ftsTool.h"
  67. static char tag[8] = "[ FTS ]\0";
  68. struct chipInfo ftsInfo;
  69. int requestCompensationData(u16 type)
  70. {
  71. int retry = 0;
  72. int ret;
  73. char *temp = NULL;
  74. u16 answer;
  75. int event_to_search[3];
  76. u8 readEvent[FIFO_EVENT_SIZE];
  77. u8 cmd[3] = { FTS_CMD_REQU_COMP_DATA, 0x00, 0x00};
  78. /* B8 is the command for asking compensation data*/
  79. u16ToU8(type, &cmd[1]);
  80. event_to_search[0] = (int)EVENTID_COMP_DATA_READ;
  81. event_to_search[1] = cmd[1];
  82. event_to_search[2] = cmd[2];
  83. while (retry < COMP_DATA_READ_RETRY) {
  84. temp = printHex("Command = ", cmd, 3);
  85. if (temp != NULL)
  86. logError(0, "%s %s", tag, temp);
  87. kfree(temp);
  88. ret = fts_writeFwCmd(cmd, 3);
  89. /*send the request to the chip to load*/
  90. /*in memory the Compensation Data*/
  91. if (ret < OK) {
  92. logError(1, "%s %s:ERROR %02X\n",
  93. tag, __func__, ERROR_I2C_W);
  94. return ERROR_I2C_W;
  95. }
  96. ret = pollForEvent(event_to_search, 3, readEvent,
  97. TIMEOUT_REQU_COMP_DATA);
  98. if (ret < OK) {
  99. logError(0, "%s Event did not Found at %d attemp!\n",
  100. tag, retry + 1);
  101. retry += 1;
  102. } else {
  103. retry = 0;
  104. break;
  105. }
  106. }
  107. if (retry == COMP_DATA_READ_RETRY) {
  108. logError(1, "%s %s: ERROR %02X\n",
  109. tag, __func__, ERROR_TIMEOUT);
  110. return ERROR_TIMEOUT;
  111. }
  112. u8ToU16_le(&readEvent[1], &answer);
  113. if (answer == type)
  114. return OK;
  115. logError(1, "%sThe event found has a different type of ", tag);
  116. logError(1, "Compensation data %02X\n", ERROR_DIFF_COMP_TYPE);
  117. return ERROR_DIFF_COMP_TYPE;
  118. }
  119. int readCompensationDataHeader(u16 type, struct DataHeader *header,
  120. u16 *address)
  121. {
  122. u16 offset = ADDR_FRAMEBUFFER_DATA;
  123. u16 answer;
  124. u8 data[COMP_DATA_HEADER];
  125. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, offset, data, COMP_DATA_HEADER,
  126. DUMMY_FRAMEBUFFER) < 0) {
  127. logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_R);
  128. return ERROR_I2C_R;
  129. }
  130. logError(0, "%s Read Data Header done!\n", tag);
  131. if (data[0] != HEADER_SIGNATURE) {
  132. logError(1, "%s %s:%02X The Header Signature was wrong!",
  133. tag, __func__, ERROR_WRONG_COMP_SIGN);
  134. logError(1, "%02X != %02X\n", data[0], HEADER_SIGNATURE);
  135. return ERROR_WRONG_COMP_SIGN;
  136. }
  137. u8ToU16_le(&data[1], &answer);
  138. if (answer != type) {
  139. logError(1, "%s %s:ERROR %02X\n",
  140. tag, __func__, ERROR_DIFF_COMP_TYPE);
  141. return ERROR_DIFF_COMP_TYPE;
  142. }
  143. logError(0, "%s Type of Compensation data OK!\n", tag);
  144. header->type = type;
  145. header->force_node = (int)data[4];
  146. header->sense_node = (int)data[5];
  147. *address = offset + COMP_DATA_HEADER;
  148. return OK;
  149. }
  150. int readMutualSenseGlobalData(u16 *address, struct MutualSenseData *global)
  151. {
  152. u8 data[COMP_DATA_GLOBAL];
  153. logError(0, "%s Address for Global data= %02X\n", tag, *address);
  154. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, *address, data,
  155. COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
  156. logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_R);
  157. return ERROR_I2C_R;
  158. }
  159. logError(0, "%s Global data Read!\n", tag);
  160. global->tuning_ver = data[0];
  161. global->cx1 = data[1];
  162. logError(0, "%s tuning_ver = %d CX1 = %d\n",
  163. tag, global->tuning_ver, global->cx1);
  164. *address += COMP_DATA_GLOBAL;
  165. return OK;
  166. }
  167. int readMutualSenseNodeData(u16 address, struct MutualSenseData *node)
  168. {
  169. int size = node->header.force_node*node->header.sense_node;
  170. logError(0, "%s Address for Node data = %02X\n", tag, address);
  171. node->node_data = (u8 *)kmalloc_array(size, (sizeof(u8)), GFP_KERNEL);
  172. if (node->node_data == NULL) {
  173. logError(1, "%s %s: ERROR %02X", tag, __func__, ERROR_ALLOC);
  174. return ERROR_ALLOC;
  175. }
  176. logError(0, "%s Node Data to read %d bytes\n", tag, size);
  177. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, node->node_data,
  178. size, DUMMY_FRAMEBUFFER) < 0) {
  179. logError(1, "%s %s:ERROR %02X\n", tag, __func__, ERROR_I2C_R);
  180. kfree(node->node_data);
  181. return ERROR_I2C_R;
  182. }
  183. node->node_data_size = size;
  184. logError(0, "%s Read node data ok!\n", tag);
  185. return size;
  186. }
  187. int readMutualSenseCompensationData(u16 type, struct MutualSenseData *data)
  188. {
  189. int ret;
  190. u16 address;
  191. data->node_data = NULL;
  192. if (!(type == MS_TOUCH_ACTIVE || type == MS_TOUCH_LOW_POWER
  193. || type == MS_TOUCH_ULTRA_LOW_POWER || type == MS_KEY)) {
  194. logError(1, "%s %s: Choose a MS type of compensation data ",
  195. tag, __func__);
  196. logError(1, "ERROR %02X\n", ERROR_OP_NOT_ALLOW);
  197. return ERROR_OP_NOT_ALLOW;
  198. }
  199. ret = requestCompensationData(type);
  200. if (ret < 0) {
  201. logError(1, "%s %s: ERROR %02X\n",
  202. tag, __func__, ERROR_REQU_COMP_DATA);
  203. return (ret|ERROR_REQU_COMP_DATA);
  204. }
  205. ret = readCompensationDataHeader(type, &(data->header), &address);
  206. if (ret < 0) {
  207. logError(1, "%s %s: ERROR %02X\n",
  208. tag, __func__, ERROR_COMP_DATA_HEADER);
  209. return (ret | ERROR_COMP_DATA_HEADER);
  210. }
  211. ret = readMutualSenseGlobalData(&address, data);
  212. if (ret < 0) {
  213. logError(1, "%s %s: ERROR %02X\n",
  214. tag, __func__, ERROR_COMP_DATA_GLOBAL);
  215. return (ret|ERROR_COMP_DATA_GLOBAL);
  216. }
  217. ret = readMutualSenseNodeData(address, data);
  218. if (ret < 0) {
  219. logError(1, "%s %s: ERROR %02X\n",
  220. tag, __func__, ERROR_COMP_DATA_NODE);
  221. return (ret | ERROR_COMP_DATA_NODE);
  222. }
  223. return OK;
  224. }
  225. int readSelfSenseGlobalData(u16 *address, struct SelfSenseData *global)
  226. {
  227. u8 data[COMP_DATA_GLOBAL];
  228. logError(0, "%s Address for Global data= %02X\n", tag, *address);
  229. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, *address, data,
  230. COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
  231. logError(1, "%s %s: ERROR %02X\n",
  232. tag, __func__, ERROR_I2C_R);
  233. return ERROR_I2C_R;
  234. }
  235. logError(0, "%s Global data Read!\n", tag);
  236. global->tuning_ver = data[0];
  237. global->f_ix1 = data[1];
  238. global->s_ix1 = data[2];
  239. global->f_cx1 = data[3];
  240. global->s_cx1 = data[4];
  241. global->f_max_n = data[5];
  242. global->s_max_n = data[6];
  243. logError(0,
  244. "%stuning_ver = %df_ix1 = %ds_ix1 = %df_cx1 = %d s_cx1 = %d\n",
  245. tag, global->tuning_ver, global->f_ix1,
  246. global->s_ix1, global->f_cx1, global->s_cx1);
  247. logError(0, "%s max_n = %d s_max_n = %d\n",
  248. tag, global->f_max_n, global->s_max_n);
  249. *address += COMP_DATA_GLOBAL;
  250. return OK;
  251. }
  252. int readSelfSenseNodeData(u16 address, struct SelfSenseData *node)
  253. {
  254. int size = node->header.force_node * 2 + node->header.sense_node * 2;
  255. u8 *data;
  256. node->ix2_fm = (u8 *)kmalloc_array(node->header.force_node,
  257. sizeof(u8), GFP_KERNEL);
  258. if (node->ix2_fm == NULL) {
  259. logError(1, "%s %s: ERROR %02X", tag, __func__, ERROR_ALLOC);
  260. return ERROR_ALLOC;
  261. }
  262. node->cx2_fm = (u8 *)kmalloc_array(node->header.force_node,
  263. sizeof(u8), GFP_KERNEL);
  264. if (node->cx2_fm == NULL) {
  265. logError(1, "%s %s: ERROR %02X", tag, __func__, ERROR_ALLOC);
  266. kfree(node->ix2_fm);
  267. return ERROR_ALLOC;
  268. }
  269. node->ix2_sn = (u8 *)kmalloc_array(node->header.sense_node,
  270. sizeof(u8), GFP_KERNEL);
  271. if (node->ix2_sn == NULL) {
  272. logError(1, "%s %s: ERROR %02X", tag, __func__, ERROR_ALLOC);
  273. kfree(node->ix2_fm);
  274. kfree(node->cx2_fm);
  275. return ERROR_ALLOC;
  276. }
  277. node->cx2_sn = (u8 *)kmalloc_array(node->header.sense_node,
  278. sizeof(u8), GFP_KERNEL);
  279. if (node->cx2_sn == NULL) {
  280. logError(1, "%s %s: ERROR %02X", tag, __func__, ERROR_ALLOC);
  281. kfree(node->ix2_fm);
  282. kfree(node->cx2_fm);
  283. kfree(node->ix2_sn);
  284. return ERROR_ALLOC;
  285. }
  286. logError(0, "%s Address for Node data = %02X\n", tag, address);
  287. logError(0, "%s Node Data to read %d bytes\n", tag, size);
  288. data = (u8 *)kmalloc_array(size, sizeof(u8), GFP_KERNEL);
  289. if (data == NULL) {
  290. logError(1, "%s %s: ERROR %02X", tag, __func__, ERROR_ALLOC);
  291. kfree(node->ix2_fm);
  292. kfree(node->cx2_fm);
  293. kfree(node->ix2_sn);
  294. kfree(node->cx2_sn);
  295. return ERROR_ALLOC;
  296. }
  297. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, size,
  298. DUMMY_FRAMEBUFFER) < 0) {
  299. logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_R);
  300. kfree(node->ix2_fm);
  301. kfree(node->cx2_fm);
  302. kfree(node->ix2_sn);
  303. kfree(node->cx2_sn);
  304. kfree(data);
  305. return ERROR_I2C_R;
  306. }
  307. logError(0, "%s Read node data ok!\n", tag);
  308. memcpy(node->ix2_fm, data, node->header.force_node);
  309. memcpy(node->ix2_sn, &data[node->header.force_node],
  310. node->header.sense_node);
  311. memcpy(node->cx2_fm,
  312. &data[node->header.force_node + node->header.sense_node],
  313. node->header.force_node);
  314. memcpy(node->cx2_sn,
  315. &data[node->header.force_node * 2 + node->header.sense_node],
  316. node->header.sense_node);
  317. kfree(data);
  318. return OK;
  319. }
  320. int readSelfSenseCompensationData(u16 type, struct SelfSenseData *data)
  321. {
  322. int ret;
  323. u16 address;
  324. data->ix2_fm = NULL;
  325. data->cx2_fm = NULL;
  326. data->ix2_sn = NULL;
  327. data->cx2_sn = NULL;
  328. if (!(type == SS_TOUCH || type == SS_KEY || type == SS_HOVER
  329. || type == SS_PROXIMITY)) {
  330. logError(1, "%s %s:Choose a SS type of compensation data ",
  331. tag, __func__);
  332. logError(1, "ERROR %02X\n", ERROR_OP_NOT_ALLOW);
  333. return ERROR_OP_NOT_ALLOW;
  334. }
  335. ret = requestCompensationData(type);
  336. if (ret < 0) {
  337. logError(1, "%s %s: ERROR %02X\n",
  338. tag, __func__, ERROR_REQU_COMP_DATA);
  339. return (ret | ERROR_REQU_COMP_DATA);
  340. }
  341. ret = readCompensationDataHeader(type, &(data->header), &address);
  342. if (ret < 0) {
  343. logError(1, "%s %s: ERROR %02X\n",
  344. tag, __func__, ERROR_COMP_DATA_HEADER);
  345. return (ret|ERROR_COMP_DATA_HEADER);
  346. }
  347. ret = readSelfSenseGlobalData(&address, data);
  348. if (ret < 0) {
  349. logError(1, "%s %s: ERROR %02X\n",
  350. tag, __func__, ERROR_COMP_DATA_GLOBAL);
  351. return (ret | ERROR_COMP_DATA_GLOBAL);
  352. }
  353. ret = readSelfSenseNodeData(address, data);
  354. if (ret < 0) {
  355. logError(1, "%s %s: ERROR %02X\n",
  356. tag, __func__, ERROR_COMP_DATA_NODE);
  357. return (ret | ERROR_COMP_DATA_NODE);
  358. }
  359. return OK;
  360. }
  361. int readGeneralGlobalData(u16 address, struct GeneralData *global)
  362. {
  363. u8 data[COMP_DATA_GLOBAL];
  364. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, COMP_DATA_GLOBAL,
  365. DUMMY_FRAMEBUFFER) < 0) {
  366. logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_R);
  367. return ERROR_I2C_R;
  368. }
  369. global->ftsd_lp_timer_cal0 = data[0];
  370. global->ftsd_lp_timer_cal1 = data[1];
  371. global->ftsd_lp_timer_cal2 = data[2];
  372. global->ftsd_lp_timer_cal3 = data[3];
  373. global->ftsa_lp_timer_cal0 = data[4];
  374. global->ftsa_lp_timer_cal1 = data[5];
  375. return OK;
  376. }
  377. int readGeneralCompensationData(u16 type, struct GeneralData *data)
  378. {
  379. int ret;
  380. u16 address;
  381. if (!(type == GENERAL_TUNING)) {
  382. logError(1, "%s %s:Choose a GENERAL type of compensation data ",
  383. tag);
  384. logError(1, "ERROR %02X\n", ERROR_OP_NOT_ALLOW);
  385. return ERROR_OP_NOT_ALLOW;
  386. }
  387. ret = requestCompensationData(type);
  388. if (ret < 0) {
  389. logError(1, "%s %s: ERROR %02X\n",
  390. tag, __func__, ERROR_REQU_COMP_DATA);
  391. return ERROR_REQU_COMP_DATA;
  392. }
  393. ret = readCompensationDataHeader(type, &(data->header), &address);
  394. if (ret < 0) {
  395. logError(1, "%s %s: ERROR %02X\n",
  396. tag, __func__, ERROR_COMP_DATA_HEADER);
  397. return ERROR_COMP_DATA_HEADER;
  398. }
  399. ret = readGeneralGlobalData(address, data);
  400. if (ret < 0) {
  401. logError(1, "%s %s: ERROR %02X\n",
  402. tag, __func__, ERROR_COMP_DATA_GLOBAL);
  403. return ERROR_COMP_DATA_GLOBAL;
  404. }
  405. return OK;
  406. }
  407. int defaultChipInfo(int i2cError)
  408. {
  409. int i;
  410. logError(0, "%s Setting default Chip Info...\n", tag);
  411. ftsInfo.u32_echoEn = 0x00000000;
  412. ftsInfo.u8_msScrConfigTuneVer = 0;
  413. ftsInfo.u8_ssTchConfigTuneVer = 0;
  414. ftsInfo.u8_msScrCxmemTuneVer = 0;
  415. ftsInfo.u8_ssTchCxmemTuneVer = 0;
  416. if (i2cError == 1) {
  417. ftsInfo.u16_fwVer = 0xFFFF;
  418. ftsInfo.u16_cfgId = 0xFFFF;
  419. for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++)
  420. ftsInfo.u8_extReleaseInfo[i] = 0xFF;
  421. } else {
  422. ftsInfo.u16_fwVer = 0x0000;
  423. ftsInfo.u16_cfgId = 0x0000;
  424. for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++)
  425. ftsInfo.u8_extReleaseInfo[i] = 0x00;
  426. }
  427. ftsInfo.u32_mpPassFlag = INIT_FIELD;
  428. ftsInfo.u16_errOffset = INVALID_ERROR_OFFS;
  429. logError(0, "%s default Chip Info DONE!\n", tag);
  430. return OK;
  431. }
  432. int readChipInfo(int doRequest)
  433. {
  434. int ret, i;
  435. u16 answer;
  436. u8 data[CHIP_INFO_SIZE + 3];
  437. /*+3 because need to read all the field of*/
  438. /*the struct plus the signature and 2 address bytes*/
  439. int index = 0;
  440. logError(0, "%s Starting Read Chip Info...\n", tag);
  441. if (doRequest == 1) {
  442. ret = requestCompensationData(CHIP_INFO);
  443. if (ret < 0) {
  444. logError(1, "%s %s: ERROR %02X\n",
  445. tag, __func__, ERROR_REQU_COMP_DATA);
  446. ret = (ret | ERROR_REQU_COMP_DATA);
  447. goto FAIL;
  448. }
  449. }
  450. logError(0, "%s Byte to read = %d bytes\n", tag, CHIP_INFO_SIZE + 3);
  451. if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, ADDR_FRAMEBUFFER_DATA, data,
  452. CHIP_INFO_SIZE + 3, DUMMY_FRAMEBUFFER) < 0) {
  453. logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_R);
  454. ret = ERROR_I2C_R;
  455. goto FAIL;
  456. }
  457. logError(0, "%s Read data ok!\n", tag);
  458. logError(0, "%s Starting parsing of data...\n", tag);
  459. if (data[0] != HEADER_SIGNATURE) {
  460. logError(1, "%s %s:ERROR ", tag, __func__);
  461. logError(1, "%02X The Header Signature is wrong!%02X != %02X\n",
  462. ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
  463. ret = ERROR_WRONG_COMP_SIGN;
  464. goto FAIL;
  465. }
  466. u8ToU16_le(&data[1], &answer);
  467. if (answer != CHIP_INFO) {
  468. logError(1, "%s %s: ERROR %02X\n",
  469. tag, __func__, ERROR_DIFF_COMP_TYPE);
  470. ret = ERROR_DIFF_COMP_TYPE;
  471. goto FAIL;
  472. }
  473. index += 3;
  474. ftsInfo.u8_loadCnt = data[index++];
  475. ftsInfo.u8_infoVer = data[index++];
  476. u8ToU16(&data[index], &ftsInfo.u16_ftsdId);
  477. index += 2;
  478. ftsInfo.u8_ftsdVer = data[index++];
  479. ftsInfo.u8_ftsaId = data[index++];
  480. ftsInfo.u8_ftsaVer = data[index++];
  481. ftsInfo.u8_tchRptVer = data[index++];
  482. logError(0, "%s External Release = ", tag);
  483. for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
  484. ftsInfo.u8_extReleaseInfo[i] = data[index++];
  485. logError(0, "%02X ", ftsInfo.u8_extReleaseInfo[i]);
  486. }
  487. logError(0, "\n");
  488. for (i = 0; i < sizeof(ftsInfo.u8_custInfo); i++)
  489. ftsInfo.u8_custInfo[i] = data[index++];
  490. u8ToU16(&data[index], &ftsInfo.u16_fwVer);
  491. index += 2;
  492. logError(1, "%s FW VERSION = %04X\n", tag, ftsInfo.u16_fwVer);
  493. u8ToU16(&data[index], &ftsInfo.u16_cfgId);
  494. index += 2;
  495. logError(1, "%s CONFIG ID = %04X\n", tag, ftsInfo.u16_cfgId);
  496. ftsInfo.u32_projId = ((data[index + 3] & 0x000000FF) << 24) +
  497. ((data[index + 2] & 0x000000FF) << 16) +
  498. ((data[index + 1] & 0x000000FF) << 8) +
  499. (data[index] & 0x000000FF);
  500. index += 4;
  501. u8ToU16(&data[index], &ftsInfo.u16_scrXRes);
  502. index += 2;
  503. u8ToU16(&data[index], &ftsInfo.u16_scrYRes);
  504. index += 2;
  505. ftsInfo.u8_scrForceLen = data[index++];
  506. logError(0, "%s Force Len = %d\n", tag, ftsInfo.u8_scrForceLen);
  507. ftsInfo.u8_scrSenseLen = data[index++];
  508. logError(0, "%s Sense Len = %d\n", tag, ftsInfo.u8_scrSenseLen);
  509. for (i = 0; i < 8; i++)
  510. ftsInfo.u64_scrForceEn[i] = data[index++];
  511. for (i = 0; i < 8; i++)
  512. ftsInfo.u64_scrSenseEn[i] = data[index++];
  513. ftsInfo.u8_msKeyLen = data[index++];
  514. logError(0, "%s MS Key Len = %d\n", tag, ftsInfo.u8_msKeyLen);
  515. for (i = 0; i < 8; i++)
  516. ftsInfo.u64_msKeyForceEn[i] = data[index++];
  517. for (i = 0; i < 8; i++)
  518. ftsInfo.u64_msKeySenseEn[i] = data[index++];
  519. ftsInfo.u8_ssKeyLen = data[index++];
  520. logError(0, "%s SS Key Len = %d\n", tag, ftsInfo.u8_ssKeyLen);
  521. for (i = 0; i < 8; i++)
  522. ftsInfo.u64_ssKeyForceEn[i] = data[index++];
  523. for (i = 0; i < 8; i++)
  524. ftsInfo.u64_ssKeySenseEn[i] = data[index++];
  525. ftsInfo.u8_frcTchXLen = data[index++];
  526. ftsInfo.u8_frcTchYLen = data[index++];
  527. for (i = 0; i < 8; i++)
  528. ftsInfo.u64_frcTchForceEn[i] = data[index++];
  529. for (i = 0; i < 8; i++)
  530. ftsInfo.u64_frcTchSenseEn[i] = data[index++];
  531. ftsInfo.u8_msScrConfigTuneVer = data[index++];
  532. logError(0, "%s CFG MS TUNING VERSION = %02X\n",
  533. tag, ftsInfo.u8_msScrConfigTuneVer);
  534. ftsInfo.u8_msScrLpConfigTuneVer = data[index++];
  535. ftsInfo.u8_msScrHwulpConfigTuneVer = data[index++];
  536. ftsInfo.u8_msKeyConfigTuneVer = data[index++];
  537. ftsInfo.u8_ssTchConfigTuneVer = data[index++];
  538. logError(0, "%s CFG SS TUNING VERSION = %02X\n",
  539. tag, ftsInfo.u8_ssTchConfigTuneVer);
  540. ftsInfo.u8_ssKeyConfigTuneVer = data[index++];
  541. ftsInfo.u8_ssHvrConfigTuneVer = data[index++];
  542. ftsInfo.u8_frcTchConfigTuneVer = data[index++];
  543. ftsInfo.u8_msScrCxmemTuneVer = data[index++];
  544. logError(0, "%s CX MS TUNING VERSION = %02X\n",
  545. tag, ftsInfo.u8_msScrCxmemTuneVer);
  546. ftsInfo.u8_msScrLpCxmemTuneVer = data[index++];
  547. ftsInfo.u8_msScrHwulpCxmemTuneVer = data[index++];
  548. ftsInfo.u8_msKeyCxmemTuneVer = data[index++];
  549. ftsInfo.u8_ssTchCxmemTuneVer = data[index++];
  550. logError(0, "%s CX SS TUNING VERSION = %02X\n",
  551. tag, ftsInfo.u8_ssTchCxmemTuneVer);
  552. ftsInfo.u8_ssKeyCxmemTuneVer = data[index++];
  553. ftsInfo.u8_ssHvrCxmemTuneVer = data[index++];
  554. ftsInfo.u8_frcTchCxmemTuneVer = data[index++];
  555. ftsInfo.u32_mpPassFlag = ((data[index + 3] & 0x000000FF) << 24)
  556. + ((data[index + 2] & 0x000000FF) << 16) +
  557. ((data[index + 1] & 0x000000FF) << 8) +
  558. (data[index] & 0x000000FF);
  559. index += 4;
  560. logError(0, "%s MP SIGNATURE = %08X\n", tag, ftsInfo.u32_mpPassFlag);
  561. ftsInfo.u32_featEn = ((data[index + 3] & 0x000000FF) << 24) +
  562. ((data[index + 2] & 0x000000FF) << 16) +
  563. ((data[index + 1] & 0x000000FF) << 8) +
  564. (data[index] & 0x000000FF);
  565. index += 4;
  566. ftsInfo.u32_echoEn = ((data[index + 3] & 0x000000FF) << 24) +
  567. ((data[index + 2] & 0x000000FF) << 16) +
  568. ((data[index + 1] & 0x000000FF) << 8) +
  569. (data[index] & 0x000000FF);
  570. index += 4;
  571. logError(0, "%s FEATURES = %08X\n", tag, ftsInfo.u32_echoEn);
  572. ftsInfo.u8_sideTchConfigTuneVer = data[index++];
  573. ftsInfo.u8_sideTchCxmemTuneVer = data[index++];
  574. ftsInfo.u8_sideTchForceLen = data[index++];
  575. logError(0, "%s Side Touch Force Len = %d\n",
  576. tag, ftsInfo.u8_sideTchForceLen);
  577. ftsInfo.u8_sideTchSenseLen = data[index++];
  578. logError(0, "%s Side Touch Sense Len = %d\n",
  579. tag, ftsInfo.u8_sideTchSenseLen);
  580. for (i = 0; i < 8; i++)
  581. ftsInfo.u64_sideTchForceEn[i] = data[index++];
  582. for (i = 0; i < 8; i++)
  583. ftsInfo.u64_sideTchSenseEn[i] = data[index++];
  584. ftsInfo.u8_errSign = data[index++];
  585. logError(0, "%s ERROR SIGNATURE = %02X\n", tag, ftsInfo.u8_errSign);
  586. if (ftsInfo.u8_errSign == ERROR_SIGN_HEAD) {
  587. logError(0, "%s Correct Error Signature found!\n", tag);
  588. u8ToU16(&data[index], &ftsInfo.u16_errOffset);
  589. } else {
  590. logError(1, "%s Error Signature NOT FOUND!\n", tag);
  591. ftsInfo.u16_errOffset = INVALID_ERROR_OFFS;
  592. }
  593. logError(0, "%s ERROR OFFSET = %04X\n", tag, ftsInfo.u16_errOffset);
  594. index += 2;
  595. logError(0, "%s Parsed %d bytes!\n", tag, index);
  596. if (index != CHIP_INFO_SIZE + 3) {
  597. logError(1, "%s %s: index = %d different from %d ERROR %02X\n",
  598. tag, __func__, index, CHIP_INFO_SIZE + 3,
  599. ERROR_OP_NOT_ALLOW);
  600. return ERROR_OP_NOT_ALLOW;
  601. }
  602. logError(0, "%s Chip Info Read DONE!\n", tag);
  603. return OK;
  604. FAIL:
  605. defaultChipInfo(isI2cError(ret));
  606. return ret;
  607. }