goodix_ts_tools.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. * Goodix Touchscreen Driver
  3. * Copyright (C) 2020 - 2021 Goodix, Inc.
  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 as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be a reference
  11. * to you, when you are integrating the GOODiX's CTP IC into your system,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. */
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/atomic.h>
  20. #include <linux/miscdevice.h>
  21. #include <linux/slab.h>
  22. #include <linux/uaccess.h>
  23. #include <linux/fs.h>
  24. #include <linux/list.h>
  25. #include <linux/ioctl.h>
  26. #include <linux/wait.h>
  27. #include "goodix_ts_core.h"
  28. #define GOODIX_TOOLS_NAME "gtp_tools"
  29. #define GOODIX_TOOLS_VER_MAJOR 1
  30. #define GOODIX_TOOLS_VER_MINOR 0
  31. static const u16 goodix_tools_ver = ((GOODIX_TOOLS_VER_MAJOR << 8) +
  32. (GOODIX_TOOLS_VER_MINOR));
  33. #define GOODIX_TS_IOC_MAGIC 'G'
  34. #define NEGLECT_SIZE_MASK (~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
  35. #define GTP_IRQ_ENABLE _IO(GOODIX_TS_IOC_MAGIC, 0)
  36. #define GTP_DEV_RESET _IO(GOODIX_TS_IOC_MAGIC, 1)
  37. #define GTP_SEND_COMMAND (_IOW(GOODIX_TS_IOC_MAGIC, 2, u8) & NEGLECT_SIZE_MASK)
  38. #define GTP_SEND_CONFIG (_IOW(GOODIX_TS_IOC_MAGIC, 3, u8) & NEGLECT_SIZE_MASK)
  39. #define GTP_ASYNC_READ (_IOR(GOODIX_TS_IOC_MAGIC, 4, u8) & NEGLECT_SIZE_MASK)
  40. #define GTP_SYNC_READ (_IOR(GOODIX_TS_IOC_MAGIC, 5, u8) & NEGLECT_SIZE_MASK)
  41. #define GTP_ASYNC_WRITE (_IOW(GOODIX_TS_IOC_MAGIC, 6, u8) & NEGLECT_SIZE_MASK)
  42. #define GTP_READ_CONFIG (_IOW(GOODIX_TS_IOC_MAGIC, 7, u8) & NEGLECT_SIZE_MASK)
  43. #define GTP_ESD_ENABLE _IO(GOODIX_TS_IOC_MAGIC, 8)
  44. #define GTP_TOOLS_VER (_IOR(GOODIX_TS_IOC_MAGIC, 9, u8) & NEGLECT_SIZE_MASK)
  45. #define GTP_TOOLS_CTRL_SYNC (_IOW(GOODIX_TS_IOC_MAGIC, 10, u8) & NEGLECT_SIZE_MASK)
  46. #define MAX_BUF_LENGTH (16*1024)
  47. #define IRQ_FALG (0x01 << 2)
  48. #define I2C_MSG_HEAD_LEN 20
  49. /*
  50. * struct goodix_tools_dev - goodix tools device struct
  51. * @ts_core: The core data struct of ts driver
  52. * @ops_mode: represent device work mode
  53. * @rawdiffcmd: Set slave device into rawdata mode
  54. * @normalcmd: Set slave device into normal mode
  55. * @wq: Wait queue struct use in synchronous data read
  56. * @mutex: Protect goodix_tools_dev
  57. * @in_use: device in use
  58. */
  59. struct goodix_tools_dev {
  60. struct goodix_ts_core *ts_core;
  61. struct list_head head;
  62. unsigned int ops_mode;
  63. struct goodix_ts_cmd rawdiffcmd, normalcmd;
  64. wait_queue_head_t wq;
  65. struct mutex mutex;
  66. atomic_t in_use;
  67. struct goodix_ext_module module;
  68. } *goodix_tools_dev;
  69. /* read data asynchronous,
  70. * success return data length, otherwise return < 0
  71. */
  72. static int async_read(struct goodix_tools_dev *dev, void __user *arg)
  73. {
  74. u8 *databuf = NULL;
  75. int ret = 0;
  76. u32 reg_addr, length;
  77. u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
  78. const struct goodix_ts_hw_ops *hw_ops = dev->ts_core->hw_ops;
  79. ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
  80. if (ret)
  81. return -EFAULT;
  82. reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
  83. + (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
  84. length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
  85. + (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
  86. if (length > MAX_BUF_LENGTH) {
  87. ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
  88. return -EINVAL;
  89. }
  90. databuf = kzalloc(length, GFP_KERNEL);
  91. if (!databuf) {
  92. ts_err("Alloc memory failed");
  93. return -ENOMEM;
  94. }
  95. if (hw_ops->read(dev->ts_core, reg_addr, databuf, length)) {
  96. ret = -EBUSY;
  97. ts_err("Read i2c failed");
  98. goto err_out;
  99. }
  100. ret = copy_to_user((u8 *)arg + I2C_MSG_HEAD_LEN, databuf, length);
  101. if (ret) {
  102. ret = -EFAULT;
  103. ts_err("Copy_to_user failed");
  104. goto err_out;
  105. }
  106. ret = length;
  107. err_out:
  108. kfree(databuf);
  109. return ret;
  110. }
  111. /* if success return config data length */
  112. static int read_config_data(struct goodix_ts_core *ts_core, void __user *arg)
  113. {
  114. int ret = 0;
  115. u32 reg_addr, length;
  116. u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
  117. u8 *tmp_buf;
  118. ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
  119. if (ret) {
  120. ts_err("Copy data from user failed");
  121. return -EFAULT;
  122. }
  123. reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
  124. + (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
  125. length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
  126. + (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
  127. ts_info("read config,reg_addr=0x%x, length=%d", reg_addr, length);
  128. if (length > MAX_BUF_LENGTH) {
  129. ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
  130. return -EINVAL;
  131. }
  132. tmp_buf = kzalloc(length, GFP_KERNEL);
  133. if (!tmp_buf) {
  134. ts_err("failed alloc memory");
  135. return -ENOMEM;
  136. }
  137. /* if reg_addr == 0, read config data with specific flow */
  138. if (!reg_addr) {
  139. if (ts_core->hw_ops->read_config)
  140. ret = ts_core->hw_ops->read_config(ts_core, tmp_buf, length);
  141. else
  142. ret = -EINVAL;
  143. } else {
  144. ret = ts_core->hw_ops->read(ts_core, reg_addr, tmp_buf, length);
  145. if (!ret)
  146. ret = length;
  147. }
  148. if (ret <= 0)
  149. goto err_out;
  150. if (copy_to_user((u8 *)arg + I2C_MSG_HEAD_LEN, tmp_buf, ret)) {
  151. ret = -EFAULT;
  152. ts_err("Copy_to_user failed");
  153. }
  154. err_out:
  155. kfree(tmp_buf);
  156. return ret;
  157. }
  158. /* write data to i2c asynchronous,
  159. * success return bytes write, else return <= 0
  160. */
  161. static int async_write(struct goodix_tools_dev *dev, void __user *arg)
  162. {
  163. u8 *databuf;
  164. int ret = 0;
  165. u32 reg_addr, length;
  166. u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
  167. struct goodix_ts_core *ts_core = dev->ts_core;
  168. const struct goodix_ts_hw_ops *hw_ops = ts_core->hw_ops;
  169. ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
  170. if (ret) {
  171. ts_err("Copy data from user failed");
  172. return -EFAULT;
  173. }
  174. reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
  175. + (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
  176. length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
  177. + (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
  178. if (length > MAX_BUF_LENGTH) {
  179. ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
  180. return -EINVAL;
  181. }
  182. databuf = kzalloc(length, GFP_KERNEL);
  183. if (!databuf) {
  184. ts_err("Alloc memory failed");
  185. return -ENOMEM;
  186. }
  187. ret = copy_from_user(databuf, (u8 *)arg + I2C_MSG_HEAD_LEN, length);
  188. if (ret) {
  189. ret = -EFAULT;
  190. ts_err("Copy data from user failed");
  191. goto err_out;
  192. }
  193. if (hw_ops->write(ts_core, reg_addr, databuf, length)) {
  194. ret = -EBUSY;
  195. ts_err("Write data to device failed");
  196. } else {
  197. ret = length;
  198. }
  199. err_out:
  200. kfree(databuf);
  201. return ret;
  202. }
  203. static int init_cfg_data(struct goodix_ic_config *cfg, void __user *arg)
  204. {
  205. int ret = 0;
  206. u32 length;
  207. u8 i2c_msg_head[I2C_MSG_HEAD_LEN] = {0};
  208. ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
  209. if (ret) {
  210. ts_err("Copy data from user failed");
  211. return -EFAULT;
  212. }
  213. length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
  214. + (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
  215. if (length > GOODIX_CFG_MAX_SIZE) {
  216. ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
  217. return -EINVAL;
  218. }
  219. ret = copy_from_user(cfg->data, (u8 *)arg + I2C_MSG_HEAD_LEN, length);
  220. if (ret) {
  221. ts_err("Copy data from user failed");
  222. return -EFAULT;
  223. }
  224. cfg->len = length;
  225. return 0;
  226. }
  227. /**
  228. * goodix_tools_ioctl - ioctl implementation
  229. *
  230. * @filp: Pointer to file opened
  231. * @cmd: Ioctl opertion command
  232. * @arg: Command data
  233. * Returns >=0 - succeed, else failed
  234. */
  235. static long goodix_tools_ioctl(struct file *filp, unsigned int cmd,
  236. unsigned long arg)
  237. {
  238. int ret = 0;
  239. struct goodix_tools_dev *dev = filp->private_data;
  240. struct goodix_ts_core *ts_core;
  241. const struct goodix_ts_hw_ops *hw_ops;
  242. struct goodix_ic_config *temp_cfg = NULL;
  243. if (!dev->ts_core) {
  244. ts_err("Tools module not register");
  245. return -EINVAL;
  246. }
  247. ts_core = dev->ts_core;
  248. hw_ops = ts_core->hw_ops;
  249. if (_IOC_TYPE(cmd) != GOODIX_TS_IOC_MAGIC) {
  250. ts_err("Bad magic num:%c", _IOC_TYPE(cmd));
  251. return -ENOTTY;
  252. }
  253. switch (cmd & NEGLECT_SIZE_MASK) {
  254. case GTP_IRQ_ENABLE:
  255. if (arg == 1) {
  256. hw_ops->irq_enable(ts_core, true);
  257. mutex_lock(&dev->mutex);
  258. dev->ops_mode |= IRQ_FALG;
  259. mutex_unlock(&dev->mutex);
  260. ts_info("IRQ enabled");
  261. } else if (arg == 0) {
  262. hw_ops->irq_enable(ts_core, false);
  263. mutex_lock(&dev->mutex);
  264. dev->ops_mode &= ~IRQ_FALG;
  265. mutex_unlock(&dev->mutex);
  266. ts_info("IRQ disabled");
  267. } else {
  268. ts_info("Irq aready set with, arg = %ld", arg);
  269. }
  270. ret = 0;
  271. break;
  272. case GTP_ESD_ENABLE:
  273. if (arg == 0)
  274. goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
  275. else
  276. goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
  277. break;
  278. case GTP_DEV_RESET:
  279. hw_ops->reset(ts_core, GOODIX_NORMAL_RESET_DELAY_MS);
  280. break;
  281. case GTP_SEND_COMMAND:
  282. /* deprecated command */
  283. ts_err("the GTP_SEND_COMMAND function has been removed");
  284. ret = -EINVAL;
  285. break;
  286. case GTP_SEND_CONFIG:
  287. temp_cfg = kzalloc(sizeof(struct goodix_ic_config), GFP_KERNEL);
  288. if (!temp_cfg) {
  289. ts_err("Memory allco err");
  290. ret = -ENOMEM;
  291. goto err_out;
  292. }
  293. ret = init_cfg_data(temp_cfg, (void __user *)arg);
  294. if (!ret && hw_ops->send_config) {
  295. ret = hw_ops->send_config(ts_core, temp_cfg->data, temp_cfg->len);
  296. if (ret) {
  297. ts_err("Failed send config");
  298. ret = -EAGAIN;
  299. } else {
  300. ts_info("Send config success");
  301. ret = 0;
  302. }
  303. }
  304. kfree(temp_cfg);
  305. temp_cfg = NULL;
  306. break;
  307. case GTP_READ_CONFIG:
  308. ret = read_config_data(ts_core, (void __user *)arg);
  309. if (ret > 0)
  310. ts_info("success read config:len=%d", ret);
  311. else
  312. ts_err("failed read config:ret=0x%x", ret);
  313. break;
  314. case GTP_ASYNC_READ:
  315. ret = async_read(dev, (void __user *)arg);
  316. if (ret < 0)
  317. ts_err("Async data read failed");
  318. break;
  319. case GTP_SYNC_READ:
  320. ts_info("unsupport sync read");
  321. break;
  322. case GTP_ASYNC_WRITE:
  323. ret = async_write(dev, (void __user *)arg);
  324. if (ret < 0)
  325. ts_err("Async data write failed");
  326. break;
  327. case GTP_TOOLS_VER:
  328. ret = copy_to_user((u8 *)arg, &goodix_tools_ver, sizeof(u16));
  329. if (ret)
  330. ts_err("failed copy driver version info to user");
  331. break;
  332. case GTP_TOOLS_CTRL_SYNC:
  333. ts_core->tools_ctrl_sync = !!arg;
  334. ts_info("set tools ctrl sync %d", ts_core->tools_ctrl_sync);
  335. break;
  336. default:
  337. ts_info("Invalid cmd");
  338. ret = -ENOTTY;
  339. break;
  340. }
  341. err_out:
  342. return ret;
  343. }
  344. #ifdef CONFIG_COMPAT
  345. static long goodix_tools_compat_ioctl(struct file *file, unsigned int cmd,
  346. unsigned long arg)
  347. {
  348. void __user *arg32 = compat_ptr(arg);
  349. if (!file->f_op || !file->f_op->unlocked_ioctl)
  350. return -ENOTTY;
  351. return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32);
  352. }
  353. #endif
  354. static int goodix_tools_open(struct inode *inode, struct file *filp)
  355. {
  356. int ret = 0;
  357. ts_info("try open tool");
  358. /* Only the first time open device need to register module */
  359. ret = goodix_register_ext_module_no_wait(&goodix_tools_dev->module);
  360. if (ret) {
  361. ts_info("failed register to core module");
  362. return -EFAULT;
  363. }
  364. ts_info("success open tools");
  365. goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
  366. filp->private_data = goodix_tools_dev;
  367. atomic_set(&goodix_tools_dev->in_use, 1);
  368. return 0;
  369. }
  370. static int goodix_tools_release(struct inode *inode, struct file *filp)
  371. {
  372. int ret = 0;
  373. /* when the last close this dev node unregister the module */
  374. goodix_tools_dev->ts_core->tools_ctrl_sync = false;
  375. atomic_set(&goodix_tools_dev->in_use, 0);
  376. goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
  377. ret = goodix_unregister_ext_module(&goodix_tools_dev->module);
  378. return ret;
  379. }
  380. static int goodix_tools_module_init(struct goodix_ts_core *core_data,
  381. struct goodix_ext_module *module)
  382. {
  383. struct goodix_tools_dev *tools_dev = module->priv_data;
  384. if (core_data)
  385. tools_dev->ts_core = core_data;
  386. else
  387. return -ENODEV;
  388. return 0;
  389. }
  390. static int goodix_tools_module_exit(struct goodix_ts_core *core_data,
  391. struct goodix_ext_module *module)
  392. {
  393. struct goodix_tools_dev *tools_dev = module->priv_data;
  394. ts_debug("tools module unregister");
  395. if (atomic_read(&tools_dev->in_use)) {
  396. ts_err("tools module busy, please close it then retry");
  397. return -EBUSY;
  398. }
  399. return 0;
  400. }
  401. static const struct file_operations goodix_tools_fops = {
  402. .owner = THIS_MODULE,
  403. .open = goodix_tools_open,
  404. .release = goodix_tools_release,
  405. .unlocked_ioctl = goodix_tools_ioctl,
  406. #ifdef CONFIG_COMPAT
  407. .compat_ioctl = goodix_tools_compat_ioctl,
  408. #endif
  409. };
  410. static struct miscdevice goodix_tools_miscdev = {
  411. .minor = MISC_DYNAMIC_MINOR,
  412. .name = GOODIX_TOOLS_NAME,
  413. .fops = &goodix_tools_fops,
  414. };
  415. static struct goodix_ext_module_funcs goodix_tools_module_funcs = {
  416. .init = goodix_tools_module_init,
  417. .exit = goodix_tools_module_exit,
  418. };
  419. /**
  420. * goodix_tools_init - init goodix tools device and register a miscdevice
  421. *
  422. * return: 0 success, else failed
  423. */
  424. int goodix_tools_init(void)
  425. {
  426. int ret;
  427. goodix_tools_dev = kzalloc(sizeof(struct goodix_tools_dev), GFP_KERNEL);
  428. if (goodix_tools_dev == NULL) {
  429. ts_err("Memory allco err");
  430. return -ENOMEM;
  431. }
  432. INIT_LIST_HEAD(&goodix_tools_dev->head);
  433. goodix_tools_dev->ops_mode = 0;
  434. goodix_tools_dev->ops_mode |= IRQ_FALG;
  435. init_waitqueue_head(&goodix_tools_dev->wq);
  436. mutex_init(&goodix_tools_dev->mutex);
  437. atomic_set(&goodix_tools_dev->in_use, 0);
  438. goodix_tools_dev->module.funcs = &goodix_tools_module_funcs;
  439. goodix_tools_dev->module.name = GOODIX_TOOLS_NAME;
  440. goodix_tools_dev->module.priv_data = goodix_tools_dev;
  441. goodix_tools_dev->module.priority = EXTMOD_PRIO_DBGTOOL;
  442. ret = misc_register(&goodix_tools_miscdev);
  443. if (ret)
  444. ts_err("Debug tools miscdev register failed");
  445. else
  446. ts_info("Debug tools miscdev register success");
  447. return ret;
  448. }
  449. void goodix_tools_exit(void)
  450. {
  451. misc_deregister(&goodix_tools_miscdev);
  452. kfree(goodix_tools_dev);
  453. ts_info("Debug tools miscdev exit");
  454. }