xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/cyttsp5/cyttsp5_test_device_access_api.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * cyttsp5_test_device_access_api.c
3  * Parade TrueTouch(TM) Standard Product V5 Device Access API test module.
4  * For use with Parade touchscreen controllers.
5  * Supported parts include:
6  * CYTMA5XX
7  * CYTMA448
8  * CYTMA445A
9  * CYTT21XXX
10  * CYTT31XXX
11  *
12  * Copyright (C) 2015 Parade Technologies
13  * Copyright (C) 2012-2015 Cypress Semiconductor
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * version 2, and only version 2, as published by the
18  * Free Software Foundation.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
26  *
27  */
28 
29 #include <linux/module.h>
30 #include <linux/cyttsp5_device_access-api.h>
31 #include <asm/unaligned.h>
32 
33 #define BUFFER_SIZE		256
34 
35 #define COMMAND_GET_SYSTEM_INFO		2
36 #define COMMAND_SUSPEND_SCANNING	3
37 #define COMMAND_RESUME_SCANNING		4
38 #define COMMAND_GET_PARAMETER		5
39 #define COMMAND_SET_PARAMETER		6
40 
41 #define PARAMETER_ACTIVE_DISTANCE_2	0x0B
42 
43 struct tt_output_report {
44 	__le16 reg_address;
45 	__le16 length;
46 	u8 report_id;
47 	u8 reserved;
48 	u8 command;
49 	u8 parameters[0];
50 } __packed;
51 
52 struct tt_input_report {
53 	__le16 length;
54 	u8 report_id;
55 	u8 reserved;
56 	u8 command;
57 	u8 return_data[0];
58 } __packed;
59 
prepare_tt_output_report(struct tt_output_report * out,u16 length,u8 command)60 static int prepare_tt_output_report(struct tt_output_report *out,
61 		u16 length, u8 command)
62 {
63 	put_unaligned_le16(0x04, &out->reg_address);
64 	put_unaligned_le16(5 + length, &out->length);
65 
66 	out->report_id = 0x2f;
67 	out->reserved = 0x00;
68 	out->command = command;
69 
70 	return 7 + length;
71 }
72 
check_and_parse_tt_input_report(struct tt_input_report * in,u16 * length,u8 * command)73 static int check_and_parse_tt_input_report(struct tt_input_report *in,
74 		u16 *length, u8 *command)
75 {
76 	if (in->report_id != 0x1f)
77 		return -EINVAL;
78 
79 	*length = get_unaligned_le16(&in->length);
80 	*command = in->command & 0x7f;
81 
82 	return 0;
83 }
84 
prepare_get_system_info_report(u8 * buf)85 static int prepare_get_system_info_report(u8 *buf)
86 {
87 	struct tt_output_report *out = (struct tt_output_report *)buf;
88 
89 	return prepare_tt_output_report(out, 0, COMMAND_GET_SYSTEM_INFO);
90 }
91 
check_get_system_info_response(u8 * buf,u16 read_length)92 static int check_get_system_info_response(u8 *buf, u16 read_length)
93 {
94 	struct tt_input_report *in = (struct tt_input_report *)buf;
95 	u16 length = 0;
96 	u8 command = 0;
97 
98 	if (read_length != 51)
99 		return -EINVAL;
100 
101 	if (check_and_parse_tt_input_report(in, &length, &command)
102 			|| command != COMMAND_GET_SYSTEM_INFO
103 			|| length != 51)
104 		return -EINVAL;
105 
106 	pr_info("PIP Major Version: %d\n", in->return_data[0]);
107 	pr_info("PIP Minor Version: %d\n", in->return_data[1]);
108 	pr_info("Touch Firmware Product Id: %d\n",
109 			get_unaligned_le16(&in->return_data[2]));
110 	pr_info("Touch Firmware Major Version: %d\n", in->return_data[4]);
111 	pr_info("Touch Firmware Minor Version: %d\n", in->return_data[5]);
112 	pr_info("Touch Firmware Internal Revision Control Number: %d\n",
113 			get_unaligned_le32(&in->return_data[6]));
114 	pr_info("Customer Specified Firmware/Configuration Version: %d\n",
115 			get_unaligned_le16(&in->return_data[10]));
116 	pr_info("Bootloader Major Version: %d\n", in->return_data[12]);
117 	pr_info("Bootloader Minor Version: %d\n", in->return_data[13]);
118 	pr_info("Family ID: 0x%02x\n", in->return_data[14]);
119 	pr_info("Revision ID: 0x%02x\n", in->return_data[15]);
120 	pr_info("Silicon ID: 0x%02x\n",
121 			get_unaligned_le16(&in->return_data[16]));
122 	pr_info("Parade Manufacturing ID[0]: 0x%02x\n", in->return_data[18]);
123 	pr_info("Parade Manufacturing ID[1]: 0x%02x\n", in->return_data[19]);
124 	pr_info("Parade Manufacturing ID[2]: 0x%02x\n", in->return_data[20]);
125 	pr_info("Parade Manufacturing ID[3]: 0x%02x\n", in->return_data[21]);
126 	pr_info("Parade Manufacturing ID[4]: 0x%02x\n", in->return_data[22]);
127 	pr_info("Parade Manufacturing ID[5]: 0x%02x\n", in->return_data[23]);
128 	pr_info("Parade Manufacturing ID[6]: 0x%02x\n", in->return_data[24]);
129 	pr_info("Parade Manufacturing ID[7]: 0x%02x\n", in->return_data[25]);
130 	pr_info("POST Result Code: 0x%02x\n",
131 			get_unaligned_le16(&in->return_data[26]));
132 
133 	pr_info("Number of X Electrodes: %d\n", in->return_data[28]);
134 	pr_info("Number of Y Electrodes: %d\n", in->return_data[29]);
135 	pr_info("Panel X Axis Length: %d\n",
136 			get_unaligned_le16(&in->return_data[30]));
137 	pr_info("Panel Y Axis Length: %d\n",
138 			get_unaligned_le16(&in->return_data[32]));
139 	pr_info("Panel X Axis Resolution: %d\n",
140 			get_unaligned_le16(&in->return_data[34]));
141 	pr_info("Panel Y Axis Resolution: %d\n",
142 			get_unaligned_le16(&in->return_data[36]));
143 	pr_info("Panel Pressure Resolution: %d\n",
144 			get_unaligned_le16(&in->return_data[38]));
145 	pr_info("X_ORG: %d\n", in->return_data[40]);
146 	pr_info("Y_ORG: %d\n", in->return_data[41]);
147 	pr_info("Panel ID: %d\n", in->return_data[42]);
148 	pr_info("Buttons: 0x%02x\n", in->return_data[43]);
149 	pr_info("BAL SELF MC: 0x%02x\n", in->return_data[44]);
150 	pr_info("Max Number of Touch Records per Refresh Cycle: %d\n",
151 			in->return_data[45]);
152 
153 	return 0;
154 }
155 
prepare_get_parameter_report(u8 * buf,u8 parameter_id)156 static int prepare_get_parameter_report(u8 *buf, u8 parameter_id)
157 {
158 	struct tt_output_report *out = (struct tt_output_report *)buf;
159 
160 	out->parameters[0] = parameter_id;
161 
162 	return prepare_tt_output_report(out, 1, COMMAND_GET_PARAMETER);
163 }
164 
check_get_parameter_response(u8 * buf,u16 read_length,u32 * parameter_value)165 static int check_get_parameter_response(u8 *buf, u16 read_length,
166 		u32 *parameter_value)
167 {
168 	struct tt_input_report *in = (struct tt_input_report *)buf;
169 	u16 length = 0;
170 	u8 command = 0;
171 	u32 param_value = 0;
172 	u8 param_id;
173 	u8 param_size = 0;
174 
175 	if (read_length != 8 && read_length != 9 && read_length != 11)
176 		return -EINVAL;
177 
178 	if (check_and_parse_tt_input_report(in, &length, &command)
179 			|| command != COMMAND_GET_PARAMETER
180 			|| (length != 8 && length != 9 && length != 11))
181 		return -EINVAL;
182 
183 	param_id = in->return_data[0];
184 
185 	param_size = in->return_data[1];
186 
187 	if (param_size == 1)
188 		param_value = in->return_data[2];
189 	else if (param_size == 2)
190 		param_value = get_unaligned_le16(&in->return_data[2]);
191 	else if (param_size == 4)
192 		param_value = get_unaligned_le32(&in->return_data[2]);
193 	else
194 		return -EINVAL;
195 
196 	pr_info("%s: Parameter ID: 0x%02x Value: 0x%02x\n",
197 		__func__, param_id, param_value);
198 
199 	if (parameter_value)
200 		*parameter_value = param_value;
201 
202 	return 0;
203 }
204 
prepare_set_parameter_report(u8 * buf,u8 parameter_id,u8 parameter_size,u32 parameter_value)205 static int prepare_set_parameter_report(u8 *buf, u8 parameter_id,
206 		u8 parameter_size, u32 parameter_value)
207 {
208 	struct tt_output_report *out = (struct tt_output_report *)buf;
209 
210 	out->parameters[0] = parameter_id;
211 	out->parameters[1] = parameter_size;
212 
213 	if (parameter_size == 1)
214 		out->parameters[2] = (u8)parameter_value;
215 	else if (parameter_size == 2)
216 		put_unaligned_le16(parameter_value, &out->parameters[2]);
217 	else if (parameter_size == 4)
218 		put_unaligned_le32(parameter_value, &out->parameters[2]);
219 	else
220 		return -EINVAL;
221 
222 	return prepare_tt_output_report(out, 2 + parameter_size,
223 			COMMAND_SET_PARAMETER);
224 }
225 
check_set_parameter_response(u8 * buf,u16 read_length)226 static int check_set_parameter_response(u8 *buf, u16 read_length)
227 {
228 	struct tt_input_report *in = (struct tt_input_report *)buf;
229 	u16 length = 0;
230 	u8 command = 0;
231 	u8 param_id;
232 	u8 param_size = 0;
233 
234 	if (read_length != 7)
235 		return -EINVAL;
236 
237 	if (check_and_parse_tt_input_report(in, &length, &command)
238 			|| command != COMMAND_SET_PARAMETER
239 			|| length != 7)
240 		return -EINVAL;
241 
242 	param_id = in->return_data[0];
243 	param_size = in->return_data[1];
244 
245 	pr_info("%s: Parameter ID: 0x%02x Size: 0x%02x\n",
246 		__func__, param_id, param_size);
247 
248 	return 0;
249 }
250 
prepare_suspend_scanning_report(u8 * buf)251 static int prepare_suspend_scanning_report(u8 *buf)
252 {
253 	struct tt_output_report *out = (struct tt_output_report *)buf;
254 
255 	return prepare_tt_output_report(out, 0, COMMAND_SUSPEND_SCANNING);
256 }
257 
check_suspend_scanning_response(u8 * buf,u16 read_length)258 static int check_suspend_scanning_response(u8 *buf, u16 read_length)
259 {
260 	struct tt_input_report *in = (struct tt_input_report *)buf;
261 	u16 length = 0;
262 	u8 command = 0;
263 
264 	if (read_length != 5)
265 		return -EINVAL;
266 
267 	if (check_and_parse_tt_input_report(in, &length, &command)
268 			|| command != COMMAND_SUSPEND_SCANNING
269 			|| length != 5)
270 		return -EINVAL;
271 
272 	return 0;
273 }
274 
prepare_resume_scanning_report(u8 * buf)275 static int prepare_resume_scanning_report(u8 *buf)
276 {
277 	struct tt_output_report *out = (struct tt_output_report *)buf;
278 
279 	return prepare_tt_output_report(out, 0, COMMAND_RESUME_SCANNING);
280 }
281 
check_resume_scanning_response(u8 * buf,u16 read_length)282 static int check_resume_scanning_response(u8 *buf, u16 read_length)
283 {
284 	struct tt_input_report *in = (struct tt_input_report *)buf;
285 	u16 length = 0;
286 	u8 command = 0;
287 
288 	if (read_length != 5)
289 		return -EINVAL;
290 
291 	if (check_and_parse_tt_input_report(in, &length, &command)
292 			|| command != COMMAND_RESUME_SCANNING
293 			|| length != 5)
294 		return -EINVAL;
295 
296 	return 0;
297 }
298 
cyttsp5_user_command_async_cont(const char * core_name,u16 read_len,u8 * read_buf,u16 write_len,u8 * write_buf,u16 actual_read_length,int rc)299 void cyttsp5_user_command_async_cont(const char *core_name,
300 		u16 read_len, u8 *read_buf, u16 write_len, u8 *write_buf,
301 		u16 actual_read_length, int rc)
302 {
303 	if (rc) {
304 		pr_err("%s: suspend scan fails\n", __func__);
305 		goto exit;
306 	}
307 
308 	rc = check_suspend_scanning_response(read_buf, actual_read_length);
309 	if (rc) {
310 		pr_err("%s: check suspend scanning response fails\n", __func__);
311 		goto exit;
312 	}
313 
314 	pr_info("%s: suspend scanning succeeds\n", __func__);
315 exit:
316 	return;
317 }
318 
319 /* Read and write buffers */
320 static u8 write_buf[BUFFER_SIZE];
321 static u8 read_buf[BUFFER_SIZE];
322 
323 static uint active_distance;
324 module_param(active_distance, uint, 0);
325 
cyttsp5_test_device_access_api_init(void)326 static int __init cyttsp5_test_device_access_api_init(void)
327 {
328 	u32 initial_active_distance;
329 	u16 actual_read_len;
330 	int write_len;
331 	int rc;
332 
333 	pr_info("%s: Enter\n", __func__);
334 
335 	/* CASE	1: Run get system information */
336 	write_len = prepare_get_system_info_report(write_buf);
337 
338 	rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
339 			read_buf, write_len, write_buf,
340 			&actual_read_len);
341 	if (rc)
342 		goto exit;
343 
344 	rc = check_get_system_info_response(read_buf, actual_read_len);
345 	if (rc)
346 		goto exit;
347 
348 	/* CASE 2: Run get parameter (Active distance) */
349 	write_len = prepare_get_parameter_report(write_buf,
350 			PARAMETER_ACTIVE_DISTANCE_2);
351 
352 	rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
353 			read_buf, write_len, write_buf,
354 			&actual_read_len);
355 	if (rc)
356 		goto exit;
357 
358 	rc = check_get_parameter_response(read_buf, actual_read_len,
359 			&initial_active_distance);
360 	if (rc)
361 		goto exit;
362 
363 	pr_info("%s: Initial Active Distance: %d\n",
364 		__func__, initial_active_distance);
365 
366 	/* CASE	3: Run set parameter (Active distance) */
367 	write_len = prepare_set_parameter_report(write_buf,
368 			PARAMETER_ACTIVE_DISTANCE_2, 1,
369 			active_distance);
370 
371 	rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
372 			read_buf, write_len, write_buf,
373 			&actual_read_len);
374 	if (rc)
375 		goto exit;
376 
377 	rc = check_set_parameter_response(read_buf, actual_read_len);
378 	if (rc)
379 		goto exit;
380 
381 	pr_info("%s: Active Distance set to %d\n", __func__, active_distance);
382 
383 	/* CASE	4: Run get parameter (Active distance) */
384 	write_len = prepare_get_parameter_report(write_buf,
385 			PARAMETER_ACTIVE_DISTANCE_2);
386 
387 	rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
388 			read_buf, write_len, write_buf,
389 			&actual_read_len);
390 	if (rc)
391 		goto exit;
392 
393 	rc = check_get_parameter_response(read_buf, actual_read_len,
394 			&active_distance);
395 	if (rc)
396 		goto exit;
397 
398 	pr_info("%s: New Active Distance: %d\n", __func__, active_distance);
399 
400 	/* CASE 5: Run suspend scanning asynchronously */
401 	write_len = prepare_suspend_scanning_report(write_buf);
402 
403 	preempt_disable();
404 	rc = cyttsp5_device_access_user_command_async(NULL,
405 			sizeof(read_buf), read_buf, write_len, write_buf,
406 			cyttsp5_user_command_async_cont);
407 	preempt_enable();
408 	if (rc)
409 		goto exit;
410 exit:
411 	return rc;
412 }
413 module_init(cyttsp5_test_device_access_api_init);
414 
cyttsp5_test_device_access_api_exit(void)415 static void __exit cyttsp5_test_device_access_api_exit(void)
416 {
417 	u16 actual_read_len;
418 	int write_len;
419 	int rc;
420 
421 	/* CASE 6: Run resume scanning */
422 	write_len = prepare_resume_scanning_report(write_buf);
423 
424 	rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
425 			read_buf, write_len, write_buf,
426 			&actual_read_len);
427 	if (rc)
428 		goto exit;
429 
430 	rc = check_resume_scanning_response(read_buf, actual_read_len);
431 	if (rc)
432 		goto exit;
433 
434 	pr_info("%s: resume scanning succeeds\n", __func__);
435 exit:
436 	return;
437 }
438 module_exit(cyttsp5_test_device_access_api_exit);
439 
440 MODULE_LICENSE("GPL");
441 MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Device Access Driver API Tester");
442 MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
443