xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/gt1x/gt1x_tools.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* drivers/input/touchscreen/goodix_tool.c
2  *
3  * 2010 - 2014 Goodix Technology.
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  * Version: 1.4
17  * Release Date:  2015/07/10
18  */
19 
20 #include <linux/delay.h>
21 #include <linux/uaccess.h>
22 #include <linux/proc_fs.h>
23 #include <generated/utsrelease.h>
24 #include "gt1x_generic.h"
25 
26 static ssize_t gt1x_tool_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos);
27 static ssize_t gt1x_tool_write(struct file *filp, const char *buffer, size_t count, loff_t *ppos);
28 
29 
30 static int gt1x_tool_release(struct inode *inode, struct file *filp);
31 static int gt1x_tool_open(struct inode *inode, struct file *file);
32 
33 #pragma pack(1)
34 typedef struct {
35 	u8 wr;
36 	u8 flag;
37 	u8 flag_addr[2];
38 	u8 flag_val;
39 	u8 flag_relation;
40 	u16 circle;
41 	u8 times;
42 	u8 retry;
43 	u16 delay;
44 	u16 data_len;
45 	u8 addr_len;
46 	u8 addr[2];
47 	u8 res[3];
48 	u8 *data;
49 } st_cmd_head;
50 #pragma pack()
51 st_cmd_head cmd_head;
52 
53 s32 DATA_LENGTH;
54 s8 IC_TYPE[16] = "GT1X";
55 
56 #define UPDATE_FUNCTIONS
57 #define DATA_LENGTH_UINT    512
58 #define CMD_HEAD_LENGTH     (sizeof(st_cmd_head) - sizeof(u8 *))
59 
60 static char procname[20] = { 0 };
61 
62 static struct proc_dir_entry *gt1x_tool_proc_entry;
63 static const struct proc_ops gt1x_tool_fops = {
64 	.proc_read = gt1x_tool_read,
65 	.proc_write = gt1x_tool_write,
66 	.proc_open = gt1x_tool_open,
67 	.proc_release = gt1x_tool_release,
68 };
69 
set_tool_node_name(char * procname)70 static void set_tool_node_name(char *procname)
71 {
72 
73 	int v0 = 0, v1 = 0, v2 = 0;
74 
75 	sscanf(UTS_RELEASE, "%d.%d.%d", &v0, &v1, &v2);
76 	sprintf(procname, "gmnode%02d%02d%02d", v0, v1, v2);
77 }
78 
gt1x_init_tool_node(void)79 int gt1x_init_tool_node(void)
80 {
81 	memset(&cmd_head, 0, sizeof(cmd_head));
82 	/*if the first operation is read, will return fail.*/
83 	cmd_head.wr = 1;
84 	cmd_head.data = kzalloc(DATA_LENGTH_UINT, GFP_KERNEL);
85 	if (NULL == cmd_head.data) {
86 		GTP_ERROR("Apply for memory failed.");
87 		return -1;
88 	}
89 	GTP_INFO("Alloc memory size:%d.", DATA_LENGTH_UINT);
90 	DATA_LENGTH = DATA_LENGTH_UINT - GTP_ADDR_LENGTH;
91 
92 	set_tool_node_name(procname);
93 
94 	gt1x_tool_proc_entry = proc_create(procname, 0755, NULL, &gt1x_tool_fops);
95 	if (gt1x_tool_proc_entry == NULL) {
96 		GTP_ERROR("CAN't create proc entry /proc/%s.", procname);
97 		return -1;
98 	} else {
99 		GTP_INFO("Created proc entry /proc/%s.", procname);
100 	}
101 	return 0;
102 }
103 
gt1x_deinit_tool_node(void)104 void gt1x_deinit_tool_node(void)
105 {
106 	remove_proc_entry(procname, NULL);
107 	kfree(cmd_head.data);
108 	cmd_head.data = NULL;
109 }
110 
tool_i2c_read(u8 * buf,u16 len)111 static s32 tool_i2c_read(u8 *buf, u16 len)
112 {
113 	u16 addr = (buf[0] << 8) + buf[1];
114 	if (!gt1x_i2c_read(addr, &buf[2], len)) {
115 		return 1;
116 	}
117 	return -1;
118 }
119 
tool_i2c_write(u8 * buf,u16 len)120 static s32 tool_i2c_write(u8 *buf, u16 len)
121 {
122 	u16 addr = (buf[0] << 8) + buf[1];
123 	if (!gt1x_i2c_write(addr, &buf[2], len - 2)) {
124 		return 1;
125 	}
126 	return -1;
127 }
128 
relation(u8 src,u8 dst,u8 rlt)129 static u8 relation(u8 src, u8 dst, u8 rlt)
130 {
131 	u8 ret = 0;
132 
133 	switch (rlt) {
134 	case 0:
135 		ret = (src != dst) ? true : false;
136 		break;
137 
138 	case 1:
139 		ret = (src == dst) ? true : false;
140 		GTP_DEBUG("equal:src:0x%02x   dst:0x%02x   ret:%d.", src, dst, (s32) ret);
141 		break;
142 
143 	case 2:
144 		ret = (src > dst) ? true : false;
145 		break;
146 
147 	case 3:
148 		ret = (src < dst) ? true : false;
149 		break;
150 
151 	case 4:
152 		ret = (src & dst) ? true : false;
153 		break;
154 
155 	case 5:
156 		ret = (!(src | dst)) ? true : false;
157 		break;
158 
159 	default:
160 		ret = false;
161 		break;
162 	}
163 
164 	return ret;
165 }
166 
167 /*******************************************************
168 Function:
169     Comfirm function.
170 Input:
171   None.
172 Output:
173     Return write length.
174 ********************************************************/
comfirm(void)175 static u8 comfirm(void)
176 {
177 	s32 i = 0;
178 	u8 buf[32];
179 
180 	memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
181 
182 	for (i = 0; i < cmd_head.times; i++) {
183 		if (tool_i2c_read(buf, 1) <= 0) {
184 			GTP_ERROR("Read flag data failed!");
185 			return -1;
186 		}
187 
188 		if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, cmd_head.flag_relation)) {
189 			GTP_DEBUG("value at flag addr:0x%02x.", buf[GTP_ADDR_LENGTH]);
190 			GTP_DEBUG("flag value:0x%02x.", cmd_head.flag_val);
191 			break;
192 		}
193 
194 		msleep(cmd_head.circle);
195 	}
196 
197 	if (i >= cmd_head.times) {
198 		GTP_ERROR("Didn't get the flag to continue!");
199 		return -1;
200 	}
201 
202 	return 0;
203 }
204 
205 /*******************************************************
206 Function:
207     Goodix tool write function.
208 Input:
209   standard proc write function param.
210 Output:
211     Return write length.
212 ********************************************************/
gt1x_tool_write(struct file * filp,const char __user * buff,size_t len,loff_t * data)213 static ssize_t gt1x_tool_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
214 {
215 	u64 ret = 0;
216 	GTP_DEBUG_FUNC();
217 	GTP_DEBUG_ARRAY((u8 *) buff, len);
218 
219 	ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
220 	if (ret) {
221 		GTP_ERROR("copy_from_user failed.");
222 	}
223 
224 	GTP_DEBUG("wr  :0x%02x.", cmd_head.wr);
225 	/*
226 	   GTP_DEBUG("flag:0x%02x.", cmd_head.flag);
227 	   GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0], cmd_head.flag_addr[1]);
228 	   GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val);
229 	   GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation);
230 	   GTP_DEBUG("circle  :%d.", (s32)cmd_head.circle);
231 	   GTP_DEBUG("times   :%d.", (s32)cmd_head.times);
232 	   GTP_DEBUG("retry   :%d.", (s32)cmd_head.retry);
233 	   GTP_DEBUG("delay   :%d.", (s32)cmd_head.delay);
234 	   GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len);
235 	   GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len);
236 	   GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]);
237 	   GTP_DEBUG("len:%d.", (s32)len);
238 	   GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]);
239 	   */
240 
241 	if (1 == cmd_head.wr) {
242 		u16 addr, data_len, pos;
243 
244 		if (1 == cmd_head.flag) {
245 			if (comfirm()) {
246 				GTP_ERROR("[WRITE]Comfirm fail!");
247 				return -1;
248 			}
249 		} else if (2 == cmd_head.flag) {
250 			/*Need interrupt!*/
251 		}
252 
253 		addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1];
254 		data_len = cmd_head.data_len;
255 		pos = 0;
256 		while (data_len > 0) {
257 			len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len;
258 			ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH + pos], len);
259 			if (ret) {
260 				GTP_ERROR("[WRITE]copy_from_user failed.");
261 				return -1;
262 			}
263 			cmd_head.data[0] = ((addr >> 8) & 0xFF);
264 			cmd_head.data[1] = (addr & 0xFF);
265 
266 			GTP_DEBUG_ARRAY(cmd_head.data, len + GTP_ADDR_LENGTH);
267 
268 			if (tool_i2c_write(cmd_head.data, len + GTP_ADDR_LENGTH) <= 0) {
269 				GTP_ERROR("[WRITE]Write data failed!");
270 				return -1;
271 			}
272 			addr += len;
273 			pos += len;
274 			data_len -= len;
275 		}
276 
277 		if (cmd_head.delay) {
278 			msleep(cmd_head.delay);
279 		}
280 		return cmd_head.data_len + CMD_HEAD_LENGTH;
281 	} else if (3 == cmd_head.wr) {	/* gt1x unused */
282 		memcpy(IC_TYPE, cmd_head.data, min((u16)sizeof(IC_TYPE), cmd_head.data_len));
283 		return cmd_head.data_len + CMD_HEAD_LENGTH;
284 	} else if (5 == cmd_head.wr) {	/* ? */
285 		/*memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);*/
286 		return cmd_head.data_len + CMD_HEAD_LENGTH;
287 	} else if (7 == cmd_head.wr) {	/* disable irq! */
288 		gt1x_irq_disable();
289 #if GTP_ESD_PROTECT
290 		gt1x_esd_switch(SWITCH_OFF);
291 #endif
292 		return CMD_HEAD_LENGTH;
293 	} else if (9 == cmd_head.wr) {	/* enable irq! */
294 		gt1x_irq_enable();
295 #if GTP_ESD_PROTECT
296 		gt1x_esd_switch(SWITCH_ON);
297 #endif
298 		return CMD_HEAD_LENGTH;
299 	} else if (17 == cmd_head.wr) {
300 		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
301 		if (ret) {
302 			GTP_ERROR("copy_from_user failed.");
303 			return -1;
304 		}
305 
306 		if (cmd_head.data[GTP_ADDR_LENGTH]) {
307 			GTP_DEBUG("gtp enter rawdiff.");
308 			gt1x_rawdiff_mode = true;
309 		} else {
310 			gt1x_rawdiff_mode = false;
311 			GTP_DEBUG("gtp leave rawdiff.");
312 		}
313 
314 		return CMD_HEAD_LENGTH;
315 	} else if (11 == cmd_head.wr) {
316 		gt1x_enter_update_mode();
317 	} else if (13 == cmd_head.wr) {
318 		gt1x_leave_update_mode();
319 	} else if (15 == cmd_head.wr) {
320 		struct task_struct *thrd = NULL;
321 		memset(cmd_head.data, 0, cmd_head.data_len + 1);
322 		memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
323 		GTP_DEBUG("update firmware, filename: %s", cmd_head.data);
324 		thrd = kthread_run(gt1x_update_firmware, (void *)cmd_head.data, "GT1x FW Update");
325 		if (IS_ERR(thrd)) {
326 			return PTR_ERR(thrd);
327 		}
328 	}
329 	return CMD_HEAD_LENGTH;
330 }
331 
332 static u8 devicecount;
gt1x_tool_open(struct inode * inode,struct file * file)333 static int gt1x_tool_open(struct inode *inode, struct file *file)
334 {
335 	if (devicecount > 0) {
336 		return -ERESTARTSYS;
337 		GTP_ERROR("tools open failed!");
338 	}
339 	devicecount++;
340 	return 0;
341 }
342 
gt1x_tool_release(struct inode * inode,struct file * filp)343 static int gt1x_tool_release(struct inode *inode, struct file *filp)
344 {
345 	devicecount--;
346 	return 0;
347 }
348 /*******************************************************
349 Function:
350     Goodix tool read function.
351 Input:
352   standard proc read function param.
353 Output:
354     Return read length.
355 ********************************************************/
gt1x_tool_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)356 static ssize_t gt1x_tool_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
357 {
358 	GTP_DEBUG_FUNC();
359 	if (*ppos) {
360 		GTP_DEBUG("[PARAM]size: %zd, *ppos: %d", count, (int)*ppos);
361 		*ppos = 0;
362 		return 0;
363 	}
364 
365 	if (cmd_head.wr % 2) {
366 		GTP_ERROR("[READ] invaild operator fail!");
367 		return -1;
368 	} else if (!cmd_head.wr) {
369 	    /* general  i2c read  */
370 		u16 addr, data_len, len, loc;
371 
372 		if (1 == cmd_head.flag) {
373 			if (comfirm()) {
374 				GTP_ERROR("[READ]Comfirm fail!");
375 				return -1;
376 			}
377 		} else if (2 == cmd_head.flag) {
378 			/*Need interrupt!*/
379 		}
380 
381 		addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1];
382 		data_len = cmd_head.data_len;
383 		loc = 0;
384 
385 		GTP_DEBUG("[READ] ADDR:0x%04X.", addr);
386 		GTP_DEBUG("[READ] Length: %d", data_len);
387 
388 		if (cmd_head.delay) {
389 			msleep(cmd_head.delay);
390 		}
391 
392 		while (data_len > 0) {
393 			len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len;
394 			cmd_head.data[0] = (addr >> 8) & 0xFF;
395 			cmd_head.data[1] = (addr & 0xFF);
396 			if (tool_i2c_read(cmd_head.data, len) <= 0) {
397 				GTP_ERROR("[READ]Read data failed!");
398 				return -1;
399 			}
400 			memcpy(&buffer[loc], &cmd_head.data[GTP_ADDR_LENGTH], len);
401 			data_len -= len;
402 			addr += len;
403 			loc += len;
404 			GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len);
405 		}
406 		 *ppos += cmd_head.data_len;
407 		return cmd_head.data_len;
408 	} else if (2 == cmd_head.wr) {
409 		GTP_DEBUG("Return ic type:%s len:%d.", buffer, (s32) cmd_head.data_len);
410 		return -1;
411 	} else if (4 == cmd_head.wr) {
412 	    /* read fw update progress */
413 		buffer[0] = update_info.progress >> 8;
414 		buffer[1] = update_info.progress & 0xff;
415 		buffer[2] = update_info.max_progress >> 8;
416 		buffer[3] = update_info.max_progress & 0xff;
417 		*ppos += 4;
418 		return 4;
419 	} else if (6 == cmd_head.wr) {
420 		/*Read error code!*/
421 		return -1;
422 	} else if (8 == cmd_head.wr) {
423 	    /* Read driver version */
424 		s32 tmp_len;
425 		tmp_len = strlen(GTP_DRIVER_VERSION);
426 		memcpy(buffer, GTP_DRIVER_VERSION, tmp_len);
427 		buffer[tmp_len] = 0;
428 		*ppos += tmp_len + 1;
429 		return (tmp_len + 1);
430 	}
431 	*ppos += cmd_head.data_len;
432 	return cmd_head.data_len;
433 }
434