sec_cmd.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2014 Samsung Electronics Co., Ltd.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include "sec_cmd.h"
  10. #include "sec_input.h"
  11. #include "sec_tsp_log.h"
  12. struct class *tsp_sec_class;
  13. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  14. __visible_for_testing struct sec_cmd_data *kunit_sec;
  15. EXPORT_SYMBOL(kunit_sec);
  16. #else
  17. #define __visible_for_testing static
  18. #endif
  19. const char *str_power_state[3] = { "OFF", "LP", "ON" };
  20. const char *str_use_case[CHECK_ALL + 1] = {
  21. "NONE", // 0
  22. "OFF", // 1 CHECK_POWEROFF
  23. "LP", // 2 CHECK_LPMODE
  24. "LP/OFF", // 3 CHECK_POWEROFF | CHECK_LPMODE
  25. "ON", // 4 CHECK_POWERON
  26. "ON/OFF", // 5 CHECK_POWEROFF | CHECK_POWERON
  27. "ON/LP", // 6 CHECK_ON_LP
  28. "ON/LP/OFF", // 7 CHECK_ALL
  29. };
  30. #ifdef USE_SEC_CMD_QUEUE
  31. static void cmd_store_function(struct sec_cmd_data *data);
  32. void sec_cmd_execution(struct sec_cmd_data *data, bool lock)
  33. {
  34. if (lock)
  35. mutex_lock(&data->fs_lock);
  36. /* check lock */
  37. mutex_lock(&data->cmd_lock);
  38. atomic_set(&data->cmd_is_running, 1);
  39. mutex_unlock(&data->cmd_lock);
  40. data->cmd_state = SEC_CMD_STATUS_RUNNING;
  41. cmd_store_function(data);
  42. if (lock)
  43. mutex_unlock(&data->fs_lock);
  44. }
  45. #endif
  46. void sec_cmd_set_cmd_exit(struct sec_cmd_data *data)
  47. {
  48. #ifdef USE_SEC_CMD_QUEUE
  49. mutex_lock(&data->fifo_lock);
  50. if (kfifo_len(&data->cmd_queue)) {
  51. pr_info("%s: %s %s: do next cmd, left cmd[%d]\n", dev_name(data->fac_dev), SECLOG, __func__,
  52. (int)(kfifo_len(&data->cmd_queue) / sizeof(struct command)));
  53. mutex_unlock(&data->fifo_lock);
  54. sec_cmd_execution(data, false);
  55. } else {
  56. mutex_unlock(&data->fifo_lock);
  57. mutex_lock(&data->cmd_lock);
  58. atomic_set(&data->cmd_is_running, 0);
  59. mutex_unlock(&data->cmd_lock);
  60. }
  61. if (data->wait_cmd_result_done)
  62. complete_all(&data->cmd_result_done);
  63. #else
  64. mutex_lock(&data->cmd_lock);
  65. atomic_set(&data->cmd_is_running, 0);
  66. mutex_unlock(&data->cmd_lock);
  67. #endif
  68. }
  69. EXPORT_SYMBOL(sec_cmd_set_cmd_exit);
  70. #ifdef USE_SEC_CMD_QUEUE
  71. static void cmd_exit_work(struct work_struct *work)
  72. {
  73. struct sec_cmd_data *data = container_of(work, struct sec_cmd_data, cmd_work.work);
  74. sec_cmd_execution(data, true);
  75. }
  76. #endif
  77. void sec_cmd_set_default_result(struct sec_cmd_data *data)
  78. {
  79. char *delim = ":";
  80. memset(data->cmd_result, 0x00, SEC_CMD_RESULT_STR_LEN_EXPAND);
  81. memcpy(data->cmd_result, data->cmd, SEC_CMD_STR_LEN);
  82. strlcat(data->cmd_result, delim, SEC_CMD_RESULT_STR_LEN_EXPAND);
  83. }
  84. EXPORT_SYMBOL(sec_cmd_set_default_result);
  85. void sec_cmd_set_cmd_result_all(struct sec_cmd_data *data, char *buff, int len, char *item)
  86. {
  87. char *delim1 = " ";
  88. char *delim2 = ":";
  89. int cmd_result_len;
  90. cmd_result_len = (int)strlen(data->cmd_result_all) + len + 2 + (int)strlen(item);
  91. if (cmd_result_len >= SEC_CMD_RESULT_STR_LEN) {
  92. pr_err("%s: %s %s: cmd length is over (%d)!!", dev_name(data->fac_dev), SECLOG, __func__, cmd_result_len);
  93. return;
  94. }
  95. data->item_count++;
  96. strlcat(data->cmd_result_all, delim1, sizeof(data->cmd_result_all));
  97. strlcat(data->cmd_result_all, item, sizeof(data->cmd_result_all));
  98. strlcat(data->cmd_result_all, delim2, sizeof(data->cmd_result_all));
  99. strlcat(data->cmd_result_all, buff, sizeof(data->cmd_result_all));
  100. }
  101. EXPORT_SYMBOL(sec_cmd_set_cmd_result_all);
  102. void sec_cmd_set_cmd_result(struct sec_cmd_data *data, char *buff, int len)
  103. {
  104. if (strlen(buff) >= (unsigned int)SEC_CMD_RESULT_STR_LEN_EXPAND) {
  105. pr_err("%s %s: cmd length is over (%d)!!", SECLOG, __func__, (int)strlen(buff));
  106. strlcat(data->cmd_result, "NG", SEC_CMD_RESULT_STR_LEN_EXPAND);
  107. return;
  108. }
  109. data->cmd_result_expand = (int)strlen(buff) / SEC_CMD_RESULT_STR_LEN;
  110. data->cmd_result_expand_count = 0;
  111. strlcat(data->cmd_result, buff, SEC_CMD_RESULT_STR_LEN_EXPAND);
  112. }
  113. EXPORT_SYMBOL(sec_cmd_set_cmd_result);
  114. void sec_cmd_check_store_condition(struct sec_cmd_data *data, struct sec_cmd *sec_cmd_ptr)
  115. {
  116. struct sec_ts_plat_data *plat_data = data->dev->platform_data;
  117. int prev_result_len = 0;
  118. pr_info("%s %s power_state:%s, check_power:%s%s, wait_result:%d\n",
  119. dev_name(data->fac_dev), SECLOG, str_power_state[atomic_read(&plat_data->power_state)],
  120. str_use_case[sec_cmd_ptr->cmd_use_cases],
  121. sec_cmd_ptr->cmd_func_forced ? "(force func)" : "",
  122. sec_cmd_ptr->wait_read_result);
  123. sec_cmd_set_default_result(data);
  124. prev_result_len = (int)strlen(data->cmd_result);
  125. if (sec_input_cmp_ic_status(data->dev, sec_cmd_ptr->cmd_use_cases)) {
  126. sec_cmd_ptr->cmd_func(data);
  127. } else {
  128. if (sec_cmd_ptr->cmd_func_forced)
  129. sec_cmd_ptr->cmd_func_forced(data);
  130. else
  131. goto CMD_NG;
  132. }
  133. if (prev_result_len == (int)strlen(data->cmd_result)) {
  134. if ((data->cmd_state == SEC_CMD_STATUS_WAITING) || (data->cmd_state == SEC_CMD_STATUS_OK))
  135. strlcat(data->cmd_result, "OK", SEC_CMD_RESULT_STR_LEN_EXPAND);
  136. else if (data->cmd_state == SEC_CMD_STATUS_NOT_APPLICABLE)
  137. strlcat(data->cmd_result, "NA", SEC_CMD_RESULT_STR_LEN_EXPAND);
  138. else
  139. strlcat(data->cmd_result, "NG", SEC_CMD_RESULT_STR_LEN_EXPAND);
  140. }
  141. if (sec_cmd_ptr->wait_read_result == EXIT_RESULT) {
  142. data->cmd_state = SEC_CMD_STATUS_WAITING;
  143. sec_cmd_set_cmd_exit(data);
  144. }
  145. return;
  146. CMD_NG:
  147. data->cmd_state = SEC_CMD_STATUS_FAIL;
  148. strlcat(data->cmd_result, "NG", SEC_CMD_RESULT_STR_LEN_EXPAND);
  149. if (sec_cmd_ptr->wait_read_result == EXIT_RESULT)
  150. sec_cmd_set_cmd_exit(data);
  151. }
  152. #ifndef USE_SEC_CMD_QUEUE
  153. __visible_for_testing ssize_t cmd_store(struct device *dev,
  154. struct device_attribute *devattr, const char *buf, size_t count)
  155. {
  156. struct sec_cmd_data *data = dev_get_drvdata(dev);
  157. char *cur, *start, *end;
  158. char buff[SEC_CMD_STR_LEN] = { 0 };
  159. int len, i;
  160. struct sec_cmd *sec_cmd_ptr = NULL;
  161. char delim = ',';
  162. bool cmd_found = false;
  163. int param_cnt = 0;
  164. if (!data) {
  165. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  166. return -EINVAL;
  167. }
  168. if (strnlen(buf, SEC_CMD_STR_LEN) >= SEC_CMD_STR_LEN) {
  169. pr_err("%s: %s %s: cmd length(strlen(buf)) is over (%d,%s)!!\n",
  170. dev_name(data->fac_dev), SECLOG, __func__, (int)strlen(buf), buf);
  171. return -EINVAL;
  172. }
  173. if (count >= (unsigned int)SEC_CMD_STR_LEN) {
  174. pr_err("%s: %s %s: cmd length(count) is over (%d,%s)!!\n",
  175. dev_name(data->fac_dev), SECLOG, __func__, (unsigned int)count, buf);
  176. return -EINVAL;
  177. }
  178. if (atomic_read(&data->cmd_is_running)) {
  179. pr_err("%s: %s %s: other cmd is running.\n", dev_name(data->fac_dev), SECLOG, __func__);
  180. return -EBUSY;
  181. }
  182. /* check lock */
  183. mutex_lock(&data->cmd_lock);
  184. atomic_set(&data->cmd_is_running, 1);
  185. mutex_unlock(&data->cmd_lock);
  186. data->cmd_state = SEC_CMD_STATUS_RUNNING;
  187. for (i = 0; i < ARRAY_SIZE(data->cmd_param); i++)
  188. data->cmd_param[i] = 0;
  189. len = (int)count;
  190. if (*(buf + len - 1) == '\n')
  191. len--;
  192. memset(data->cmd, 0x00, ARRAY_SIZE(data->cmd));
  193. memcpy(data->cmd, buf, len);
  194. cur = strchr(buf, (int)delim);
  195. if (cur)
  196. memcpy(buff, buf, cur - buf);
  197. else
  198. memcpy(buff, buf, len);
  199. pr_debug("%s: %s %s: COMMAND = %s\n", dev_name(data->fac_dev), SECLOG, __func__, buff);
  200. /* find command */
  201. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  202. if (!strncmp(buff, sec_cmd_ptr->cmd_name, SEC_CMD_STR_LEN)) {
  203. if (!sec_cmd_ptr->not_support_cmds) {
  204. cmd_found = true;
  205. break;
  206. }
  207. pr_err("%s: %s %s: [%s] is in not_support_cmds list\n", dev_name(data->fac_dev), SECLOG, __func__, buff);
  208. }
  209. }
  210. check_not_support_cmd:
  211. /* set not_support_cmd */
  212. if (!cmd_found) {
  213. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  214. if (!strncmp("not_support_cmd", sec_cmd_ptr->cmd_name,
  215. SEC_CMD_STR_LEN))
  216. break;
  217. }
  218. }
  219. /* parsing parameters */
  220. if (cur && cmd_found) {
  221. cur++;
  222. start = cur;
  223. memset(buff, 0x00, ARRAY_SIZE(buff));
  224. do {
  225. if (*cur == delim || cur - buf == len) {
  226. end = cur;
  227. memcpy(buff, start, end - start);
  228. *(buff + strnlen(buff, ARRAY_SIZE(buff))) = '\0';
  229. if (kstrtoint(buff, 10, data->cmd_param + param_cnt) < 0) {
  230. pr_err("%s: %s %s: error to parse parameter\n",
  231. dev_name(data->fac_dev), SECLOG, __func__);
  232. cmd_found = false;
  233. goto check_not_support_cmd;
  234. }
  235. start = cur + 1;
  236. memset(buff, 0x00, ARRAY_SIZE(buff));
  237. param_cnt++;
  238. }
  239. cur++;
  240. } while ((cur - buf <= len) && (param_cnt < SEC_CMD_PARAM_NUM));
  241. }
  242. if (cmd_found) {
  243. char dbuff[13];
  244. char tdbuff[13 * SEC_CMD_PARAM_NUM] = { 0 };
  245. for (i = 0; i < param_cnt; i++) {
  246. snprintf(dbuff, sizeof(dbuff), "%d ", data->cmd_param[i]);
  247. strlcat(tdbuff, dbuff, sizeof(tdbuff));
  248. }
  249. if (param_cnt == 0)
  250. snprintf(tdbuff, sizeof(tdbuff), "none");
  251. pr_info("%s: %s %s: cmd = %s param = %s\n", dev_name(data->fac_dev), SECLOG, __func__, sec_cmd_ptr->cmd_name, tdbuff);
  252. } else {
  253. pr_info("%s: %s %s: cmd = %s(%s)\n", dev_name(data->fac_dev), SECLOG, __func__, buff, sec_cmd_ptr->cmd_name);
  254. }
  255. if (sec_cmd_ptr->cmd_use_cases)
  256. sec_cmd_check_store_condition(data, sec_cmd_ptr);
  257. else
  258. sec_cmd_ptr->cmd_func(data);
  259. return count;
  260. }
  261. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  262. EXPORT_SYMBOL_KUNIT(cmd_store);
  263. #endif
  264. #else /* defined USE_SEC_CMD_QUEUE */
  265. static void cmd_store_function(struct sec_cmd_data *data)
  266. {
  267. char *cur, *start, *end;
  268. char buff[SEC_CMD_STR_LEN] = { 0 };
  269. int len, i;
  270. struct sec_cmd *sec_cmd_ptr = NULL;
  271. char delim = ',';
  272. bool cmd_found = false;
  273. int param_cnt = 0;
  274. int ret;
  275. const char *buf;
  276. size_t count;
  277. struct command cmd = {{0}};
  278. if (!data) {
  279. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  280. return;
  281. }
  282. mutex_lock(&data->fifo_lock);
  283. if (kfifo_len(&data->cmd_queue)) {
  284. ret = kfifo_out(&data->cmd_queue, &cmd, sizeof(struct command));
  285. if (!ret) {
  286. pr_err("%s: %s %s: kfifo_out failed, it seems empty, ret=%d\n", dev_name(data->fac_dev), SECLOG, __func__, ret);
  287. mutex_unlock(&data->fifo_lock);
  288. return;
  289. }
  290. } else {
  291. pr_err("%s: %s %s: left cmd is nothing\n", dev_name(data->fac_dev), SECLOG, __func__);
  292. mutex_unlock(&data->fifo_lock);
  293. mutex_lock(&data->cmd_lock);
  294. atomic_set(&data->cmd_is_running, 0);
  295. mutex_unlock(&data->cmd_lock);
  296. return;
  297. }
  298. mutex_unlock(&data->fifo_lock);
  299. buf = cmd.cmd;
  300. count = strlen(buf);
  301. for (i = 0; i < (int)ARRAY_SIZE(data->cmd_param); i++)
  302. data->cmd_param[i] = 0;
  303. len = (int)count;
  304. if (*(buf + len - 1) == '\n')
  305. len--;
  306. memset(data->cmd, 0x00, ARRAY_SIZE(data->cmd));
  307. memcpy(data->cmd, buf, len);
  308. cur = strchr(buf, (int)delim);
  309. if (cur)
  310. memcpy(buff, buf, cur - buf);
  311. else
  312. memcpy(buff, buf, len);
  313. pr_debug("%s: %s %s: COMMAND : %s\n", dev_name(data->fac_dev), SECLOG, __func__, buff);
  314. /* find command */
  315. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  316. if (!strncmp(buff, sec_cmd_ptr->cmd_name, SEC_CMD_STR_LEN)) {
  317. if (!sec_cmd_ptr->not_support_cmds) {
  318. cmd_found = true;
  319. break;
  320. }
  321. pr_err("%s: %s %s: [%s] is in not_support_cmds list\n", dev_name(data->fac_dev), SECLOG, __func__, buff);
  322. }
  323. }
  324. check_not_support_cmd:
  325. /* set not_support_cmd */
  326. if (!cmd_found) {
  327. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  328. if (!strncmp("not_support_cmd", sec_cmd_ptr->cmd_name,
  329. SEC_CMD_STR_LEN))
  330. break;
  331. }
  332. }
  333. /* parsing parameters */
  334. if (cur && cmd_found) {
  335. cur++;
  336. start = cur;
  337. memset(buff, 0x00, ARRAY_SIZE(buff));
  338. do {
  339. if (*cur == delim || cur - buf == len) {
  340. end = cur;
  341. memcpy(buff, start, end - start);
  342. *(buff + strnlen(buff, ARRAY_SIZE(buff))) = '\0';
  343. if (kstrtoint(buff, 10, data->cmd_param + param_cnt) < 0) {
  344. pr_err("%s: %s %s: error to parse parameter\n",
  345. dev_name(data->fac_dev), SECLOG, __func__);
  346. cmd_found = false;
  347. goto check_not_support_cmd;
  348. }
  349. start = cur + 1;
  350. memset(buff, 0x00, ARRAY_SIZE(buff));
  351. param_cnt++;
  352. }
  353. cur++;
  354. } while ((cur - buf <= len) && (param_cnt < SEC_CMD_PARAM_NUM));
  355. }
  356. if (cmd_found) {
  357. char dbuff[13];
  358. char tdbuff[13 * SEC_CMD_PARAM_NUM] = { 0 };
  359. for (i = 0; i < param_cnt; i++) {
  360. snprintf(dbuff, sizeof(dbuff), "%d ", data->cmd_param[i]);
  361. strlcat(tdbuff, dbuff, sizeof(tdbuff));
  362. }
  363. if (param_cnt == 0)
  364. snprintf(tdbuff, sizeof(tdbuff), "none");
  365. pr_info("%s: %s %s: cmd = %s param = %s\n", dev_name(data->fac_dev), SECLOG, __func__, sec_cmd_ptr->cmd_name, tdbuff);
  366. } else {
  367. pr_info("%s: %s %s: cmd = %s(%s)\n", dev_name(data->fac_dev), SECLOG, __func__, buff, sec_cmd_ptr->cmd_name);
  368. }
  369. if (sec_cmd_ptr->cmd_use_cases)
  370. sec_cmd_check_store_condition(data, sec_cmd_ptr);
  371. else
  372. sec_cmd_ptr->cmd_func(data);
  373. if (cmd_found && sec_cmd_ptr->cmd_log) {
  374. char tbuf[32];
  375. unsigned long long t;
  376. unsigned long nanosec_rem;
  377. memset(tbuf, 0x00, sizeof(tbuf));
  378. t = local_clock();
  379. nanosec_rem = do_div(t, 1000000000);
  380. snprintf(tbuf, sizeof(tbuf), "[r:%lu.%06lu]",
  381. (unsigned long)t,
  382. nanosec_rem / 1000);
  383. #if IS_ENABLED(CONFIG_SEC_DEBUG_TSP_LOG)
  384. sec_debug_tsp_command_history(tbuf);
  385. #endif
  386. }
  387. }
  388. __visible_for_testing ssize_t cmd_store(struct device *dev, struct device_attribute *devattr,
  389. const char *buf, size_t count)
  390. {
  391. struct sec_cmd_data *data = dev_get_drvdata(dev);
  392. struct command cmd = {{0}};
  393. struct sec_cmd *sec_cmd_ptr = NULL;
  394. int queue_size;
  395. if (!data) {
  396. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  397. return -EINVAL;
  398. }
  399. if (strnlen(buf, SEC_CMD_STR_LEN) >= SEC_CMD_STR_LEN) {
  400. pr_err("%s: %s %s: cmd length(strlen(buf)) is over (%d,%s)!!\n",
  401. dev_name(data->fac_dev), SECLOG, __func__, (int)strlen(buf), buf);
  402. return -EINVAL;
  403. }
  404. if (count >= (unsigned int)SEC_CMD_STR_LEN) {
  405. pr_err("%s: %s %s: cmd length(count) is over (%d,%s)!!\n",
  406. dev_name(data->fac_dev), SECLOG, __func__, (unsigned int)count, buf);
  407. return -EINVAL;
  408. }
  409. if (strnlen(buf, SEC_CMD_STR_LEN) == 0) {
  410. pr_err("%s: %s %s: cmd length is zero (%d,%s) count(%ld)!!\n",
  411. dev_name(data->fac_dev), SECLOG, __func__, (int)strlen(buf), buf, count);
  412. return -EINVAL;
  413. }
  414. strncpy(cmd.cmd, buf, count);
  415. if (data->wait_cmd_result_done) {
  416. int ret;
  417. mutex_lock(&data->wait_lock);
  418. if (!data->cmd_result_done.done)
  419. pr_info("%s: %s %s: %s - waiting prev cmd...\n", dev_name(data->fac_dev), SECLOG, __func__, cmd.cmd);
  420. ret = wait_for_completion_interruptible_timeout(&data->cmd_result_done, msecs_to_jiffies(2000));
  421. if (ret <= 0)
  422. pr_err("%s: %s %s: completion %d\n", dev_name(data->fac_dev), SECLOG, __func__, ret);
  423. reinit_completion(&data->cmd_result_done);
  424. mutex_unlock(&data->wait_lock);
  425. }
  426. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  427. if (!strncmp(cmd.cmd, sec_cmd_ptr->cmd_name, strlen(sec_cmd_ptr->cmd_name))) {
  428. if (sec_cmd_ptr->cmd_log) {
  429. char task_info[40];
  430. char tbuf[32];
  431. unsigned long long t;
  432. unsigned long nanosec_rem;
  433. memset(tbuf, 0x00, sizeof(tbuf));
  434. t = local_clock();
  435. nanosec_rem = do_div(t, 1000000000);
  436. snprintf(tbuf, sizeof(tbuf), "[q:%lu.%06lu]",
  437. (unsigned long)t,
  438. nanosec_rem / 1000);
  439. snprintf(task_info, 40, "\n[%d:%s:%s]", current->pid, current->comm, dev_name(data->fac_dev));
  440. #if IS_ENABLED(CONFIG_SEC_DEBUG_TSP_LOG)
  441. sec_debug_tsp_command_history(task_info);
  442. sec_debug_tsp_command_history(cmd.cmd);
  443. sec_debug_tsp_command_history(tbuf);
  444. #endif
  445. }
  446. break;
  447. }
  448. }
  449. mutex_lock(&data->fifo_lock);
  450. queue_size = (kfifo_len(&data->cmd_queue) / sizeof(struct command));
  451. if (kfifo_avail(&data->cmd_queue) && (queue_size < SEC_CMD_MAX_QUEUE)) {
  452. kfifo_in(&data->cmd_queue, &cmd, sizeof(struct command));
  453. pr_info("%s: %s %s: push cmd: %s\n", dev_name(data->fac_dev), SECLOG, __func__, cmd.cmd);
  454. } else {
  455. pr_err("%s: %s %s: cmd_queue is full!!\n", dev_name(data->fac_dev), SECLOG, __func__);
  456. kfifo_reset(&data->cmd_queue);
  457. pr_err("%s: %s %s: cmd_queue is reset!!\n", dev_name(data->fac_dev), SECLOG, __func__);
  458. mutex_unlock(&data->fifo_lock);
  459. mutex_lock(&data->cmd_lock);
  460. atomic_set(&data->cmd_is_running, 0);
  461. mutex_unlock(&data->cmd_lock);
  462. if (data->wait_cmd_result_done)
  463. complete_all(&data->cmd_result_done);
  464. return -ENOSPC;
  465. }
  466. if (atomic_read(&data->cmd_is_running)) {
  467. pr_err("%s: %s %s: other cmd is running. Wait until previous cmd is done[%d]\n",
  468. dev_name(data->fac_dev), SECLOG, __func__, (int)(kfifo_len(&data->cmd_queue) / sizeof(struct command)));
  469. mutex_unlock(&data->fifo_lock);
  470. return count;
  471. }
  472. mutex_unlock(&data->fifo_lock);
  473. sec_cmd_execution(data, true);
  474. return count;
  475. }
  476. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  477. EXPORT_SYMBOL_KUNIT(cmd_store);
  478. #endif
  479. #endif
  480. __visible_for_testing ssize_t cmd_status_show(struct device *dev,
  481. struct device_attribute *devattr, char *buf)
  482. {
  483. struct sec_cmd_data *data = dev_get_drvdata(dev);
  484. char buff[16] = { 0 };
  485. if (!data) {
  486. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  487. return -EINVAL;
  488. }
  489. if (data->cmd_state == SEC_CMD_STATUS_WAITING)
  490. snprintf(buff, sizeof(buff), "WAITING");
  491. else if (data->cmd_state == SEC_CMD_STATUS_RUNNING)
  492. snprintf(buff, sizeof(buff), "RUNNING");
  493. else if (data->cmd_state == SEC_CMD_STATUS_OK)
  494. snprintf(buff, sizeof(buff), "OK");
  495. else if (data->cmd_state == SEC_CMD_STATUS_FAIL)
  496. snprintf(buff, sizeof(buff), "FAIL");
  497. else if (data->cmd_state == SEC_CMD_STATUS_EXPAND)
  498. snprintf(buff, sizeof(buff), "EXPAND");
  499. else if (data->cmd_state == SEC_CMD_STATUS_NOT_APPLICABLE)
  500. snprintf(buff, sizeof(buff), "NOT_APPLICABLE");
  501. pr_debug("%s: %s %s: %d, %s\n", dev_name(data->fac_dev), SECLOG, __func__, data->cmd_state, buff);
  502. return snprintf(buf, sizeof(buff), "%s\n", buff);
  503. }
  504. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  505. EXPORT_SYMBOL_KUNIT(cmd_status_show);
  506. #endif
  507. __visible_for_testing ssize_t cmd_status_all_show(struct device *dev,
  508. struct device_attribute *devattr, char *buf)
  509. {
  510. struct sec_cmd_data *data = dev_get_drvdata(dev);
  511. char buff[16] = { 0 };
  512. if (!data) {
  513. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  514. return -EINVAL;
  515. }
  516. if (data->cmd_all_factory_state == SEC_CMD_STATUS_WAITING)
  517. snprintf(buff, sizeof(buff), "WAITING");
  518. else if (data->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
  519. snprintf(buff, sizeof(buff), "RUNNING");
  520. else if (data->cmd_all_factory_state == SEC_CMD_STATUS_OK)
  521. snprintf(buff, sizeof(buff), "OK");
  522. else if (data->cmd_all_factory_state == SEC_CMD_STATUS_FAIL)
  523. snprintf(buff, sizeof(buff), "FAIL");
  524. else if (data->cmd_state == SEC_CMD_STATUS_EXPAND)
  525. snprintf(buff, sizeof(buff), "EXPAND");
  526. else if (data->cmd_all_factory_state == SEC_CMD_STATUS_NOT_APPLICABLE)
  527. snprintf(buff, sizeof(buff), "NOT_APPLICABLE");
  528. pr_debug("%s: %s %s: %d, %s\n", dev_name(data->fac_dev), SECLOG, __func__, data->cmd_all_factory_state, buff);
  529. return snprintf(buf, sizeof(buff), "%s\n", buff);
  530. }
  531. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  532. EXPORT_SYMBOL_KUNIT(cmd_status_all_show);
  533. #endif
  534. __visible_for_testing ssize_t cmd_result_show(struct device *dev,
  535. struct device_attribute *devattr, char *buf)
  536. {
  537. struct sec_cmd_data *data = dev_get_drvdata(dev);
  538. int size;
  539. if (!data) {
  540. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  541. return -EINVAL;
  542. }
  543. size = snprintf(buf, SEC_CMD_RESULT_STR_LEN, "%s\n",
  544. data->cmd_result + (SEC_CMD_RESULT_STR_LEN - 1) * data->cmd_result_expand_count);
  545. if (data->cmd_result_expand_count != data->cmd_result_expand) {
  546. data->cmd_state = SEC_CMD_STATUS_EXPAND;
  547. data->cmd_result_expand_count++;
  548. } else {
  549. data->cmd_state = SEC_CMD_STATUS_WAITING;
  550. }
  551. pr_info("%s: %s %s: %s\n", dev_name(data->fac_dev), SECLOG, __func__, buf);
  552. sec_cmd_set_cmd_exit(data);
  553. return size;
  554. }
  555. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  556. EXPORT_SYMBOL_KUNIT(cmd_result_show);
  557. #endif
  558. __visible_for_testing ssize_t cmd_result_all_show(struct device *dev,
  559. struct device_attribute *devattr, char *buf)
  560. {
  561. struct sec_cmd_data *data = dev_get_drvdata(dev);
  562. int size;
  563. if (!data) {
  564. pr_err("%s %s: No platform data found\n", SECLOG, __func__);
  565. return -EINVAL;
  566. }
  567. data->cmd_state = SEC_CMD_STATUS_WAITING;
  568. pr_info("%s: %s %s: %d, %s\n", dev_name(data->fac_dev), SECLOG, __func__, data->item_count, data->cmd_result_all);
  569. size = snprintf(buf, SEC_CMD_RESULT_STR_LEN, "%d%s\n", data->item_count, data->cmd_result_all);
  570. sec_cmd_set_cmd_exit(data);
  571. data->item_count = 0;
  572. memset(data->cmd_result_all, 0x00, SEC_CMD_RESULT_STR_LEN);
  573. return size;
  574. }
  575. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  576. EXPORT_SYMBOL_KUNIT(cmd_result_all_show);
  577. #endif
  578. __visible_for_testing ssize_t cmd_list_show(struct device *dev,
  579. struct device_attribute *attr, char *buf)
  580. {
  581. struct sec_cmd_data *data = dev_get_drvdata(dev);
  582. struct sec_cmd *sec_cmd_ptr = NULL;
  583. char *buffer;
  584. char buffer_name[SEC_CMD_STR_LEN];
  585. int ret = 0;
  586. buffer = kzalloc(data->cmd_buffer_size + 30, GFP_KERNEL);
  587. if (!buffer)
  588. return -ENOMEM;
  589. snprintf(buffer, 30, "++factory command list++\n");
  590. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  591. if (sec_cmd_ptr->not_support_cmds)
  592. continue;
  593. if (strncmp(sec_cmd_ptr->cmd_name, "not_support_cmd", 15)) {
  594. snprintf(buffer_name, SEC_CMD_STR_LEN, "%s\n", sec_cmd_ptr->cmd_name);
  595. strlcat(buffer, buffer_name, data->cmd_buffer_size + 30);
  596. }
  597. }
  598. ret = snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buffer);
  599. kfree(buffer);
  600. return ret;
  601. }
  602. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  603. EXPORT_SYMBOL_KUNIT(cmd_list_show);
  604. #endif
  605. static DEVICE_ATTR(cmd, 0220, NULL, cmd_store);
  606. static DEVICE_ATTR_RO(cmd_status);
  607. static DEVICE_ATTR_RO(cmd_status_all);
  608. static DEVICE_ATTR_RO(cmd_result);
  609. static DEVICE_ATTR_RO(cmd_result_all);
  610. static DEVICE_ATTR_RO(cmd_list);
  611. static struct attribute *sec_fac_attrs[] = {
  612. &dev_attr_cmd.attr,
  613. &dev_attr_cmd_status.attr,
  614. &dev_attr_cmd_status_all.attr,
  615. &dev_attr_cmd_result.attr,
  616. &dev_attr_cmd_result_all.attr,
  617. &dev_attr_cmd_list.attr,
  618. NULL,
  619. };
  620. static struct attribute_group sec_fac_attr_group = {
  621. .attrs = sec_fac_attrs,
  622. };
  623. static ssize_t prox_power_off_show(struct device *dev,
  624. struct device_attribute *attr, char *buf)
  625. {
  626. struct sec_cmd_data *sec = dev_get_drvdata(dev);
  627. struct sec_ts_plat_data *plat_data = sec->dev->platform_data;
  628. input_info(true, sec->dev, "%s: %d\n", __func__, plat_data->prox_power_off);
  629. return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", plat_data->prox_power_off);
  630. }
  631. static ssize_t prox_power_off_store(struct device *dev,
  632. struct device_attribute *attr,
  633. const char *buf, size_t count)
  634. {
  635. struct sec_cmd_data *sec = dev_get_drvdata(dev);
  636. struct sec_ts_plat_data *plat_data = sec->dev->platform_data;
  637. long data;
  638. int ret;
  639. ret = kstrtol(buf, 10, &data);
  640. if (ret < 0)
  641. return ret;
  642. input_info(true, sec->dev, "%s: %ld\n", __func__, data);
  643. plat_data->prox_power_off = data;
  644. return count;
  645. }
  646. static ssize_t support_feature_show(struct device *dev,
  647. struct device_attribute *attr, char *buf)
  648. {
  649. struct sec_cmd_data *sec = dev_get_drvdata(dev);
  650. struct sec_ts_plat_data *plat_data = sec->dev->platform_data;
  651. u32 feature = 0;
  652. if (plat_data->enable_settings_aot)
  653. feature |= INPUT_FEATURE_ENABLE_SETTINGS_AOT;
  654. if (plat_data->support_vrr)
  655. feature |= INPUT_FEATURE_ENABLE_VRR;
  656. if (plat_data->support_open_short_test)
  657. feature |= INPUT_FEATURE_SUPPORT_OPEN_SHORT_TEST;
  658. if (plat_data->support_mis_calibration_test)
  659. feature |= INPUT_FEATURE_SUPPORT_MIS_CALIBRATION_TEST;
  660. if (plat_data->support_wireless_tx)
  661. feature |= INPUT_FEATURE_SUPPORT_WIRELESS_TX;
  662. if (plat_data->enable_sysinput_enabled)
  663. feature |= INPUT_FEATURE_ENABLE_SYSINPUT_ENABLED;
  664. if (plat_data->prox_lp_scan_enabled)
  665. feature |= INPUT_FEATURE_ENABLE_PROX_LP_SCAN_ENABLED;
  666. if (plat_data->support_input_monitor)
  667. feature |= INPUT_FEATURE_SUPPORT_INPUT_MONITOR;
  668. if (plat_data->support_rawdata_motion_aivf)
  669. feature |= INPUT_FEATURE_SUPPORT_MOTION_AIVF;
  670. if (plat_data->support_rawdata_motion_palm)
  671. feature |= INPUT_FEATURE_SUPPORT_MOTION_PALM;
  672. input_info(true, sec->dev, "%s: %d%s%s%s%s%s%s%s%s%s%s%s\n",
  673. __func__, feature,
  674. feature & INPUT_FEATURE_ENABLE_SETTINGS_AOT ? " aot" : "",
  675. feature & INPUT_FEATURE_ENABLE_PRESSURE ? " pressure" : "",
  676. feature & INPUT_FEATURE_ENABLE_VRR ? " vrr" : "",
  677. feature & INPUT_FEATURE_SUPPORT_OPEN_SHORT_TEST ? " openshort" : "",
  678. feature & INPUT_FEATURE_SUPPORT_MIS_CALIBRATION_TEST ? " miscal" : "",
  679. feature & INPUT_FEATURE_SUPPORT_WIRELESS_TX ? " wirelesstx" : "",
  680. feature & INPUT_FEATURE_SUPPORT_INPUT_MONITOR ? " inputmonitor" : "",
  681. feature & INPUT_FEATURE_ENABLE_SYSINPUT_ENABLED ? " SE" : "",
  682. feature & INPUT_FEATURE_ENABLE_PROX_LP_SCAN_ENABLED ? " LPSCAN" : "",
  683. feature & INPUT_FEATURE_SUPPORT_MOTION_AIVF ? " AIVF" : "",
  684. feature & INPUT_FEATURE_SUPPORT_MOTION_PALM ? " PALM" : "");
  685. return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", feature);
  686. }
  687. static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
  688. char *buf)
  689. {
  690. struct sec_cmd_data *sec = dev_get_drvdata(dev);
  691. struct sec_ts_plat_data *plat_data = sec->dev->platform_data;
  692. if (!plat_data->enable_sysinput_enabled)
  693. return -EINVAL;
  694. input_info(true, sec->dev, "%s: enabled %d\n", __func__, atomic_read(&plat_data->enabled));
  695. return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", atomic_read(&plat_data->enabled));
  696. }
  697. ssize_t sec_cmd_enabled_show(struct device *dev, struct device_attribute *attr,
  698. char *buf)
  699. {
  700. return enabled_show(dev, attr, buf);
  701. }
  702. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  703. EXPORT_SYMBOL_KUNIT(sec_cmd_enabled_show);
  704. #endif
  705. static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
  706. const char *buf, size_t count)
  707. {
  708. struct sec_cmd_data *sec = dev_get_drvdata(dev);
  709. struct sec_ts_plat_data *plat_data = sec->dev->platform_data;
  710. int buff[2];
  711. int ret;
  712. if (!plat_data->enable_sysinput_enabled)
  713. return -EINVAL;
  714. ret = sscanf(buf, "%d,%d", &buff[0], &buff[1]);
  715. if (ret != 2) {
  716. input_err(true, sec->dev,
  717. "%s: failed read params [%d]\n", __func__, ret);
  718. return -EINVAL;
  719. }
  720. if (buff[0] == DISPLAY_STATE_ON && buff[1] == DISPLAY_EVENT_LATE) {
  721. input_info(true, sec->dev, "%s: DISPLAY_STATE_ON\n", __func__);
  722. if (atomic_read(&plat_data->enabled)) {
  723. input_err(true, sec->dev, "%s: device already enabled\n", __func__);
  724. goto out;
  725. }
  726. ret = sec_input_enable_device(plat_data->dev);
  727. } else if (buff[0] == DISPLAY_STATE_OFF && buff[1] == DISPLAY_EVENT_EARLY) {
  728. input_info(true, sec->dev, "%s: DISPLAY_STATE_OFF\n", __func__);
  729. if (!atomic_read(&plat_data->enabled)) {
  730. input_err(true, sec->dev, "%s: device already disabled\n", __func__);
  731. goto out;
  732. }
  733. ret = sec_input_disable_device(plat_data->dev);
  734. } else if (buff[0] == DISPLAY_STATE_FORCE_ON) {
  735. input_info(true, sec->dev, "%s: DISPLAY_STATE_FORCE_ON\n", __func__);
  736. if (atomic_read(&plat_data->enabled)) {
  737. input_err(true, sec->dev, "%s: device already enabled\n", __func__);
  738. goto out;
  739. }
  740. ret = sec_input_enable_device(plat_data->dev);
  741. } else if (buff[0] == DISPLAY_STATE_FORCE_OFF || buff[0] == DISPLAY_STATE_LPM_OFF) {
  742. input_info(true, sec->dev, "%s: %s\n", __func__, buff[0] == DISPLAY_STATE_FORCE_OFF ?
  743. "DISPLAY_STATE_FORCE_OFF" : "DISPLAY_STATE_LPM_OFF");
  744. if (!atomic_read(&plat_data->enabled)) {
  745. input_err(true, sec->dev, "%s: device already disabled\n", __func__);
  746. goto out;
  747. }
  748. ret = sec_input_disable_device(plat_data->dev);
  749. }
  750. if (ret)
  751. return ret;
  752. out:
  753. return count;
  754. }
  755. ssize_t sec_cmd_enabled_store(struct device *dev, struct device_attribute *attr,
  756. const char *buf, size_t count)
  757. {
  758. return enabled_store(dev, attr, buf, count);
  759. }
  760. #if IS_ENABLED(CONFIG_SEC_KUNIT)
  761. EXPORT_SYMBOL_KUNIT(sec_cmd_enabled_store);
  762. #endif
  763. static DEVICE_ATTR_RW(prox_power_off);
  764. static DEVICE_ATTR_RO(support_feature);
  765. static DEVICE_ATTR_RW(enabled);
  766. static struct attribute *sec_fac_common_attrs[] = {
  767. &dev_attr_prox_power_off.attr,
  768. &dev_attr_support_feature.attr,
  769. &dev_attr_enabled.attr,
  770. NULL,
  771. };
  772. static struct attribute_group sec_fac_common_attr_group = {
  773. .attrs = sec_fac_common_attrs,
  774. };
  775. static void sec_cmd_parse_dt_not_support_cmds(struct sec_cmd_data *data)
  776. {
  777. struct device *dev;
  778. struct device_node *np;
  779. struct sec_cmd *sec_cmd_ptr = NULL;
  780. int count = 0;
  781. int ii = 0;
  782. int ret = 0;
  783. if (data->dev)
  784. dev = data->dev;
  785. else
  786. return;
  787. if (dev->of_node)
  788. np = dev->of_node;
  789. else
  790. return;
  791. count = of_property_count_strings(np, "sec_cmd,not_support_cmds");
  792. for (ii = 0; ii < count; ii++) {
  793. const char *buff;
  794. ret = of_property_read_string_index(np, "sec_cmd,not_support_cmds", ii, &buff);
  795. if (ret < 0 || strlen(buff) <= 0) {
  796. input_err(true, dev, "%s: failed get sec_cmd,not_support_cmds: %d, %lu\n", __func__, ret, strlen(buff));
  797. return;
  798. }
  799. list_for_each_entry(sec_cmd_ptr, &data->cmd_list_head, list) {
  800. if (!strncmp(buff, sec_cmd_ptr->cmd_name, SEC_CMD_STR_LEN)) {
  801. sec_cmd_ptr->not_support_cmds = true;
  802. }
  803. }
  804. input_info(true, dev, "%s: sec_cmd,not_support_cmds(%d): %s\n", __func__, ii, buff);
  805. }
  806. }
  807. int sec_cmd_init(struct sec_cmd_data *data, struct device *dev, struct sec_cmd *cmds,
  808. int len, int devt, struct attribute_group *vendor_attr_group)
  809. {
  810. const char *dev_name;
  811. int ret, i;
  812. INIT_LIST_HEAD(&data->cmd_list_head);
  813. data->cmd_buffer_size = 0;
  814. for (i = 0; i < len; i++) {
  815. list_add_tail(&cmds[i].list, &data->cmd_list_head);
  816. if (cmds[i].cmd_name)
  817. data->cmd_buffer_size += strlen(cmds[i].cmd_name) + 1;
  818. }
  819. mutex_init(&data->cmd_lock);
  820. mutex_init(&data->fs_lock);
  821. mutex_lock(&data->cmd_lock);
  822. atomic_set(&data->cmd_is_running, 0);
  823. mutex_unlock(&data->cmd_lock);
  824. data->cmd_result = kzalloc(SEC_CMD_RESULT_STR_LEN_EXPAND, GFP_KERNEL);
  825. if (!data->cmd_result)
  826. goto err_alloc_cmd_result;
  827. if (!IS_ERR_OR_NULL(dev))
  828. data->dev = dev;
  829. #ifdef USE_SEC_CMD_QUEUE
  830. if (kfifo_alloc(&data->cmd_queue,
  831. SEC_CMD_MAX_QUEUE * sizeof(struct command), GFP_KERNEL)) {
  832. pr_err("%s %s: failed to alloc queue for cmd\n", SECLOG, __func__);
  833. goto err_alloc_queue;
  834. }
  835. mutex_init(&data->fifo_lock);
  836. mutex_init(&data->wait_lock);
  837. init_completion(&data->cmd_result_done);
  838. complete_all(&data->cmd_result_done);
  839. INIT_DELAYED_WORK(&data->cmd_work, cmd_exit_work);
  840. #endif
  841. switch (devt) {
  842. case SEC_CLASS_DEVT_TSP:
  843. dev_name = SEC_CLASS_DEV_NAME_TSP;
  844. break;
  845. case SEC_CLASS_DEVT_TSP1:
  846. dev_name = SEC_CLASS_DEV_NAME_TSP1;
  847. break;
  848. case SEC_CLASS_DEVT_TSP2:
  849. dev_name = SEC_CLASS_DEV_NAME_TSP2;
  850. break;
  851. case SEC_CLASS_DEVT_TKEY:
  852. dev_name = SEC_CLASS_DEV_NAME_TKEY;
  853. break;
  854. case SEC_CLASS_DEVT_WACOM:
  855. dev_name = SEC_CLASS_DEV_NAME_WACOM;
  856. break;
  857. case SEC_CLASS_DEVT_SIDEKEY:
  858. dev_name = SEC_CLASS_DEV_NAME_SIDEKEY;
  859. break;
  860. default:
  861. pr_err("%s %s: not defined devt=%d\n", SECLOG, __func__, devt);
  862. goto err_get_dev_name;
  863. }
  864. #if IS_ENABLED(CONFIG_DRV_SAMSUNG)
  865. data->fac_dev = sec_device_create(data, dev_name);
  866. #else
  867. tsp_sec_class = class_create(THIS_MODULE, dev_name);
  868. if (IS_ERR(tsp_sec_class)) {
  869. pr_err("%s %s: Failed to create class(sec) %ld\n", SECLOG, __func__, PTR_ERR(tsp_sec_class));
  870. return PTR_ERR(tsp_sec_class);
  871. }
  872. data->fac_dev = device_create(tsp_sec_class, NULL, devt, data, "%s", dev_name);
  873. #endif
  874. if (IS_ERR(data->fac_dev)) {
  875. pr_err("%s %s: failed to create device for the sysfs\n", SECLOG, __func__);
  876. goto err_sysfs_device;
  877. }
  878. dev_set_drvdata(data->fac_dev, data);
  879. sec_cmd_parse_dt_not_support_cmds(data);
  880. ret = sysfs_create_group(&data->fac_dev->kobj, &sec_fac_attr_group);
  881. if (ret < 0) {
  882. pr_err("%s %s: failed to create sysfs group\n", SECLOG, __func__);
  883. goto err_sysfs_group;
  884. }
  885. pr_info("%s: %s create sec_fac_attr_group: done\n", SECLOG, __func__);
  886. if (!IS_ERR_OR_NULL(vendor_attr_group)) {
  887. ret = sysfs_create_group(&data->fac_dev->kobj, vendor_attr_group);
  888. if (ret < 0) {
  889. pr_err("%s %s: failed to create sysfs group\n", SECLOG, __func__);
  890. goto err_vendor_sysfs_group;
  891. }
  892. data->vendor_attr_group = vendor_attr_group;
  893. pr_info("%s: %s create vendor_attr_group: done\n", SECLOG, __func__);
  894. }
  895. if (!IS_ERR_OR_NULL(dev)) {
  896. /* if you do not use sec_ts_plat_data, should invoke sec_cmd_init_without_platdata */
  897. struct sec_ts_plat_data *plat_data = dev->platform_data;
  898. plat_data->sec = data;
  899. ret = sysfs_create_group(&data->fac_dev->kobj, &sec_fac_common_attr_group);
  900. if (ret < 0) {
  901. pr_err("%s %s: failed to create sec_fac_common_attr_group\n", SECLOG, __func__);
  902. goto err_common_sysfs_group;
  903. }
  904. pr_info("%s: %s create sec_fac_common_attr_group: done\n", SECLOG, __func__);
  905. }
  906. pr_info("%s: %s %s: done\n", dev_name, SECLOG, __func__);
  907. sec_cmd_send_event_to_user(data, NULL, "RESULT=PROBE_DONE");
  908. return 0;
  909. err_common_sysfs_group:
  910. if (!IS_ERR_OR_NULL(data->vendor_attr_group))
  911. sysfs_remove_group(&data->fac_dev->kobj, data->vendor_attr_group);
  912. err_vendor_sysfs_group:
  913. sysfs_remove_group(&data->fac_dev->kobj, &sec_fac_attr_group);
  914. err_sysfs_group:
  915. #if IS_ENABLED(CONFIG_DRV_SAMSUNG)
  916. sec_device_destroy(data->fac_dev->devt);
  917. #else
  918. device_destroy(tsp_sec_class, devt);
  919. #endif
  920. err_sysfs_device:
  921. err_get_dev_name:
  922. #ifdef USE_SEC_CMD_QUEUE
  923. mutex_destroy(&data->fifo_lock);
  924. kfifo_free(&data->cmd_queue);
  925. mutex_destroy(&data->wait_lock);
  926. err_alloc_queue:
  927. #endif
  928. kfree(data->cmd_result);
  929. err_alloc_cmd_result:
  930. mutex_destroy(&data->cmd_lock);
  931. list_del(&data->cmd_list_head);
  932. return -ENODEV;
  933. }
  934. EXPORT_SYMBOL(sec_cmd_init);
  935. /*
  936. * sec_cmd_init_without_platdata
  937. *
  938. * If device driver doesn't use sec_ts_plat_data as platform_data, you should init cmds with this function.
  939. * and should make sysfs like sec_fac_common_attrs on device driver side
  940. */
  941. int sec_cmd_init_without_platdata(struct sec_cmd_data *data, struct sec_cmd *cmds,
  942. int len, int devt, struct attribute_group *vendor_attr_group)
  943. {
  944. return sec_cmd_init(data, NULL, cmds, len, devt, vendor_attr_group);
  945. }
  946. EXPORT_SYMBOL(sec_cmd_init_without_platdata);
  947. void sec_cmd_exit(struct sec_cmd_data *data, int devt)
  948. {
  949. #ifdef USE_SEC_CMD_QUEUE
  950. struct command cmd = {{0}};
  951. int ret;
  952. #endif
  953. pr_info("%s: %s %s\n", dev_name(data->fac_dev), SECLOG, __func__);
  954. if (!IS_ERR_OR_NULL(data->fac_dev))
  955. sysfs_remove_group(&data->fac_dev->kobj, &sec_fac_common_attr_group);
  956. if (!IS_ERR_OR_NULL(data->vendor_attr_group))
  957. sysfs_remove_group(&data->fac_dev->kobj, data->vendor_attr_group);
  958. sysfs_remove_group(&data->fac_dev->kobj, &sec_fac_attr_group);
  959. dev_set_drvdata(data->fac_dev, NULL);
  960. #if IS_ENABLED(CONFIG_DRV_SAMSUNG)
  961. sec_device_destroy(data->fac_dev->devt);
  962. #else
  963. device_destroy(tsp_sec_class, devt);
  964. #endif
  965. #ifdef USE_SEC_CMD_QUEUE
  966. mutex_lock(&data->fifo_lock);
  967. while (kfifo_len(&data->cmd_queue)) {
  968. ret = kfifo_out(&data->cmd_queue, &cmd, sizeof(struct command));
  969. if (!ret)
  970. pr_err("%s %s: kfifo_out failed, it seems empty, ret=%d\n", SECLOG, __func__, ret);
  971. pr_info("%s %s: remove pending commands: %s", SECLOG, __func__, cmd.cmd);
  972. }
  973. mutex_unlock(&data->fifo_lock);
  974. mutex_destroy(&data->fifo_lock);
  975. kfifo_free(&data->cmd_queue);
  976. mutex_destroy(&data->wait_lock);
  977. cancel_delayed_work_sync(&data->cmd_work);
  978. flush_delayed_work(&data->cmd_work);
  979. #endif
  980. if (!IS_ERR_OR_NULL(data->dev)) {
  981. struct sec_ts_plat_data *plat_data = data->dev->platform_data;
  982. plat_data->sec = NULL;
  983. }
  984. data->fac_dev = NULL;
  985. kfree(data->cmd_result);
  986. mutex_destroy(&data->cmd_lock);
  987. list_del(&data->cmd_list_head);
  988. }
  989. EXPORT_SYMBOL(sec_cmd_exit);
  990. void sec_cmd_send_event_to_user(struct sec_cmd_data *data, char *test, char *result)
  991. {
  992. char *event[5];
  993. char timestamp[32];
  994. char feature[32];
  995. char stest[32];
  996. char sresult[64];
  997. ktime_t calltime;
  998. u64 realtime;
  999. int curr_time;
  1000. char *eol = "\0";
  1001. if (!data || !data->fac_dev)
  1002. return;
  1003. calltime = ktime_get();
  1004. realtime = ktime_to_ns(calltime);
  1005. do_div(realtime, NSEC_PER_USEC);
  1006. curr_time = realtime / USEC_PER_MSEC;
  1007. snprintf(timestamp, 32, "TIMESTAMP=%d", curr_time);
  1008. strncat(timestamp, eol, 1);
  1009. snprintf(feature, 32, "FEATURE=TSP");
  1010. strncat(feature, eol, 1);
  1011. if (!test)
  1012. snprintf(stest, 32, "TEST=NULL");
  1013. else
  1014. snprintf(stest, 32, "%s", test);
  1015. strncat(stest, eol, 1);
  1016. if (!result)
  1017. snprintf(sresult, 64, "RESULT=NULL");
  1018. else
  1019. snprintf(sresult, 64, "%s", result);
  1020. strncat(sresult, eol, 1);
  1021. pr_info("%s: %s %s: time:%s, feature:%s, test:%s, result:%s\n",
  1022. dev_name(data->fac_dev), SECLOG, __func__, timestamp, feature, stest, sresult);
  1023. event[0] = timestamp;
  1024. event[1] = feature;
  1025. event[2] = stest;
  1026. event[3] = sresult;
  1027. event[4] = NULL;
  1028. kobject_uevent_env(&data->fac_dev->kobj, KOBJ_CHANGE, event);
  1029. }
  1030. EXPORT_SYMBOL(sec_cmd_send_event_to_user);
  1031. void sec_cmd_send_status_uevent(struct sec_cmd_data *data, enum sec_cmd_status_uevent_type type, int value)
  1032. {
  1033. char test[32] = { 0 };
  1034. char result[32] = { 0 };
  1035. switch (type) {
  1036. case STATUS_TYPE_WET:
  1037. snprintf(test, sizeof(test), "STATUS=WET");
  1038. break;
  1039. case STATUS_TYPE_NOISE:
  1040. snprintf(test, sizeof(test), "STATUS=NOISE");
  1041. break;
  1042. case STATUS_TYPE_FREQ:
  1043. snprintf(test, sizeof(test), "STATUS=FREQ");
  1044. break;
  1045. default:
  1046. pr_info("%s: %s %s: undefined type %d\n",
  1047. dev_name(data->fac_dev), SECLOG, __func__, type);
  1048. return;
  1049. }
  1050. snprintf(result, sizeof(result), "VALUE=%d", value);
  1051. sec_cmd_send_event_to_user(data, test, result);
  1052. }
  1053. EXPORT_SYMBOL(sec_cmd_send_status_uevent);
  1054. void sec_cmd_send_gesture_uevent(struct sec_cmd_data *data, int type, int x, int y)
  1055. {
  1056. struct sec_ts_plat_data *plat_data;
  1057. char test[32] = { 0 };
  1058. char result[32] = { 0 };
  1059. if (!data->dev)
  1060. return;
  1061. plat_data = data->dev->platform_data;
  1062. if (IS_ERR_OR_NULL(plat_data))
  1063. return;
  1064. snprintf(test, sizeof(test), "GESTURE=%d", type);
  1065. snprintf(result, sizeof(result), "POS=%d,%d", x, y);
  1066. sec_cmd_send_event_to_user(data, test, result);
  1067. }
  1068. EXPORT_SYMBOL(sec_cmd_send_gesture_uevent);
  1069. MODULE_DESCRIPTION("Samsung input command");
  1070. MODULE_LICENSE("GPL");