Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* drivers/input/touchscreen/goodix_tool.c |
2 | * | |
3 | * 2010 - 2012 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.2 | |
17 | * V1.0:2012/05/01,create file. | |
18 | * V1.2:2012/10/17,reset_guitar etc. | |
19 | * V1.4: 2013/06/08, new proc name | |
20 | */ | |
21 | ||
22 | #include "tpd.h" | |
23 | #include <linux/interrupt.h> | |
24 | #include <cust_eint.h> | |
25 | #include <linux/i2c.h> | |
26 | #include <linux/sched.h> | |
27 | #include <linux/kthread.h> | |
28 | #include <linux/rtpm_prio.h> | |
29 | #include <linux/wait.h> | |
30 | #include <linux/time.h> | |
31 | #include <linux/delay.h> | |
32 | #include "cust_gpio_usage.h" | |
33 | #include <linux/device.h> | |
34 | #include <linux/miscdevice.h> | |
35 | #include <asm/uaccess.h> | |
36 | #include <linux/proc_fs.h> /*proc*/ | |
37 | ||
38 | #include "tpd_custom_gt9xx.h" | |
39 | #pragma pack(1) | |
40 | typedef struct | |
41 | { | |
42 | u8 wr; //write read flag0:R 1:W 2:PID 3: | |
43 | u8 flag; //0:no need flag/int 1: need flag 2:need int | |
44 | u8 flag_addr[2]; //flag address | |
45 | u8 flag_val; //flag val | |
46 | u8 flag_relation; //flag_val:flag 0:not equal 1:equal 2:> 3:< | |
47 | u16 circle; //polling cycle | |
48 | u8 times; //plling times | |
49 | u8 retry; //I2C retry times | |
50 | u16 delay; //delay befor read or after write | |
51 | u16 data_len; //data length | |
52 | u8 addr_len; //address length | |
53 | u8 addr[2]; //address | |
54 | u8 res[3]; //reserved | |
55 | u8 *data; //data pointer | |
56 | } st_cmd_head; | |
57 | #pragma pack() | |
58 | st_cmd_head cmd_head; | |
59 | ||
60 | #define UPDATE_FUNCTIONS | |
61 | #define DATA_LENGTH_UINT 512 | |
62 | #define CMD_HEAD_LENGTH (sizeof(st_cmd_head) - sizeof(u8*)) | |
63 | static char procname[20] = {0}; | |
64 | extern struct i2c_client *i2c_client_point; | |
65 | static struct i2c_client *gt_client = NULL; | |
66 | ||
67 | #ifdef UPDATE_FUNCTIONS | |
68 | extern s32 gup_enter_update_mode(struct i2c_client *client); | |
69 | extern void gup_leave_update_mode(void); | |
70 | extern s32 gup_update_proc(void *dir); | |
71 | #endif | |
72 | extern s32 gup_load_hotknot_system(void); | |
73 | extern s32 gup_load_fx_system(void); | |
74 | extern s32 gup_recovery_main_system(void); | |
75 | extern s32 gup_load_main_system(char *filepath); | |
76 | ||
77 | #if 0 | |
78 | static struct proc_dir_entry *goodix_proc_entry; | |
79 | #endif | |
80 | ||
81 | static s32 goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data); | |
82 | static s32 goodix_tool_read(char *page, char **start, off_t off, int count, int *eof, void *data); | |
83 | static s32(*tool_i2c_read)(u8 *, u16); | |
84 | static s32(*tool_i2c_write)(u8 *, u16); | |
85 | ||
86 | #if GTP_ESD_PROTECT | |
87 | extern void gtp_esd_switch(struct i2c_client *client, s32 on); | |
88 | #endif | |
89 | ||
90 | #if (GTP_ESD_PROTECT || GTP_COMPATIBLE_MODE) | |
91 | extern u8 is_reseting; | |
92 | #endif | |
93 | ||
94 | ||
95 | s32 DATA_LENGTH = 0; | |
96 | s8 IC_TYPE[16] = "GT9XX"; | |
97 | ||
98 | #if HOTKNOT_BLOCK_RW | |
99 | DECLARE_WAIT_QUEUE_HEAD(bp_waiter); | |
100 | u8 got_hotknot_state = 0; | |
101 | u8 got_hotknot_extra_state = 0; | |
102 | u8 wait_hotknot_state = 0; | |
103 | u8 force_wake_flag = 0; | |
104 | #endif | |
105 | ||
106 | #define HOTKNOTNAME "hotknot" | |
107 | ||
108 | static ssize_t hotknot_read(struct file *file, char __user *buffer, | |
109 | size_t count, loff_t *ppos) | |
110 | { | |
111 | return goodix_tool_read(buffer, NULL,0, count, NULL, ppos); | |
112 | } | |
113 | ||
114 | static ssize_t hotknot_write(struct file *file, const char __user *buffer, | |
115 | size_t count, loff_t *ppos) | |
116 | { | |
117 | return goodix_tool_write(file, buffer, count, ppos); | |
118 | } | |
119 | ||
120 | static struct file_operations hotknot_fops = | |
121 | { | |
122 | // .owner = THIS_MODULE, | |
123 | .read = hotknot_read, | |
124 | .write = hotknot_write, | |
125 | }; | |
126 | ||
127 | static struct miscdevice hotknot_misc_device = | |
128 | { | |
129 | .minor = MISC_DYNAMIC_MINOR, | |
130 | .name = HOTKNOTNAME, | |
131 | .fops = &hotknot_fops, | |
132 | }; | |
133 | static ssize_t goodix_tool_upper_read(struct file *file, char __user *buffer, | |
134 | size_t count, loff_t *ppos) | |
135 | { | |
136 | return goodix_tool_read(buffer, NULL,0, count, NULL, ppos); | |
137 | } | |
138 | ||
139 | static ssize_t goodix_tool_upper_write(struct file *file, const char __user *buffer, | |
140 | size_t count, loff_t *ppos) | |
141 | { | |
142 | return goodix_tool_write(file, buffer, count, ppos); | |
143 | } | |
144 | ||
145 | static const struct file_operations gt_tool_fops = { | |
146 | .write = goodix_tool_upper_write, | |
147 | .read = goodix_tool_upper_read, | |
148 | }; | |
149 | ||
150 | static void tool_set_proc_name(char * procname) | |
151 | { | |
152 | #if 1 | |
153 | char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", | |
154 | "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; | |
155 | char date[20] = {0}; | |
156 | char month[4] = {0}; | |
157 | int i = 0, n_month = 1, n_day = 0, n_year = 0; | |
158 | ||
159 | sprintf(date, "%s", __DATE__); | |
160 | ||
161 | //GTP_DEBUG("compile date: %s", date); | |
162 | ||
163 | sscanf(date, "%s %d %d", month, &n_day, &n_year); | |
164 | ||
165 | for (i = 0; i < 12; ++i) | |
166 | { | |
167 | if (!memcmp(months[i], month, 3)) | |
168 | { | |
169 | n_month = i+1; | |
170 | break; | |
171 | } | |
172 | } | |
173 | ||
174 | sprintf(procname, "gmnode%04d%02d%02d", n_year, n_month, n_day); | |
175 | #else | |
176 | sprintf(procname, HOTKNOTNAME); | |
177 | #endif | |
178 | //GTP_DEBUG("procname = %s", procname); | |
179 | } | |
180 | static s32 tool_i2c_read_no_extra(u8 *buf, u16 len) | |
181 | { | |
182 | s32 ret = -1; | |
183 | ||
184 | ret = gtp_i2c_read(gt_client, buf, len + GTP_ADDR_LENGTH); | |
185 | return ret; | |
186 | } | |
187 | ||
188 | static s32 tool_i2c_write_no_extra(u8 *buf, u16 len) | |
189 | { | |
190 | s32 ret = -1; | |
191 | ||
192 | ret = gtp_i2c_write(gt_client, buf, len); | |
193 | return ret; | |
194 | } | |
195 | ||
196 | static s32 tool_i2c_read_with_extra(u8 *buf, u16 len) | |
197 | { | |
198 | s32 ret = -1; | |
199 | u8 pre[2] = {0x0f, 0xff}; | |
200 | u8 end[2] = {0x80, 0x00}; | |
201 | ||
202 | tool_i2c_write_no_extra(pre, 2); | |
203 | ret = tool_i2c_read_no_extra(buf, len); | |
204 | tool_i2c_write_no_extra(end, 2); | |
205 | ||
206 | return ret; | |
207 | } | |
208 | ||
209 | static s32 tool_i2c_write_with_extra(u8 *buf, u16 len) | |
210 | { | |
211 | s32 ret = -1; | |
212 | u8 pre[2] = {0x0f, 0xff}; | |
213 | u8 end[2] = {0x80, 0x00}; | |
214 | ||
215 | tool_i2c_write_no_extra(pre, 2); | |
216 | ret = tool_i2c_write_no_extra(buf, len); | |
217 | tool_i2c_write_no_extra(end, 2); | |
218 | ||
219 | return ret; | |
220 | } | |
221 | ||
222 | static void register_i2c_func(void) | |
223 | { | |
224 | // if (!strncmp(IC_TYPE, "GT818", 5) || !strncmp(IC_TYPE, "GT816", 5) | |
225 | // || !strncmp(IC_TYPE, "GT811", 5) || !strncmp(IC_TYPE, "GT818F", 6) | |
226 | // || !strncmp(IC_TYPE, "GT827", 5) || !strncmp(IC_TYPE,"GT828", 5) | |
227 | // || !strncmp(IC_TYPE, "GT813", 5)) | |
228 | if (strncmp(IC_TYPE, "GT8110", 6) && strncmp(IC_TYPE, "GT8105", 6) | |
229 | && strncmp(IC_TYPE, "GT801", 5) && strncmp(IC_TYPE, "GT800", 5) | |
230 | && strncmp(IC_TYPE, "GT801PLUS", 9) && strncmp(IC_TYPE, "GT811", 5) | |
231 | && strncmp(IC_TYPE, "GTxxx", 5) && strncmp(IC_TYPE, "GT9XX", 5)) | |
232 | { | |
233 | tool_i2c_read = tool_i2c_read_with_extra; | |
234 | tool_i2c_write = tool_i2c_write_with_extra; | |
235 | GTP_DEBUG("I2C function: with pre and end cmd!"); | |
236 | } | |
237 | else | |
238 | { | |
239 | tool_i2c_read = tool_i2c_read_no_extra; | |
240 | tool_i2c_write = tool_i2c_write_no_extra; | |
241 | GTP_INFO("I2C function: without pre and end cmd!"); | |
242 | } | |
243 | } | |
244 | ||
245 | static void unregister_i2c_func(void) | |
246 | { | |
247 | tool_i2c_read = NULL; | |
248 | tool_i2c_write = NULL; | |
249 | GTP_INFO("I2C function: unregister i2c transfer function!"); | |
250 | } | |
251 | ||
252 | s32 init_wr_node(struct i2c_client *client) | |
253 | { | |
254 | s32 i; | |
255 | ||
256 | gt_client = i2c_client_point; | |
257 | ||
258 | memset(&cmd_head, 0, sizeof(cmd_head)); | |
259 | cmd_head.data = NULL; | |
260 | ||
261 | i = 5; | |
262 | ||
263 | while ((!cmd_head.data) && i) | |
264 | { | |
265 | cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL); | |
266 | ||
267 | if (NULL != cmd_head.data) | |
268 | { | |
269 | break; | |
270 | } | |
271 | ||
272 | i--; | |
273 | } | |
274 | ||
275 | if (i) | |
276 | { | |
277 | DATA_LENGTH = i * DATA_LENGTH_UINT + GTP_ADDR_LENGTH; | |
278 | GTP_INFO("Applied memory size:%d.", DATA_LENGTH); | |
279 | } | |
280 | else | |
281 | { | |
282 | GTP_ERROR("Apply for memory failed."); | |
283 | return FAIL; | |
284 | } | |
285 | ||
286 | cmd_head.addr_len = 2; | |
287 | cmd_head.retry = 5; | |
288 | ||
289 | register_i2c_func(); | |
290 | ||
291 | tool_set_proc_name(procname); | |
292 | #if 0 | |
293 | goodix_proc_entry = create_proc_entry(procname, 0660, NULL); | |
294 | if (goodix_proc_entry == NULL) | |
295 | { | |
296 | GTP_ERROR("Couldn't create proc entry!"); | |
297 | return FAIL; | |
298 | } | |
299 | else | |
300 | { | |
301 | GTP_INFO("Create proc entry success!"); | |
302 | goodix_proc_entry->write_proc = goodix_tool_write; | |
303 | goodix_proc_entry->read_proc = goodix_tool_read; | |
304 | } | |
305 | #else | |
306 | if(proc_create(procname, 0660, NULL, >_tool_fops)== NULL) | |
307 | { | |
308 | GTP_ERROR("create_proc_entry %s failed", procname); | |
309 | return -1; | |
310 | } | |
311 | #endif | |
312 | ||
313 | #if 1 // setting by hotknot feature | |
314 | if (misc_register(&hotknot_misc_device)) | |
315 | { | |
316 | printk("mtk_tpd: hotknot_device register failed\n"); | |
317 | return FAIL; | |
318 | } | |
319 | #endif | |
320 | ||
321 | return SUCCESS; | |
322 | } | |
323 | ||
324 | void uninit_wr_node(void) | |
325 | { | |
326 | kfree(cmd_head.data); | |
327 | cmd_head.data = NULL; | |
328 | unregister_i2c_func(); | |
329 | remove_proc_entry(procname, NULL); | |
330 | } | |
331 | ||
332 | static u8 relation(u8 src, u8 dst, u8 rlt) | |
333 | { | |
334 | u8 ret = 0; | |
335 | ||
336 | switch (rlt) | |
337 | { | |
338 | case 0: | |
339 | ret = (src != dst) ? true : false; | |
340 | break; | |
341 | ||
342 | case 1: | |
343 | ret = (src == dst) ? true : false; | |
344 | GTP_DEBUG("equal:src:0x%02x dst:0x%02x ret:%d.", src, dst, (s32)ret); | |
345 | break; | |
346 | ||
347 | case 2: | |
348 | ret = (src > dst) ? true : false; | |
349 | break; | |
350 | ||
351 | case 3: | |
352 | ret = (src < dst) ? true : false; | |
353 | break; | |
354 | ||
355 | case 4: | |
356 | ret = (src & dst) ? true : false; | |
357 | break; | |
358 | ||
359 | case 5: | |
360 | ret = (!(src | dst)) ? true : false; | |
361 | break; | |
362 | ||
363 | default: | |
364 | ret = false; | |
365 | break; | |
366 | } | |
367 | ||
368 | return ret; | |
369 | } | |
370 | ||
371 | /******************************************************* | |
372 | Function: | |
373 | Comfirm function. | |
374 | Input: | |
375 | None. | |
376 | Output: | |
377 | Return write length. | |
378 | ********************************************************/ | |
379 | static u8 comfirm(void) | |
380 | { | |
381 | s32 i = 0; | |
382 | u8 buf[32]; | |
383 | ||
384 | // memcpy(&buf[GTP_ADDR_LENGTH - cmd_head.addr_len], &cmd_head.flag_addr, cmd_head.addr_len); | |
385 | // memcpy(buf, &cmd_head.flag_addr, cmd_head.addr_len);//Modified by Scott, 2012-02-17 | |
386 | memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len); | |
387 | ||
388 | for (i = 0; i < cmd_head.times; i++) | |
389 | { | |
390 | if (tool_i2c_read(buf, 1) <= 0) | |
391 | { | |
392 | GTP_ERROR("Read flag data failed!"); | |
393 | return FAIL; | |
394 | } | |
395 | ||
396 | if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, cmd_head.flag_relation)) | |
397 | { | |
398 | GTP_DEBUG("value at flag addr:0x%02x.", buf[GTP_ADDR_LENGTH]); | |
399 | GTP_DEBUG("flag value:0x%02x.", cmd_head.flag_val); | |
400 | break; | |
401 | } | |
402 | ||
403 | msleep(cmd_head.circle); | |
404 | } | |
405 | ||
406 | if (i >= cmd_head.times) | |
407 | { | |
408 | GTP_ERROR("Didn't get the flag to continue!"); | |
409 | return FAIL; | |
410 | } | |
411 | ||
412 | return SUCCESS; | |
413 | } | |
414 | ||
415 | /******************************************************* | |
416 | Function: | |
417 | Goodix tool write function. | |
418 | Input: | |
419 | standard proc write function param. | |
420 | Output: | |
421 | Return write length. | |
422 | ********************************************************/ | |
423 | static s32 goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data) | |
424 | { | |
425 | u64 ret = 0; | |
426 | GTP_DEBUG_FUNC(); | |
427 | GTP_DEBUG_ARRAY((u8 *)buff, len); | |
428 | ||
429 | if(tpd_halt == 1||is_reseting == 1) | |
430 | { | |
431 | //GTP_ERROR("[Write]tpd_halt =1 fail!"); | |
432 | return FAIL; | |
433 | } | |
434 | ||
435 | ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); | |
436 | ||
437 | if (ret) | |
438 | { | |
439 | GTP_ERROR("copy_from_user failed."); | |
440 | } | |
441 | ||
442 | GTP_DEBUG("wr :0x%02x.", cmd_head.wr); | |
443 | /* | |
444 | GTP_DEBUG("flag:0x%02x.", cmd_head.flag); | |
445 | GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0], cmd_head.flag_addr[1]); | |
446 | GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val); | |
447 | GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation); | |
448 | GTP_DEBUG("circle :%d.", (s32)cmd_head.circle); | |
449 | GTP_DEBUG("times :%d.", (s32)cmd_head.times); | |
450 | GTP_DEBUG("retry :%d.", (s32)cmd_head.retry); | |
451 | GTP_DEBUG("delay :%d.", (s32)cmd_head.delay); | |
452 | GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len); | |
453 | GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len); | |
454 | GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); | |
455 | GTP_DEBUG("len:%d.", (s32)len); | |
456 | GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]); | |
457 | */ | |
458 | ||
459 | if (1 == cmd_head.wr) | |
460 | { | |
461 | // copy_from_user(&cmd_head.data[cmd_head.addr_len], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
462 | ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
463 | ||
464 | if (ret) | |
465 | { | |
466 | GTP_ERROR("copy_from_user failed."); | |
467 | } | |
468 | ||
469 | memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len); | |
470 | ||
471 | GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len + cmd_head.addr_len); | |
472 | GTP_DEBUG_ARRAY((u8 *)&buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
473 | ||
474 | if (1 == cmd_head.flag) | |
475 | { | |
476 | if (FAIL == comfirm()) | |
477 | { | |
478 | GTP_ERROR("[WRITE]Comfirm fail!"); | |
479 | return FAIL; | |
480 | } | |
481 | } | |
482 | else if (2 == cmd_head.flag) | |
483 | { | |
484 | //Need interrupt! | |
485 | } | |
486 | ||
487 | if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], | |
488 | cmd_head.data_len + cmd_head.addr_len) <= 0) | |
489 | { | |
490 | GTP_ERROR("[WRITE]Write data failed!"); | |
491 | return FAIL; | |
492 | } | |
493 | ||
494 | GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.data_len + cmd_head.addr_len); | |
495 | ||
496 | if (cmd_head.delay) | |
497 | { | |
498 | msleep(cmd_head.delay); | |
499 | } | |
500 | ||
501 | return cmd_head.data_len + CMD_HEAD_LENGTH; | |
502 | } | |
503 | else if (3 == cmd_head.wr) //Write ic type | |
504 | { | |
505 | memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); | |
506 | register_i2c_func(); | |
507 | ||
508 | return cmd_head.data_len + CMD_HEAD_LENGTH; | |
509 | } | |
510 | else if (5 == cmd_head.wr) | |
511 | { | |
512 | //memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); | |
513 | ||
514 | return cmd_head.data_len + CMD_HEAD_LENGTH; | |
515 | } | |
516 | else if (7 == cmd_head.wr)//disable irq! | |
517 | { | |
518 | mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); | |
519 | #if GTP_ESD_PROTECT | |
520 | gtp_esd_switch(i2c_client_point, SWITCH_OFF); | |
521 | #endif | |
522 | return CMD_HEAD_LENGTH; | |
523 | } | |
524 | else if (9 == cmd_head.wr) //enable irq! | |
525 | { | |
526 | mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); | |
527 | #if GTP_ESD_PROTECT | |
528 | gtp_esd_switch(i2c_client_point, SWITCH_ON); | |
529 | #endif | |
530 | return CMD_HEAD_LENGTH; | |
531 | } | |
532 | else if (17 == cmd_head.wr) | |
533 | { | |
534 | ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
535 | ||
536 | if (ret) | |
537 | { | |
538 | GTP_DEBUG("copy_from_user failed."); | |
539 | } | |
540 | ||
541 | if (cmd_head.data[GTP_ADDR_LENGTH]) | |
542 | { | |
543 | GTP_DEBUG("gtp enter rawdiff."); | |
544 | gtp_rawdiff_mode = true; | |
545 | } | |
546 | else | |
547 | { | |
548 | gtp_rawdiff_mode = false; | |
549 | GTP_DEBUG("gtp leave rawdiff."); | |
550 | } | |
551 | ||
552 | return CMD_HEAD_LENGTH; | |
553 | } | |
554 | ||
555 | #ifdef UPDATE_FUNCTIONS | |
556 | else if (11 == cmd_head.wr) //Enter update mode! | |
557 | { | |
558 | if (FAIL == gup_enter_update_mode(gt_client)) | |
559 | { | |
560 | return FAIL; | |
561 | } | |
562 | } | |
563 | else if (13 == cmd_head.wr)//Leave update mode! | |
564 | { | |
565 | gup_leave_update_mode(); | |
566 | } | |
567 | else if (15 == cmd_head.wr) //Update firmware! | |
568 | { | |
569 | show_len = 0; | |
570 | total_len = 0; | |
4b9e9796 S |
571 | if ((cmd_head.data == NULL) |
572 | || (cmd_head.data_len >= DATA_LENGTH) | |
573 | || (cmd_head.data_len >= (len - CMD_HEAD_LENGTH))) { | |
574 | GTP_ERROR("copy_from_user data out of range."); | |
575 | return -EINVAL; | |
576 | } | |
577 | ||
6fa3eb70 S |
578 | memset(cmd_head.data, 0, cmd_head.data_len + 1); |
579 | ret = copy_from_user(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
580 | if (ret) | |
581 | { | |
582 | GTP_ERROR("copy_from_user failed."); | |
583 | } | |
584 | GTP_DEBUG("update firmware, filename: %s", cmd_head.data); | |
585 | if (FAIL == gup_update_proc((void *)cmd_head.data)) | |
586 | { | |
587 | return FAIL; | |
588 | } | |
589 | } | |
590 | ||
591 | #endif | |
592 | else if (19 == cmd_head.wr) //load subsystem | |
593 | { | |
594 | ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
595 | if(0 == cmd_head.data[0]) | |
596 | { | |
597 | if (FAIL == gup_load_hotknot_system()) | |
598 | { | |
599 | return FAIL; | |
600 | } | |
601 | } | |
602 | else if(1 == cmd_head.data[0]) | |
603 | { | |
604 | if (FAIL == gup_load_fx_system()) | |
605 | { | |
606 | return FAIL; | |
607 | } | |
608 | } | |
609 | else if(2 == cmd_head.data[0]) | |
610 | { | |
611 | if (FAIL == gup_recovery_main_system()) | |
612 | { | |
613 | return FAIL; | |
614 | } | |
615 | } | |
616 | else if(3 == cmd_head.data[0]) | |
617 | { | |
618 | if (FAIL == gup_load_main_system(NULL)) | |
619 | { | |
620 | return FAIL; | |
621 | } | |
622 | } | |
623 | } | |
624 | #if HOTKNOT_BLOCK_RW | |
625 | else if (21 == cmd_head.wr) | |
626 | { | |
627 | u16 wait_hotknot_timeout = 0; | |
628 | u8 rqst_hotknot_state; | |
629 | ||
630 | ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], | |
631 | &buff[CMD_HEAD_LENGTH], cmd_head.data_len); | |
632 | ||
633 | if (ret) | |
634 | { | |
635 | GTP_ERROR("copy_from_user failed."); | |
636 | } | |
637 | ||
638 | rqst_hotknot_state = cmd_head.data[GTP_ADDR_LENGTH]; | |
639 | wait_hotknot_state |= rqst_hotknot_state; | |
640 | wait_hotknot_timeout = (cmd_head.data[GTP_ADDR_LENGTH + 1]<<8) + | |
641 | cmd_head.data[GTP_ADDR_LENGTH + 2]; | |
642 | GTP_DEBUG("Goodix tool received wait polling state:0x%x,timeout:%d, all wait state:0x%x", | |
643 | rqst_hotknot_state, wait_hotknot_timeout, wait_hotknot_state); | |
644 | got_hotknot_state &= (~rqst_hotknot_state); | |
645 | //got_hotknot_extra_state = 0; | |
646 | switch(rqst_hotknot_state) | |
647 | { | |
648 | set_current_state(TASK_INTERRUPTIBLE); | |
649 | case HN_DEVICE_PAIRED: | |
650 | hotknot_paired_flag = 0; | |
651 | wait_event_interruptible(bp_waiter, force_wake_flag || | |
652 | rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state)); | |
653 | wait_hotknot_state &= (~rqst_hotknot_state); | |
654 | if(rqst_hotknot_state != (got_hotknot_state&rqst_hotknot_state)) | |
655 | { | |
656 | GTP_ERROR("Wait 0x%x block polling waiter failed.", rqst_hotknot_state); | |
657 | force_wake_flag = 0; | |
658 | return FAIL; | |
659 | } | |
660 | break; | |
661 | case HN_MASTER_SEND: | |
662 | case HN_SLAVE_RECEIVED: | |
663 | wait_event_interruptible_timeout(bp_waiter, force_wake_flag || | |
664 | rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state), | |
665 | wait_hotknot_timeout); | |
666 | wait_hotknot_state &= (~rqst_hotknot_state); | |
667 | if(rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state)) | |
668 | { | |
669 | return got_hotknot_extra_state; | |
670 | } | |
671 | else | |
672 | { | |
673 | GTP_ERROR("Wait 0x%x block polling waiter timeout.", rqst_hotknot_state); | |
674 | force_wake_flag = 0; | |
675 | return FAIL; | |
676 | } | |
677 | break; | |
678 | case HN_MASTER_DEPARTED: | |
679 | case HN_SLAVE_DEPARTED: | |
680 | wait_event_interruptible_timeout(bp_waiter, force_wake_flag || | |
681 | rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state), | |
682 | wait_hotknot_timeout); | |
683 | wait_hotknot_state &= (~rqst_hotknot_state); | |
684 | if(rqst_hotknot_state != (got_hotknot_state&rqst_hotknot_state)) | |
685 | { | |
686 | GTP_ERROR("Wait 0x%x block polling waitor timeout.", rqst_hotknot_state); | |
687 | force_wake_flag = 0; | |
688 | return FAIL; | |
689 | } | |
690 | break; | |
691 | default: | |
692 | GTP_ERROR("Invalid rqst_hotknot_state in goodix_tool."); | |
693 | break; | |
694 | } | |
695 | force_wake_flag = 0; | |
696 | } | |
697 | else if(23 == cmd_head.wr) | |
698 | { | |
699 | GTP_DEBUG("Manual wakeup all block polling waiter!"); | |
700 | got_hotknot_state = 0; | |
701 | wait_hotknot_state = 0; | |
702 | force_wake_flag = 1; | |
703 | hotknot_paired_flag = 0; | |
704 | wake_up_interruptible(&bp_waiter); | |
705 | } | |
706 | #endif | |
707 | return CMD_HEAD_LENGTH; | |
708 | } | |
709 | ||
710 | /******************************************************* | |
711 | Function: | |
712 | Goodix tool read function. | |
713 | Input: | |
714 | standard proc read function param. | |
715 | Output: | |
716 | Return read length. | |
717 | ********************************************************/ | |
718 | static s32 goodix_tool_read(char *page, char **start, off_t off, int count, int *eof, void *data) | |
719 | { | |
720 | u64 ret = 0; | |
721 | ||
722 | GTP_DEBUG_FUNC(); | |
723 | ||
724 | if(tpd_halt == 1||is_reseting == 1) | |
725 | { | |
726 | //GTP_ERROR("[READ]tpd_halt =1 fail!"); | |
727 | return FAIL; | |
728 | } | |
729 | if (cmd_head.wr % 2) | |
730 | { | |
731 | GTP_ERROR("[READ] invaild operator fail!"); | |
732 | return FAIL; | |
733 | } | |
734 | else if (!cmd_head.wr) | |
735 | { | |
736 | u16 len = 0; | |
737 | s16 data_len = 0; | |
738 | u16 loc = 0; | |
739 | ||
740 | if (1 == cmd_head.flag) | |
741 | { | |
742 | if (FAIL == comfirm()) | |
743 | { | |
744 | GTP_ERROR("[READ]Comfirm fail!"); | |
745 | return FAIL; | |
746 | } | |
747 | } | |
748 | else if (2 == cmd_head.flag) | |
749 | { | |
750 | //Need interrupt! | |
751 | } | |
752 | ||
753 | memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len); | |
754 | ||
755 | GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0], cmd_head.data[1]); | |
756 | GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); | |
757 | ||
758 | if (cmd_head.delay) | |
759 | { | |
760 | msleep(cmd_head.delay); | |
761 | } | |
762 | ||
763 | data_len = cmd_head.data_len; | |
764 | ||
765 | while (data_len > 0) | |
766 | { | |
767 | if (data_len > DATA_LENGTH) | |
768 | { | |
769 | len = DATA_LENGTH; | |
770 | } | |
771 | else | |
772 | { | |
773 | len = data_len; | |
774 | } | |
775 | ||
776 | data_len -= DATA_LENGTH; | |
777 | ||
778 | if (tool_i2c_read(cmd_head.data, len) <= 0) | |
779 | { | |
780 | GTP_ERROR("[READ]Read data failed!"); | |
781 | return FAIL; | |
782 | } | |
783 | ||
784 | ret = copy_to_user(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH], len); | |
785 | if (ret) | |
786 | { | |
787 | GTP_ERROR("copy_from_user failed."); | |
788 | return FAIL; | |
789 | } | |
790 | loc += len; | |
791 | ||
792 | GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len); | |
793 | GTP_DEBUG_ARRAY(page, len); | |
794 | } | |
795 | } | |
796 | else if (2 == cmd_head.wr) | |
797 | { | |
798 | // memcpy(page, "gt8", cmd_head.data_len); | |
799 | // memcpy(page, "GT818", 5); | |
800 | // page[5] = 0; | |
801 | ||
802 | GTP_DEBUG("Return ic type:%s len:%d.", page, (s32)cmd_head.data_len); | |
803 | return cmd_head.data_len; | |
804 | //return sizeof(IC_TYPE_NAME); | |
805 | } | |
806 | else if (4 == cmd_head.wr) | |
807 | { | |
808 | page[0] = show_len >> 8; | |
809 | page[1] = show_len & 0xff; | |
810 | page[2] = total_len >> 8; | |
811 | page[3] = total_len & 0xff; | |
812 | ||
813 | return cmd_head.data_len; | |
814 | } | |
815 | else if (6 == cmd_head.wr) | |
816 | { | |
817 | //Read error code! | |
818 | } | |
819 | else if (8 == cmd_head.wr) //Read driver version | |
820 | { | |
821 | // memcpy(page, GTP_DRIVER_VERSION, strlen(GTP_DRIVER_VERSION)); | |
822 | s32 tmp_len; | |
823 | tmp_len = strlen(GTP_DRIVER_VERSION); | |
824 | ret = copy_to_user(page, GTP_DRIVER_VERSION, tmp_len); | |
825 | if (ret) | |
826 | { | |
827 | GTP_ERROR("copy_from_user failed."); | |
828 | return FAIL; | |
829 | } | |
830 | page[tmp_len] = 0; | |
831 | } | |
832 | ||
833 | return cmd_head.data_len; | |
834 | } | |
835 | ||
836 |