1 /*
2 *
3 * FocalTech TouchScreen driver.
4 *
5 * Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18 /*****************************************************************************
19 *
20 * File Name: Focaltech_ex_fun.c
21 *
22 * Author: Focaltech Driver Team
23 *
24 * Created: 2016-08-08
25 *
26 * Abstract:
27 *
28 * Reference:
29 *
30 *****************************************************************************/
31
32 /*****************************************************************************
33 * 1.Included header files
34 *****************************************************************************/
35 #include "focaltech_core.h"
36
37 /*****************************************************************************
38 * Private constant and macro definitions using #define
39 *****************************************************************************/
40 #define PROC_UPGRADE 0
41 #define PROC_READ_REGISTER 1
42 #define PROC_WRITE_REGISTER 2
43 #define PROC_AUTOCLB 4
44 #define PROC_UPGRADE_INFO 5
45 #define PROC_WRITE_DATA 6
46 #define PROC_READ_DATA 7
47 #define PROC_SET_TEST_FLAG 8
48 #define PROC_SET_SLAVE_ADDR 10
49 #define PROC_HW_RESET 11
50 #define PROC_READ_STATUS 12
51 #define PROC_SET_BOOT_MODE 13
52 #define PROC_ENTER_TEST_ENVIRONMENT 14
53 #define PROC_NAME "ftxxxx-debug"
54 #define PROC_BUF_SIZE 256
55
56 /*****************************************************************************
57 * Private enumerations, structures and unions using typedef
58 *****************************************************************************/
59 enum {
60 RWREG_OP_READ = 0,
61 RWREG_OP_WRITE = 1,
62 };
63
64 /*****************************************************************************
65 * Static variables
66 *****************************************************************************/
67 static struct rwreg_operation_t {
68 int type; /* 0: read, 1: write */
69 int reg; /* register */
70 int len; /* read/write length */
71 int val; /* length = 1; read: return value, write: op return */
72 int res; /* 0: success, otherwise: fail */
73 char *opbuf; /* length >= 1, read return value, write: op return */
74 } rw_op;
75
76 /*****************************************************************************
77 * Global variable or extern global variabls/functions
78 *****************************************************************************/
79
80 /*****************************************************************************
81 * Static function prototypes
82 *****************************************************************************/
83 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
fts_debug_write(struct file * filp,const char __user * buff,size_t count,loff_t * ppos)84 static ssize_t fts_debug_write(
85 struct file *filp, const char __user *buff, size_t count, loff_t *ppos)
86 {
87 u8 *writebuf = NULL;
88 u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
89 int buflen = count;
90 int writelen = 0;
91 int ret = 0;
92 char tmp[PROC_BUF_SIZE];
93 struct fts_ts_data *ts_data = fts_data;
94 struct ftxxxx_proc *proc = &ts_data->proc;
95
96 if ((buflen <= 1) || (buflen > PAGE_SIZE)) {
97 FTS_ERROR("apk proc wirte count(%d>%d) fail", buflen, (int)PAGE_SIZE);
98 return -EINVAL;
99 }
100
101 if (buflen > PROC_BUF_SIZE) {
102 writebuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
103 if (NULL == writebuf) {
104 FTS_ERROR("apk proc wirte buf zalloc fail");
105 return -ENOMEM;
106 }
107 } else {
108 writebuf = tmpbuf;
109 }
110
111 if (copy_from_user(writebuf, buff, buflen)) {
112 FTS_ERROR("[APK]: copy from user error!!");
113 ret = -EFAULT;
114 goto proc_write_err;
115 }
116
117 proc->opmode = writebuf[0];
118 switch (proc->opmode) {
119 case PROC_SET_TEST_FLAG:
120 FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x", writebuf[1]);
121 if (writebuf[1] == 0) {
122 #if FTS_ESDCHECK_EN
123 fts_esdcheck_switch(ENABLE);
124 #endif
125 } else {
126 #if FTS_ESDCHECK_EN
127 fts_esdcheck_switch(DISABLE);
128 #endif
129 }
130 break;
131
132 case PROC_READ_REGISTER:
133 proc->cmd[0] = writebuf[1];
134 break;
135
136 case PROC_WRITE_REGISTER:
137 ret = fts_write_reg(writebuf[1], writebuf[2]);
138 if (ret < 0) {
139 FTS_ERROR("PROC_WRITE_REGISTER write error");
140 goto proc_write_err;
141 }
142 break;
143
144 case PROC_READ_DATA:
145 writelen = buflen - 1;
146 if (writelen >= FTX_MAX_COMMMAND_LENGTH) {
147 FTS_ERROR("cmd(PROC_READ_DATA) length(%d) fail", writelen);
148 goto proc_write_err;
149 }
150 memcpy(proc->cmd, writebuf + 1, writelen);
151 proc->cmd_len = writelen;
152 ret = fts_write(writebuf + 1, writelen);
153 if (ret < 0) {
154 FTS_ERROR("PROC_READ_DATA write error");
155 goto proc_write_err;
156 }
157 break;
158
159 case PROC_WRITE_DATA:
160 writelen = buflen - 1;
161 ret = fts_write(writebuf + 1, writelen);
162 if (ret < 0) {
163 FTS_ERROR("PROC_WRITE_DATA write error");
164 goto proc_write_err;
165 }
166 break;
167
168 case PROC_SET_SLAVE_ADDR:
169 break;
170
171 case PROC_HW_RESET:
172 snprintf(tmp, PROC_BUF_SIZE, "%s", writebuf + 1);
173 tmp[buflen - 1] = '\0';
174 if (strncmp(tmp, "focal_driver", 12) == 0) {
175 FTS_INFO("APK execute HW Reset");
176 fts_reset_proc(0);
177 }
178 break;
179
180 case PROC_SET_BOOT_MODE:
181 FTS_DEBUG("[APK]: PROC_SET_BOOT_MODE = %x", writebuf[1]);
182 if (0 == writebuf[1]) {
183 ts_data->fw_is_running = true;
184 } else {
185 ts_data->fw_is_running = false;
186 }
187 break;
188 case PROC_ENTER_TEST_ENVIRONMENT:
189 FTS_DEBUG("[APK]: PROC_ENTER_TEST_ENVIRONMENT = %x", writebuf[1]);
190 if (0 == writebuf[1]) {
191 fts_enter_test_environment(0);
192 } else {
193 fts_enter_test_environment(1);
194 }
195 break;
196
197 default:
198 break;
199 }
200
201 ret = buflen;
202 proc_write_err:
203 if ((buflen > PROC_BUF_SIZE) && writebuf) {
204 kfree(writebuf);
205 writebuf = NULL;
206 }
207 return ret;
208 }
209
fts_debug_read(struct file * filp,char __user * buff,size_t count,loff_t * ppos)210 static ssize_t fts_debug_read(
211 struct file *filp, char __user *buff, size_t count, loff_t *ppos)
212 {
213 int ret = 0;
214 int num_read_chars = 0;
215 int buflen = count;
216 u8 *readbuf = NULL;
217 u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
218 struct fts_ts_data *ts_data = fts_data;
219 struct ftxxxx_proc *proc = &ts_data->proc;
220
221 if ((buflen <= 0) || (buflen > PAGE_SIZE)) {
222 FTS_ERROR("apk proc read count(%d>%d) fail", buflen, (int)PAGE_SIZE);
223 return -EINVAL;
224 }
225
226 if (buflen > PROC_BUF_SIZE) {
227 readbuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
228 if (NULL == readbuf) {
229 FTS_ERROR("apk proc wirte buf zalloc fail");
230 return -ENOMEM;
231 }
232 } else {
233 readbuf = tmpbuf;
234 }
235
236 #if FTS_ESDCHECK_EN
237 fts_esdcheck_proc_busy(1);
238 #endif
239
240 switch (proc->opmode) {
241 case PROC_READ_REGISTER:
242 num_read_chars = 1;
243 ret = fts_read_reg(proc->cmd[0], &readbuf[0]);
244 if (ret < 0) {
245 FTS_ERROR("PROC_READ_REGISTER read error");
246 goto proc_read_err;
247 }
248 break;
249 case PROC_WRITE_REGISTER:
250 break;
251
252 case PROC_READ_DATA:
253 num_read_chars = buflen;
254 ret = fts_read(NULL, 0, readbuf, num_read_chars);
255 if (ret < 0) {
256 FTS_ERROR("PROC_READ_DATA read error");
257 goto proc_read_err;
258 }
259 break;
260
261 case PROC_WRITE_DATA:
262 break;
263
264 default:
265 break;
266 }
267
268 #if FTS_ESDCHECK_EN
269 fts_esdcheck_proc_busy(0);
270 #endif
271
272 if (copy_to_user(buff, readbuf, num_read_chars)) {
273 FTS_ERROR("copy to user error");
274 ret = -EFAULT;
275 goto proc_read_err;
276 }
277
278 ret = num_read_chars;
279 proc_read_err:
280 if ((buflen > PROC_BUF_SIZE) && readbuf) {
281 kfree(readbuf);
282 readbuf = NULL;
283 }
284 return ret;
285 }
286
287 static const struct file_operations fts_proc_fops = {
288 .owner = THIS_MODULE,
289 .read = fts_debug_read,
290 .write = fts_debug_write,
291 };
292 #else
fts_debug_write(struct file * filp,const char __user * buff,unsigned long len,void * data)293 static int fts_debug_write(
294 struct file *filp, const char __user *buff, unsigned long len, void *data)
295 {
296 u8 *writebuf = NULL;
297 u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
298 int buflen = count;
299 int writelen = 0;
300 int ret = 0;
301 char tmp[PROC_BUF_SIZE];
302 struct fts_ts_data *ts_data = fts_data;
303 struct ftxxxx_proc *proc = &ts_data->proc;
304
305 if ((buflen <= 1) || (buflen > PAGE_SIZE)) {
306 FTS_ERROR("apk proc wirte count(%d>%d) fail", buflen, (int)PAGE_SIZE);
307 return -EINVAL;
308 }
309
310 if (buflen > PROC_BUF_SIZE) {
311 writebuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
312 if (NULL == writebuf) {
313 FTS_ERROR("apk proc wirte buf zalloc fail");
314 return -ENOMEM;
315 }
316 } else {
317 writebuf = tmpbuf;
318 }
319
320 if (copy_from_user(writebuf, buff, buflen)) {
321 FTS_ERROR("[APK]: copy from user error!!");
322 ret = -EFAULT;
323 goto proc_write_err;
324 }
325
326 proc->opmode = writebuf[0];
327 switch (proc->opmode) {
328 case PROC_SET_TEST_FLAG:
329 FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x", writebuf[1]);
330 if (writebuf[1] == 0) {
331 #if FTS_ESDCHECK_EN
332 fts_esdcheck_switch(ENABLE);
333 #endif
334 } else {
335 #if FTS_ESDCHECK_EN
336 fts_esdcheck_switch(DISABLE);
337 #endif
338 }
339 break;
340
341 case PROC_READ_REGISTER:
342 proc->cmd[0] = writebuf[1];
343 break;
344
345 case PROC_WRITE_REGISTER:
346 ret = fts_write_reg(writebuf[1], writebuf[2]);
347 if (ret < 0) {
348 FTS_ERROR("PROC_WRITE_REGISTER write error");
349 goto proc_write_err;
350 }
351 break;
352
353 case PROC_READ_DATA:
354 writelen = buflen - 1;
355 if (writelen >= FTX_MAX_COMMMAND_LENGTH) {
356 FTS_ERROR("cmd(PROC_READ_DATA) length(%d) fail", writelen);
357 goto proc_write_err;
358 }
359 memcpy(proc->cmd, writebuf + 1, writelen);
360 proc->cmd_len = writelen;
361 ret = fts_write(writebuf + 1, writelen);
362 if (ret < 0) {
363 FTS_ERROR("PROC_READ_DATA write error");
364 goto proc_write_err;
365 }
366 break;
367
368 case PROC_WRITE_DATA:
369 writelen = buflen - 1;
370 ret = fts_write(writebuf + 1, writelen);
371 if (ret < 0) {
372 FTS_ERROR("PROC_WRITE_DATA write error");
373 goto proc_write_err;
374 }
375 break;
376
377 case PROC_SET_SLAVE_ADDR:
378 break;
379
380 case PROC_HW_RESET:
381 snprintf(tmp, PROC_BUF_SIZE, "%s", writebuf + 1);
382 tmp[buflen - 1] = '\0';
383 if (strncmp(tmp, "focal_driver", 12) == 0) {
384 FTS_INFO("APK execute HW Reset");
385 fts_reset_proc(0);
386 }
387 break;
388
389 case PROC_SET_BOOT_MODE:
390 FTS_DEBUG("[APK]: PROC_SET_BOOT_MODE = %x", writebuf[1]);
391 if (0 == writebuf[1]) {
392 ts_data->fw_is_running = true;
393 } else {
394 ts_data->fw_is_running = false;
395 }
396 break;
397 case PROC_ENTER_TEST_ENVIRONMENT:
398 FTS_DEBUG("[APK]: PROC_ENTER_TEST_ENVIRONMENT = %x", writebuf[1]);
399 if (0 == writebuf[1]) {
400 fts_enter_test_environment(0);
401 } else {
402 fts_enter_test_environment(1);
403 }
404 break;
405
406 default:
407 break;
408 }
409
410 ret = buflen;
411 proc_write_err:
412 if ((buflen > PROC_BUF_SIZE) && writebuf) {
413 kfree(writebuf);
414 writebuf = NULL;
415 }
416 return ret;
417 }
418
fts_debug_read(char * page,char ** start,off_t off,int count,int * eof,void * data)419 static int fts_debug_read(
420 char *page, char **start, off_t off, int count, int *eof, void *data )
421 {
422 int ret = 0;
423 int num_read_chars = 0;
424 int buflen = count;
425 u8 *readbuf = NULL;
426 u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
427 struct fts_ts_data *ts_data = fts_data;
428 struct ftxxxx_proc *proc = &ts_data->proc;
429
430 if ((buflen <= 0) || (buflen > PAGE_SIZE)) {
431 FTS_ERROR("apk proc read count(%d>%d) fail", buflen, (int)PAGE_SIZE);
432 return -EINVAL;
433 }
434
435 if (buflen > PROC_BUF_SIZE) {
436 readbuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
437 if (NULL == readbuf) {
438 FTS_ERROR("apk proc wirte buf zalloc fail");
439 return -ENOMEM;
440 }
441 } else {
442 readbuf = tmpbuf;
443 }
444
445 #if FTS_ESDCHECK_EN
446 fts_esdcheck_proc_busy(1);
447 #endif
448
449 switch (proc->opmode) {
450 case PROC_READ_REGISTER:
451 num_read_chars = 1;
452 ret = fts_read_reg(proc->cmd[0], &readbuf[0]);
453 if (ret < 0) {
454 FTS_ERROR("PROC_READ_REGISTER read error");
455 goto proc_read_err;
456 }
457 break;
458 case PROC_WRITE_REGISTER:
459 break;
460
461 case PROC_READ_DATA:
462 num_read_chars = buflen;
463 ret = fts_read(NULL, 0, readbuf, num_read_chars);
464 if (ret < 0) {
465 FTS_ERROR("PROC_READ_DATA read error");
466 goto proc_read_err;
467 }
468 break;
469
470 case PROC_WRITE_DATA:
471 break;
472
473 default:
474 break;
475 }
476
477 #if FTS_ESDCHECK_EN
478 fts_esdcheck_proc_busy(0);
479 #endif
480
481 if (copy_to_user(buff, readbuf, num_read_chars)) {
482 FTS_ERROR("copy to user error");
483 ret = -EFAULT;
484 goto proc_read_err;
485 }
486
487 ret = num_read_chars;
488 proc_read_err:
489 if ((buflen > PROC_BUF_SIZE) && readbuf) {
490 kfree(readbuf);
491 readbuf = NULL;
492 }
493 return ret;
494 }
495 #endif
496
fts_create_apk_debug_channel(struct fts_ts_data * ts_data)497 int fts_create_apk_debug_channel(struct fts_ts_data *ts_data)
498 {
499 struct ftxxxx_proc *proc = &ts_data->proc;
500 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
501 proc->proc_entry = proc_create(PROC_NAME, 0777, NULL, &fts_proc_fops);
502 if (NULL == proc->proc_entry) {
503 FTS_ERROR("create proc entry fail");
504 return -ENOMEM;
505 }
506 #else
507 proc->proc_entry = create_proc_entry(PROC_NAME, 0777, NULL);
508 if (NULL == proc->proc_entry) {
509 FTS_ERROR("create proc entry fail");
510 return -ENOMEM;
511 }
512 proc->proc_entry->write_proc = fts_debug_write;
513 proc->proc_entry->read_proc = fts_debug_read;
514 #endif
515
516 FTS_INFO("Create proc entry success!");
517 return 0;
518 }
519
fts_release_apk_debug_channel(struct fts_ts_data * ts_data)520 void fts_release_apk_debug_channel(struct fts_ts_data *ts_data)
521 {
522 struct ftxxxx_proc *proc = &ts_data->proc;
523
524 if (proc->proc_entry) {
525 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
526 proc_remove(proc->proc_entry);
527 #else
528 remove_proc_entry(PROC_NAME, NULL);
529 #endif
530 }
531 }
532
533 /************************************************************************
534 * sysfs interface
535 ***********************************************************************/
536 /* fts_hw_reset interface */
fts_hw_reset_show(struct device * dev,struct device_attribute * attr,char * buf)537 static ssize_t fts_hw_reset_show(
538 struct device *dev, struct device_attribute *attr, char *buf)
539 {
540 struct input_dev *input_dev = fts_data->input_dev;
541 ssize_t count = 0;
542
543 mutex_lock(&input_dev->mutex);
544 fts_reset_proc(0);
545 count = snprintf(buf, PAGE_SIZE, "hw reset executed\n");
546 mutex_unlock(&input_dev->mutex);
547
548 return count;
549 }
550
fts_hw_reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)551 static ssize_t fts_hw_reset_store(
552 struct device *dev,
553 struct device_attribute *attr, const char *buf, size_t count)
554 {
555 return -EPERM;
556 }
557
558 /* fts_irq interface */
fts_irq_show(struct device * dev,struct device_attribute * attr,char * buf)559 static ssize_t fts_irq_show(
560 struct device *dev, struct device_attribute *attr, char *buf)
561 {
562 ssize_t count = 0;
563 struct irq_desc *desc = irq_to_desc(fts_data->irq);
564
565 count = snprintf(buf, PAGE_SIZE, "irq_depth:%d\n", desc->depth);
566
567 return count;
568 }
569
fts_irq_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)570 static ssize_t fts_irq_store(
571 struct device *dev,
572 struct device_attribute *attr, const char *buf, size_t count)
573 {
574 struct input_dev *input_dev = fts_data->input_dev;
575
576 mutex_lock(&input_dev->mutex);
577 if (FTS_SYSFS_ECHO_ON(buf)) {
578 FTS_INFO("enable irq");
579 fts_irq_enable();
580 } else if (FTS_SYSFS_ECHO_OFF(buf)) {
581 FTS_INFO("disable irq");
582 fts_irq_disable();
583 }
584 mutex_unlock(&input_dev->mutex);
585 return count;
586 }
587
588 /* fts_boot_mode interface */
fts_bootmode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)589 static ssize_t fts_bootmode_store(
590 struct device *dev,
591 struct device_attribute *attr, const char *buf, size_t count)
592 {
593 struct input_dev *input_dev = fts_data->input_dev;
594
595 FTS_FUNC_ENTER();
596 mutex_lock(&input_dev->mutex);
597 if (FTS_SYSFS_ECHO_ON(buf)) {
598 FTS_INFO("[EX-FUN]set to boot mode");
599 fts_data->fw_is_running = false;
600 } else if (FTS_SYSFS_ECHO_OFF(buf)) {
601 FTS_INFO("[EX-FUN]set to fw mode");
602 fts_data->fw_is_running = true;
603 }
604 mutex_unlock(&input_dev->mutex);
605 FTS_FUNC_EXIT();
606
607 return count;
608 }
609
fts_bootmode_show(struct device * dev,struct device_attribute * attr,char * buf)610 static ssize_t fts_bootmode_show(
611 struct device *dev, struct device_attribute *attr, char *buf)
612 {
613 ssize_t count = 0;
614 struct input_dev *input_dev = fts_data->input_dev;
615
616 FTS_FUNC_ENTER();
617 mutex_lock(&input_dev->mutex);
618 if (true == fts_data->fw_is_running) {
619 count = snprintf(buf, PAGE_SIZE, "tp is in fw mode\n");
620 } else {
621 count = snprintf(buf, PAGE_SIZE, "tp is in boot mode\n");
622 }
623 mutex_unlock(&input_dev->mutex);
624 FTS_FUNC_EXIT();
625
626 return count;
627 }
628
629 /* fts_tpfwver interface */
fts_tpfwver_show(struct device * dev,struct device_attribute * attr,char * buf)630 static ssize_t fts_tpfwver_show(
631 struct device *dev, struct device_attribute *attr, char *buf)
632 {
633 struct fts_ts_data *ts_data = fts_data;
634 struct input_dev *input_dev = ts_data->input_dev;
635 ssize_t num_read_chars = 0;
636 u8 fwver = 0;
637
638 mutex_lock(&input_dev->mutex);
639
640 #if FTS_ESDCHECK_EN
641 fts_esdcheck_proc_busy(1);
642 #endif
643 fts_read_reg(FTS_REG_FW_VER, &fwver);
644 #if FTS_ESDCHECK_EN
645 fts_esdcheck_proc_busy(0);
646 #endif
647 if ((fwver == 0xFF) || (fwver == 0x00))
648 num_read_chars = snprintf(buf, PAGE_SIZE, "get tp fw version fail!\n");
649 else
650 num_read_chars = snprintf(buf, PAGE_SIZE, "%02x\n", fwver);
651
652 mutex_unlock(&input_dev->mutex);
653 return num_read_chars;
654 }
655
fts_tpfwver_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)656 static ssize_t fts_tpfwver_store(
657 struct device *dev,
658 struct device_attribute *attr, const char *buf, size_t count)
659 {
660 return -EPERM;
661 }
662
663 /* fts_rw_reg */
fts_tprwreg_show(struct device * dev,struct device_attribute * attr,char * buf)664 static ssize_t fts_tprwreg_show(
665 struct device *dev, struct device_attribute *attr, char *buf)
666 {
667 int count;
668 int i;
669 struct input_dev *input_dev = fts_data->input_dev;
670
671 mutex_lock(&input_dev->mutex);
672
673 if (rw_op.len < 0) {
674 count = snprintf(buf, PAGE_SIZE, "Invalid cmd line\n");
675 } else if (rw_op.len == 1) {
676 if (RWREG_OP_READ == rw_op.type) {
677 if (rw_op.res == 0) {
678 count = snprintf(buf, PAGE_SIZE, "Read %02X: %02X\n", rw_op.reg, rw_op.val);
679 } else {
680 count = snprintf(buf, PAGE_SIZE, "Read %02X failed, ret: %d\n", rw_op.reg, rw_op.res);
681 }
682 } else {
683 if (rw_op.res == 0) {
684 count = snprintf(buf, PAGE_SIZE, "Write %02X, %02X success\n", rw_op.reg, rw_op.val);
685 } else {
686 count = snprintf(buf, PAGE_SIZE, "Write %02X failed, ret: %d\n", rw_op.reg, rw_op.res);
687 }
688 }
689 } else {
690 if (RWREG_OP_READ == rw_op.type) {
691 count = snprintf(buf, PAGE_SIZE, "Read Reg: [%02X]-[%02X]\n", rw_op.reg, rw_op.reg + rw_op.len);
692 count += snprintf(buf + count, PAGE_SIZE, "Result: ");
693 if (rw_op.res) {
694 count += snprintf(buf + count, PAGE_SIZE, "failed, ret: %d\n", rw_op.res);
695 } else {
696 if (rw_op.opbuf) {
697 for (i = 0; i < rw_op.len; i++) {
698 count += snprintf(buf + count, PAGE_SIZE, "%02X ", rw_op.opbuf[i]);
699 }
700 count += snprintf(buf + count, PAGE_SIZE, "\n");
701 }
702 }
703 } else {
704 ;
705 count = snprintf(buf, PAGE_SIZE, "Write Reg: [%02X]-[%02X]\n", rw_op.reg, rw_op.reg + rw_op.len - 1);
706 count += snprintf(buf + count, PAGE_SIZE, "Write Data: ");
707 if (rw_op.opbuf) {
708 for (i = 1; i < rw_op.len; i++) {
709 count += snprintf(buf + count, PAGE_SIZE, "%02X ", rw_op.opbuf[i]);
710 }
711 count += snprintf(buf + count, PAGE_SIZE, "\n");
712 }
713 if (rw_op.res) {
714 count += snprintf(buf + count, PAGE_SIZE, "Result: failed, ret: %d\n", rw_op.res);
715 } else {
716 count += snprintf(buf + count, PAGE_SIZE, "Result: success\n");
717 }
718 }
719 /*if (rw_op.opbuf) {
720 kfree(rw_op.opbuf);
721 rw_op.opbuf = NULL;
722 }*/
723 }
724 mutex_unlock(&input_dev->mutex);
725
726 return count;
727 }
728
shex_to_int(const char * hex_buf,int size)729 static int shex_to_int(const char *hex_buf, int size)
730 {
731 int i;
732 int base = 1;
733 int value = 0;
734 char single;
735
736 for (i = size - 1; i >= 0; i--) {
737 single = hex_buf[i];
738
739 if ((single >= '0') && (single <= '9')) {
740 value += (single - '0') * base;
741 } else if ((single >= 'a') && (single <= 'z')) {
742 value += (single - 'a' + 10) * base;
743 } else if ((single >= 'A') && (single <= 'Z')) {
744 value += (single - 'A' + 10) * base;
745 } else {
746 return -EINVAL;
747 }
748
749 base *= 16;
750 }
751
752 return value;
753 }
754
755
shex_to_u8(const char * hex_buf,int size)756 static u8 shex_to_u8(const char *hex_buf, int size)
757 {
758 return (u8)shex_to_int(hex_buf, size);
759 }
760 /*
761 * Format buf:
762 * [0]: '0' write, '1' read(reserved)
763 * [1-2]: addr, hex
764 * [3-4]: length, hex
765 * [5-6]...[n-(n+1)]: data, hex
766 */
fts_parse_buf(const char * buf,size_t cmd_len)767 static int fts_parse_buf(const char *buf, size_t cmd_len)
768 {
769 int length;
770 int i;
771 char *tmpbuf;
772
773 rw_op.reg = shex_to_u8(buf + 1, 2);
774 length = shex_to_int(buf + 3, 2);
775
776 if (buf[0] == '1') {
777 rw_op.len = length;
778 rw_op.type = RWREG_OP_READ;
779 FTS_DEBUG("read %02X, %d bytes", rw_op.reg, rw_op.len);
780 } else {
781 if (cmd_len < (length * 2 + 5)) {
782 pr_err("data invalided!\n");
783 return -EINVAL;
784 }
785 FTS_DEBUG("write %02X, %d bytes", rw_op.reg, length);
786
787 /* first byte is the register addr */
788 rw_op.type = RWREG_OP_WRITE;
789 rw_op.len = length + 1;
790 }
791
792 if (rw_op.len > 0) {
793 tmpbuf = (char *)kzalloc(rw_op.len, GFP_KERNEL);
794 if (!tmpbuf) {
795 FTS_ERROR("allocate memory failed!\n");
796 return -ENOMEM;
797 }
798
799 if (RWREG_OP_WRITE == rw_op.type) {
800 tmpbuf[0] = rw_op.reg & 0xFF;
801 FTS_DEBUG("write buffer: ");
802 for (i = 1; i < rw_op.len; i++) {
803 tmpbuf[i] = shex_to_u8(buf + 5 + i * 2 - 2, 2);
804 FTS_DEBUG("buf[%d]: %02X", i, tmpbuf[i] & 0xFF);
805 }
806 }
807 rw_op.opbuf = tmpbuf;
808 }
809
810 return rw_op.len;
811 }
812
fts_tprwreg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)813 static ssize_t fts_tprwreg_store(
814 struct device *dev,
815 struct device_attribute *attr, const char *buf, size_t count)
816 {
817 struct input_dev *input_dev = fts_data->input_dev;
818 ssize_t cmd_length = 0;
819
820 mutex_lock(&input_dev->mutex);
821 cmd_length = count - 1;
822
823 if (rw_op.opbuf) {
824 kfree(rw_op.opbuf);
825 rw_op.opbuf = NULL;
826 }
827
828 FTS_DEBUG("cmd len: %d, buf: %s", (int)cmd_length, buf);
829 /* compatible old ops */
830 if (2 == cmd_length) {
831 rw_op.type = RWREG_OP_READ;
832 rw_op.len = 1;
833 rw_op.reg = shex_to_int(buf, 2);
834 } else if (4 == cmd_length) {
835 rw_op.type = RWREG_OP_WRITE;
836 rw_op.len = 1;
837 rw_op.reg = shex_to_int(buf, 2);
838 rw_op.val = shex_to_int(buf + 2, 2);
839 } else if (cmd_length < 5) {
840 FTS_ERROR("Invalid cmd buffer");
841 mutex_unlock(&input_dev->mutex);
842 return -EINVAL;
843 } else {
844 rw_op.len = fts_parse_buf(buf, cmd_length);
845 }
846
847 #if FTS_ESDCHECK_EN
848 fts_esdcheck_proc_busy(1);
849 #endif
850 if (rw_op.len < 0) {
851 FTS_ERROR("cmd buffer error!");
852
853 } else {
854 if (RWREG_OP_READ == rw_op.type) {
855 if (rw_op.len == 1) {
856 u8 reg, val;
857 reg = rw_op.reg & 0xFF;
858 rw_op.res = fts_read_reg(reg, &val);
859 rw_op.val = val;
860 } else {
861 char reg;
862 reg = rw_op.reg & 0xFF;
863
864 rw_op.res = fts_read(®, 1, rw_op.opbuf, rw_op.len);
865 }
866
867 if (rw_op.res < 0) {
868 FTS_ERROR("Could not read 0x%02x", rw_op.reg);
869 } else {
870 FTS_INFO("read 0x%02x, %d bytes successful", rw_op.reg, rw_op.len);
871 rw_op.res = 0;
872 }
873
874 } else {
875 if (rw_op.len == 1) {
876 u8 reg, val;
877 reg = rw_op.reg & 0xFF;
878 val = rw_op.val & 0xFF;
879 rw_op.res = fts_write_reg(reg, val);
880 } else {
881 rw_op.res = fts_write(rw_op.opbuf, rw_op.len);
882 }
883 if (rw_op.res < 0) {
884 FTS_ERROR("Could not write 0x%02x", rw_op.reg);
885
886 } else {
887 FTS_INFO("Write 0x%02x, %d bytes successful", rw_op.val, rw_op.len);
888 rw_op.res = 0;
889 }
890 }
891 }
892
893 #if FTS_ESDCHECK_EN
894 fts_esdcheck_proc_busy(0);
895 #endif
896 mutex_unlock(&input_dev->mutex);
897
898 return count;
899 }
900
901 /* fts_upgrade_bin interface */
fts_fwupgradebin_show(struct device * dev,struct device_attribute * attr,char * buf)902 static ssize_t fts_fwupgradebin_show(
903 struct device *dev, struct device_attribute *attr, char *buf)
904 {
905 return -EPERM;
906 }
907
fts_fwupgradebin_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)908 static ssize_t fts_fwupgradebin_store(
909 struct device *dev,
910 struct device_attribute *attr, const char *buf, size_t count)
911 {
912 char fwname[FILE_NAME_LENGTH] = { 0 };
913 struct input_dev *input_dev = fts_data->input_dev;
914
915 if ((count <= 1) || (count >= FILE_NAME_LENGTH - 32)) {
916 FTS_ERROR("fw bin name's length(%d) fail", (int)count);
917 return -EINVAL;
918 }
919 memset(fwname, 0, sizeof(fwname));
920 snprintf(fwname, FILE_NAME_LENGTH, "%s", buf);
921 fwname[count - 1] = '\0';
922
923 FTS_INFO("upgrade with bin file through sysfs node");
924 mutex_lock(&input_dev->mutex);
925 fts_upgrade_bin(fwname, 0);
926 mutex_unlock(&input_dev->mutex);
927
928 return count;
929 }
930
931 /* fts_force_upgrade interface */
fts_fwforceupg_show(struct device * dev,struct device_attribute * attr,char * buf)932 static ssize_t fts_fwforceupg_show(
933 struct device *dev, struct device_attribute *attr, char *buf)
934 {
935 return -EPERM;
936 }
937
fts_fwforceupg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)938 static ssize_t fts_fwforceupg_store(
939 struct device *dev,
940 struct device_attribute *attr, const char *buf, size_t count)
941 {
942 char fwname[FILE_NAME_LENGTH];
943 struct input_dev *input_dev = fts_data->input_dev;
944
945 if ((count <= 1) || (count >= FILE_NAME_LENGTH - 32)) {
946 FTS_ERROR("fw bin name's length(%d) fail", (int)count);
947 return -EINVAL;
948 }
949 memset(fwname, 0, sizeof(fwname));
950 snprintf(fwname, FILE_NAME_LENGTH, "%s", buf);
951 fwname[count - 1] = '\0';
952
953 FTS_INFO("force upgrade through sysfs node");
954 mutex_lock(&input_dev->mutex);
955 fts_upgrade_bin(fwname, 1);
956 mutex_unlock(&input_dev->mutex);
957
958 return count;
959 }
960
961 /* fts_driver_info interface */
fts_driverinfo_show(struct device * dev,struct device_attribute * attr,char * buf)962 static ssize_t fts_driverinfo_show(
963 struct device *dev, struct device_attribute *attr, char *buf)
964 {
965 int count = 0;
966 struct fts_ts_data *ts_data = fts_data;
967 struct fts_ts_platform_data *pdata = ts_data->pdata;
968 struct input_dev *input_dev = ts_data->input_dev;
969
970 mutex_lock(&input_dev->mutex);
971 count += snprintf(buf + count, PAGE_SIZE, "Driver Ver:%s\n", FTS_DRIVER_VERSION);
972
973 count += snprintf(buf + count, PAGE_SIZE, "Resolution:(%d,%d)~(%d,%d)\n",
974 pdata->x_min, pdata->y_min, pdata->x_max, pdata->y_max);
975
976 count += snprintf(buf + count, PAGE_SIZE, "Max Touchs:%d\n", pdata->max_touch_number);
977
978 count += snprintf(buf + count, PAGE_SIZE, "reset gpio:%d,int gpio:%d,irq:%d\n",
979 pdata->reset_gpio, pdata->irq_gpio, ts_data->irq);
980
981 count += snprintf(buf + count, PAGE_SIZE, "IC ID:0x%02x%02x\n",
982 ts_data->ic_info.ids.chip_idh, ts_data->ic_info.ids.chip_idl);
983 mutex_unlock(&input_dev->mutex);
984
985 return count;
986 }
987
fts_driverinfo_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)988 static ssize_t fts_driverinfo_store(struct device *dev,
989 struct device_attribute *attr, const char *buf, size_t count)
990 {
991 return -EPERM;
992 }
993
994 /* fts_dump_reg interface */
fts_dumpreg_show(struct device * dev,struct device_attribute * attr,char * buf)995 static ssize_t fts_dumpreg_show(
996 struct device *dev, struct device_attribute *attr, char *buf)
997 {
998 int count = 0;
999 u8 val = 0;
1000 struct input_dev *input_dev = fts_data->input_dev;
1001
1002 mutex_lock(&input_dev->mutex);
1003 #if FTS_ESDCHECK_EN
1004 fts_esdcheck_proc_busy(1);
1005 #endif
1006 fts_read_reg(FTS_REG_POWER_MODE, &val);
1007 count += snprintf(buf + count, PAGE_SIZE, "Power Mode:0x%02x\n", val);
1008
1009 fts_read_reg(FTS_REG_FW_VER, &val);
1010 count += snprintf(buf + count, PAGE_SIZE, "FW Ver:0x%02x\n", val);
1011
1012 fts_read_reg(FTS_REG_LIC_VER, &val);
1013 count += snprintf(buf + count, PAGE_SIZE, "LCD Initcode Ver:0x%02x\n", val);
1014
1015 fts_read_reg(FTS_REG_IDE_PARA_VER_ID, &val);
1016 count += snprintf(buf + count, PAGE_SIZE, "Param Ver:0x%02x\n", val);
1017
1018 fts_read_reg(FTS_REG_IDE_PARA_STATUS, &val);
1019 count += snprintf(buf + count, PAGE_SIZE, "Param status:0x%02x\n", val);
1020
1021 fts_read_reg(FTS_REG_VENDOR_ID, &val);
1022 count += snprintf(buf + count, PAGE_SIZE, "Vendor ID:0x%02x\n", val);
1023
1024 fts_read_reg(FTS_REG_LCD_BUSY_NUM, &val);
1025 count += snprintf(buf + count, PAGE_SIZE, "LCD Busy Number:0x%02x\n", val);
1026
1027 fts_read_reg(FTS_REG_GESTURE_EN, &val);
1028 count += snprintf(buf + count, PAGE_SIZE, "Gesture Mode:0x%02x\n", val);
1029
1030 fts_read_reg(FTS_REG_CHARGER_MODE_EN, &val);
1031 count += snprintf(buf + count, PAGE_SIZE, "charge stat:0x%02x\n", val);
1032
1033 fts_read_reg(FTS_REG_INT_CNT, &val);
1034 count += snprintf(buf + count, PAGE_SIZE, "INT count:0x%02x\n", val);
1035
1036 fts_read_reg(FTS_REG_FLOW_WORK_CNT, &val);
1037 count += snprintf(buf + count, PAGE_SIZE, "ESD count:0x%02x\n", val);
1038 #if FTS_ESDCHECK_EN
1039 fts_esdcheck_proc_busy(0);
1040 #endif
1041
1042 mutex_unlock(&input_dev->mutex);
1043
1044 return count;
1045 }
1046
fts_dumpreg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1047 static ssize_t fts_dumpreg_store(
1048 struct device *dev,
1049 struct device_attribute *attr, const char *buf, size_t count)
1050 {
1051 return -EPERM;
1052 }
1053
1054 /* fts_dump_reg interface */
fts_tpbuf_show(struct device * dev,struct device_attribute * attr,char * buf)1055 static ssize_t fts_tpbuf_show(
1056 struct device *dev, struct device_attribute *attr, char *buf)
1057 {
1058 int count = 0;
1059 int i = 0;
1060 struct input_dev *input_dev = fts_data->input_dev;
1061
1062 mutex_lock(&input_dev->mutex);
1063 count += snprintf(buf + count, PAGE_SIZE, "touch point buffer:\n");
1064 for (i = 0; i < fts_data->pnt_buf_size; i++) {
1065 count += snprintf(buf + count, PAGE_SIZE, "%02x ", fts_data->point_buf[i]);
1066 }
1067 count += snprintf(buf + count, PAGE_SIZE, "\n");
1068 mutex_unlock(&input_dev->mutex);
1069
1070 return count;
1071 }
1072
fts_tpbuf_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1073 static ssize_t fts_tpbuf_store(
1074 struct device *dev,
1075 struct device_attribute *attr, const char *buf, size_t count)
1076 {
1077 return -EPERM;
1078 }
1079
1080 /* fts_log_level interface */
fts_log_level_show(struct device * dev,struct device_attribute * attr,char * buf)1081 static ssize_t fts_log_level_show(
1082 struct device *dev, struct device_attribute *attr, char *buf)
1083 {
1084 int count = 0;
1085 struct input_dev *input_dev = fts_data->input_dev;
1086
1087 mutex_lock(&input_dev->mutex);
1088 count += snprintf(buf + count, PAGE_SIZE, "log level:%d\n",
1089 fts_data->log_level);
1090 mutex_unlock(&input_dev->mutex);
1091
1092 return count;
1093 }
1094
fts_log_level_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1095 static ssize_t fts_log_level_store(
1096 struct device *dev,
1097 struct device_attribute *attr, const char *buf, size_t count)
1098 {
1099 int value = 0;
1100 struct input_dev *input_dev = fts_data->input_dev;
1101
1102 FTS_FUNC_ENTER();
1103 mutex_lock(&input_dev->mutex);
1104 sscanf(buf, "%d", &value);
1105 FTS_DEBUG("log level:%d->%d", fts_data->log_level, value);
1106 fts_data->log_level = value;
1107 mutex_unlock(&input_dev->mutex);
1108 FTS_FUNC_EXIT();
1109
1110 return count;
1111 }
1112
1113 /* get the fw version example:cat fw_version */
1114 static DEVICE_ATTR(fts_fw_version, S_IRUGO | S_IWUSR, fts_tpfwver_show, fts_tpfwver_store);
1115
1116 /* read and write register(s)
1117 * All data type is **HEX**
1118 * Single Byte:
1119 * read: echo 88 > rw_reg ---read register 0x88
1120 * write: echo 8807 > rw_reg ---write 0x07 into register 0x88
1121 * Multi-bytes:
1122 * [0:rw-flag][1-2: reg addr, hex][3-4: length, hex][5-6...n-n+1: write data, hex]
1123 * rw-flag: 0, write; 1, read
1124 * read: echo 10005 > rw_reg ---read reg 0x00-0x05
1125 * write: echo 000050102030405 > rw_reg ---write reg 0x00-0x05 as 01,02,03,04,05
1126 * Get result:
1127 * cat rw_reg
1128 */
1129 static DEVICE_ATTR(fts_rw_reg, S_IRUGO | S_IWUSR, fts_tprwreg_show, fts_tprwreg_store);
1130 /* upgrade from fw bin file example:echo "*.bin" > fts_upgrade_bin */
1131 static DEVICE_ATTR(fts_upgrade_bin, S_IRUGO | S_IWUSR, fts_fwupgradebin_show, fts_fwupgradebin_store);
1132 static DEVICE_ATTR(fts_force_upgrade, S_IRUGO | S_IWUSR, fts_fwforceupg_show, fts_fwforceupg_store);
1133 static DEVICE_ATTR(fts_driver_info, S_IRUGO | S_IWUSR, fts_driverinfo_show, fts_driverinfo_store);
1134 static DEVICE_ATTR(fts_dump_reg, S_IRUGO | S_IWUSR, fts_dumpreg_show, fts_dumpreg_store);
1135 static DEVICE_ATTR(fts_hw_reset, S_IRUGO | S_IWUSR, fts_hw_reset_show, fts_hw_reset_store);
1136 static DEVICE_ATTR(fts_irq, S_IRUGO | S_IWUSR, fts_irq_show, fts_irq_store);
1137 static DEVICE_ATTR(fts_boot_mode, S_IRUGO | S_IWUSR, fts_bootmode_show, fts_bootmode_store);
1138 static DEVICE_ATTR(fts_touch_point, S_IRUGO | S_IWUSR, fts_tpbuf_show, fts_tpbuf_store);
1139 static DEVICE_ATTR(fts_log_level, S_IRUGO | S_IWUSR, fts_log_level_show, fts_log_level_store);
1140
1141 /* add your attr in here*/
1142 static struct attribute *fts_attributes[] = {
1143 &dev_attr_fts_fw_version.attr,
1144 &dev_attr_fts_rw_reg.attr,
1145 &dev_attr_fts_dump_reg.attr,
1146 &dev_attr_fts_upgrade_bin.attr,
1147 &dev_attr_fts_force_upgrade.attr,
1148 &dev_attr_fts_driver_info.attr,
1149 &dev_attr_fts_hw_reset.attr,
1150 &dev_attr_fts_irq.attr,
1151 &dev_attr_fts_boot_mode.attr,
1152 &dev_attr_fts_touch_point.attr,
1153 &dev_attr_fts_log_level.attr,
1154 NULL
1155 };
1156
1157 static struct attribute_group fts_attribute_group = {
1158 .attrs = fts_attributes
1159 };
1160
fts_create_sysfs(struct fts_ts_data * ts_data)1161 int fts_create_sysfs(struct fts_ts_data *ts_data)
1162 {
1163 int ret = 0;
1164
1165 ret = sysfs_create_group(&ts_data->dev->kobj, &fts_attribute_group);
1166 if (ret) {
1167 FTS_ERROR("[EX]: sysfs_create_group() failed!!");
1168 sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
1169 return -ENOMEM;
1170 } else {
1171 FTS_INFO("[EX]: sysfs_create_group() succeeded!!");
1172 }
1173
1174 return ret;
1175 }
1176
fts_remove_sysfs(struct fts_ts_data * ts_data)1177 int fts_remove_sysfs(struct fts_ts_data *ts_data)
1178 {
1179 sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
1180 return 0;
1181 }
1182