xref: /linux/drivers/hid/hid-picolcd_debugfs.c (revision 69050f8d6d075dc01af7a5f2f550a8067510366f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /***************************************************************************
3  *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
4  *                                                                         *
5  *   Based on Logitech G13 driver (v0.4)                                   *
6  *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
7  *                                                                         *
8  ***************************************************************************/
9 
10 #include <linux/hid.h>
11 #include <linux/hid-debug.h>
12 
13 #include <linux/fb.h>
14 #include <linux/hex.h>
15 #include <linux/seq_file.h>
16 #include <linux/debugfs.h>
17 
18 #include <linux/module.h>
19 #include <linux/uaccess.h>
20 
21 #include "hid-picolcd.h"
22 
23 
24 static int picolcd_debug_reset_show(struct seq_file *f, void *p)
25 {
26 	if (picolcd_fbinfo((struct picolcd_data *)f->private))
27 		seq_printf(f, "all fb\n");
28 	else
29 		seq_printf(f, "all\n");
30 	return 0;
31 }
32 
33 static int picolcd_debug_reset_open(struct inode *inode, struct file *f)
34 {
35 	return single_open(f, picolcd_debug_reset_show, inode->i_private);
36 }
37 
38 static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf,
39 		size_t count, loff_t *ppos)
40 {
41 	struct picolcd_data *data = ((struct seq_file *)f->private_data)->private;
42 	char buf[32];
43 	size_t cnt = min(count, sizeof(buf)-1);
44 	if (copy_from_user(buf, user_buf, cnt))
45 		return -EFAULT;
46 
47 	while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n'))
48 		cnt--;
49 	buf[cnt] = '\0';
50 	if (strcmp(buf, "all") == 0) {
51 		picolcd_reset(data->hdev);
52 		picolcd_fb_reset(data, 1);
53 	} else if (strcmp(buf, "fb") == 0) {
54 		picolcd_fb_reset(data, 1);
55 	} else {
56 		return -EINVAL;
57 	}
58 	return count;
59 }
60 
61 static const struct file_operations picolcd_debug_reset_fops = {
62 	.owner    = THIS_MODULE,
63 	.open     = picolcd_debug_reset_open,
64 	.read     = seq_read,
65 	.llseek   = seq_lseek,
66 	.write    = picolcd_debug_reset_write,
67 	.release  = single_release,
68 };
69 
70 /*
71  * The "eeprom" file
72  */
73 static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
74 		size_t s, loff_t *off)
75 {
76 	struct picolcd_data *data = f->private_data;
77 	struct picolcd_pending *resp;
78 	u8 raw_data[3];
79 	ssize_t ret = -EIO;
80 
81 	if (s == 0)
82 		return -EINVAL;
83 	if (*off > 0x0ff)
84 		return 0;
85 
86 	/* prepare buffer with info about what we want to read (addr & len) */
87 	raw_data[0] = *off & 0xff;
88 	raw_data[1] = (*off >> 8) & 0xff;
89 	raw_data[2] = s < 20 ? s : 20;
90 	if (*off + raw_data[2] > 0xff)
91 		raw_data[2] = 0x100 - *off;
92 	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data,
93 			sizeof(raw_data));
94 	if (!resp)
95 		return -EIO;
96 
97 	if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
98 		/* successful read :) */
99 		ret = resp->raw_data[2];
100 		if (ret > s)
101 			ret = s;
102 		if (copy_to_user(u, resp->raw_data+3, ret))
103 			ret = -EFAULT;
104 		else
105 			*off += ret;
106 	} /* anything else is some kind of IO error */
107 
108 	kfree(resp);
109 	return ret;
110 }
111 
112 static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
113 		size_t s, loff_t *off)
114 {
115 	struct picolcd_data *data = f->private_data;
116 	struct picolcd_pending *resp;
117 	ssize_t ret = -EIO;
118 	u8 raw_data[23];
119 
120 	if (s == 0)
121 		return -EINVAL;
122 	if (*off > 0x0ff)
123 		return -ENOSPC;
124 
125 	memset(raw_data, 0, sizeof(raw_data));
126 	raw_data[0] = *off & 0xff;
127 	raw_data[1] = (*off >> 8) & 0xff;
128 	raw_data[2] = min_t(size_t, 20, s);
129 	if (*off + raw_data[2] > 0xff)
130 		raw_data[2] = 0x100 - *off;
131 
132 	if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
133 		return -EFAULT;
134 	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
135 			sizeof(raw_data));
136 
137 	if (!resp)
138 		return -EIO;
139 
140 	if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
141 		/* check if written data matches */
142 		if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) {
143 			*off += raw_data[2];
144 			ret = raw_data[2];
145 		}
146 	}
147 	kfree(resp);
148 	return ret;
149 }
150 
151 /*
152  * Notes:
153  * - read/write happens in chunks of at most 20 bytes, it's up to userspace
154  *   to loop in order to get more data.
155  * - on write errors on otherwise correct write request the bytes
156  *   that should have been written are in undefined state.
157  */
158 static const struct file_operations picolcd_debug_eeprom_fops = {
159 	.owner    = THIS_MODULE,
160 	.open     = simple_open,
161 	.read     = picolcd_debug_eeprom_read,
162 	.write    = picolcd_debug_eeprom_write,
163 	.llseek   = generic_file_llseek,
164 };
165 
166 /*
167  * The "flash" file
168  */
169 /* record a flash address to buf (bounds check to be done by caller) */
170 static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
171 {
172 	buf[0] = off & 0xff;
173 	buf[1] = (off >> 8) & 0xff;
174 	if (data->addr_sz == 3)
175 		buf[2] = (off >> 16) & 0xff;
176 	return data->addr_sz == 2 ? 2 : 3;
177 }
178 
179 /* read a given size of data (bounds check to be done by caller) */
180 static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id,
181 		char __user *u, size_t s, loff_t *off)
182 {
183 	struct picolcd_pending *resp;
184 	u8 raw_data[4];
185 	ssize_t ret = 0;
186 	int len_off, err = -EIO;
187 
188 	while (s > 0) {
189 		err = -EIO;
190 		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
191 		raw_data[len_off] = s > 32 ? 32 : s;
192 		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1);
193 		if (!resp || !resp->in_report)
194 			goto skip;
195 		if (resp->in_report->id == REPORT_MEMORY ||
196 			resp->in_report->id == REPORT_BL_READ_MEMORY) {
197 			if (memcmp(raw_data, resp->raw_data, len_off+1) != 0)
198 				goto skip;
199 			if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) {
200 				err = -EFAULT;
201 				goto skip;
202 			}
203 			*off += raw_data[len_off];
204 			s    -= raw_data[len_off];
205 			ret  += raw_data[len_off];
206 			err   = 0;
207 		}
208 skip:
209 		kfree(resp);
210 		if (err)
211 			return ret > 0 ? ret : err;
212 	}
213 	return ret;
214 }
215 
216 static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u,
217 		size_t s, loff_t *off)
218 {
219 	struct picolcd_data *data = f->private_data;
220 
221 	if (s == 0)
222 		return -EINVAL;
223 	if (*off > 0x05fff)
224 		return 0;
225 	if (*off + s > 0x05fff)
226 		s = 0x06000 - *off;
227 
228 	if (data->status & PICOLCD_BOOTLOADER)
229 		return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off);
230 	else
231 		return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off);
232 }
233 
234 /* erase block aligned to 64bytes boundary */
235 static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id,
236 		loff_t *off)
237 {
238 	struct picolcd_pending *resp;
239 	u8 raw_data[3];
240 	int len_off;
241 	ssize_t ret = -EIO;
242 
243 	if (*off & 0x3f)
244 		return -EINVAL;
245 
246 	len_off = _picolcd_flash_setaddr(data, raw_data, *off);
247 	resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off);
248 	if (!resp || !resp->in_report)
249 		goto skip;
250 	if (resp->in_report->id == REPORT_MEMORY ||
251 		resp->in_report->id == REPORT_BL_ERASE_MEMORY) {
252 		if (memcmp(raw_data, resp->raw_data, len_off) != 0)
253 			goto skip;
254 		ret = 0;
255 	}
256 skip:
257 	kfree(resp);
258 	return ret;
259 }
260 
261 /* write a given size of data (bounds check to be done by caller) */
262 static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id,
263 		const char __user *u, size_t s, loff_t *off)
264 {
265 	struct picolcd_pending *resp;
266 	u8 raw_data[36];
267 	ssize_t ret = 0;
268 	int len_off, err = -EIO;
269 
270 	while (s > 0) {
271 		err = -EIO;
272 		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
273 		raw_data[len_off] = s > 32 ? 32 : s;
274 		if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) {
275 			err = -EFAULT;
276 			break;
277 		}
278 		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data,
279 				len_off+1+raw_data[len_off]);
280 		if (!resp || !resp->in_report)
281 			goto skip;
282 		if (resp->in_report->id == REPORT_MEMORY ||
283 			resp->in_report->id == REPORT_BL_WRITE_MEMORY) {
284 			if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0)
285 				goto skip;
286 			*off += raw_data[len_off];
287 			s    -= raw_data[len_off];
288 			ret  += raw_data[len_off];
289 			err   = 0;
290 		}
291 skip:
292 		kfree(resp);
293 		if (err)
294 			break;
295 	}
296 	return ret > 0 ? ret : err;
297 }
298 
299 static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u,
300 		size_t s, loff_t *off)
301 {
302 	struct picolcd_data *data = f->private_data;
303 	ssize_t err, ret = 0;
304 	int report_erase, report_write;
305 
306 	if (s == 0)
307 		return -EINVAL;
308 	if (*off > 0x5fff)
309 		return -ENOSPC;
310 	if (s & 0x3f)
311 		return -EINVAL;
312 	if (*off & 0x3f)
313 		return -EINVAL;
314 
315 	if (data->status & PICOLCD_BOOTLOADER) {
316 		report_erase = REPORT_BL_ERASE_MEMORY;
317 		report_write = REPORT_BL_WRITE_MEMORY;
318 	} else {
319 		report_erase = REPORT_ERASE_MEMORY;
320 		report_write = REPORT_WRITE_MEMORY;
321 	}
322 	mutex_lock(&data->mutex_flash);
323 	while (s > 0) {
324 		err = _picolcd_flash_erase64(data, report_erase, off);
325 		if (err)
326 			break;
327 		err = _picolcd_flash_write(data, report_write, u, 64, off);
328 		if (err < 0)
329 			break;
330 		ret += err;
331 		*off += err;
332 		s -= err;
333 		if (err != 64)
334 			break;
335 	}
336 	mutex_unlock(&data->mutex_flash);
337 	return ret > 0 ? ret : err;
338 }
339 
340 /*
341  * Notes:
342  * - concurrent writing is prevented by mutex and all writes must be
343  *   n*64 bytes and 64-byte aligned, each write being preceded by an
344  *   ERASE which erases a 64byte block.
345  *   If less than requested was written or an error is returned for an
346  *   otherwise correct write request the next 64-byte block which should
347  *   have been written is in undefined state (mostly: original, erased,
348  *   (half-)written with write error)
349  * - reading can happen without special restriction
350  */
351 static const struct file_operations picolcd_debug_flash_fops = {
352 	.owner    = THIS_MODULE,
353 	.open     = simple_open,
354 	.read     = picolcd_debug_flash_read,
355 	.write    = picolcd_debug_flash_write,
356 	.llseek   = generic_file_llseek,
357 };
358 
359 
360 /*
361  * Helper code for HID report level dumping/debugging
362  */
363 static const char * const error_codes[] = {
364 	"success", "parameter missing", "data_missing", "block readonly",
365 	"block not erasable", "block too big", "section overflow",
366 	"invalid command length", "invalid data length",
367 };
368 
369 static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
370 		const size_t data_len)
371 {
372 	int i, j;
373 	for (i = j = 0; i < data_len && j + 4 < dst_sz; i++) {
374 		dst[j++] = hex_asc[(data[i] >> 4) & 0x0f];
375 		dst[j++] = hex_asc[data[i] & 0x0f];
376 		dst[j++] = ' ';
377 	}
378 	dst[j]   = '\0';
379 	if (j > 0)
380 		dst[j-1] = '\n';
381 	if (i < data_len && j > 2)
382 		dst[j-2] = dst[j-3] = '.';
383 }
384 
385 void picolcd_debug_out_report(struct picolcd_data *data,
386 		struct hid_device *hdev, struct hid_report *report)
387 {
388 	u8 *raw_data;
389 	int raw_size = (report->size >> 3) + 1;
390 	char *buff;
391 #define BUFF_SZ 256
392 
393 	/* Avoid unnecessary overhead if debugfs is disabled */
394 	if (list_empty(&hdev->debug_list))
395 		return;
396 
397 	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
398 	if (!buff)
399 		return;
400 
401 	raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
402 	if (!raw_data) {
403 		kfree(buff);
404 		return;
405 	}
406 
407 	snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
408 			report->id, raw_size);
409 	hid_debug_event(hdev, buff);
410 	raw_data[0] = report->id;
411 	hid_output_report(report, raw_data);
412 	dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
413 	hid_debug_event(hdev, buff);
414 
415 	switch (report->id) {
416 	case REPORT_LED_STATE:
417 		/* 1 data byte with GPO state */
418 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
419 			"REPORT_LED_STATE", report->id, raw_size-1);
420 		hid_debug_event(hdev, buff);
421 		snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]);
422 		hid_debug_event(hdev, buff);
423 		break;
424 	case REPORT_BRIGHTNESS:
425 		/* 1 data byte with brightness */
426 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
427 			"REPORT_BRIGHTNESS", report->id, raw_size-1);
428 		hid_debug_event(hdev, buff);
429 		snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]);
430 		hid_debug_event(hdev, buff);
431 		break;
432 	case REPORT_CONTRAST:
433 		/* 1 data byte with contrast */
434 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
435 			"REPORT_CONTRAST", report->id, raw_size-1);
436 		hid_debug_event(hdev, buff);
437 		snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]);
438 		hid_debug_event(hdev, buff);
439 		break;
440 	case REPORT_RESET:
441 		/* 2 data bytes with reset duration in ms */
442 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
443 			"REPORT_RESET", report->id, raw_size-1);
444 		hid_debug_event(hdev, buff);
445 		snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n",
446 				raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]);
447 		hid_debug_event(hdev, buff);
448 		break;
449 	case REPORT_LCD_CMD:
450 		/* 63 data bytes with LCD commands */
451 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
452 			"REPORT_LCD_CMD", report->id, raw_size-1);
453 		hid_debug_event(hdev, buff);
454 		/* TODO: format decoding */
455 		break;
456 	case REPORT_LCD_DATA:
457 		/* 63 data bytes with LCD data */
458 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
459 			"REPORT_LCD_CMD", report->id, raw_size-1);
460 		/* TODO: format decoding */
461 		hid_debug_event(hdev, buff);
462 		break;
463 	case REPORT_LCD_CMD_DATA:
464 		/* 63 data bytes with LCD commands and data */
465 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
466 			"REPORT_LCD_CMD", report->id, raw_size-1);
467 		/* TODO: format decoding */
468 		hid_debug_event(hdev, buff);
469 		break;
470 	case REPORT_EE_READ:
471 		/* 3 data bytes with read area description */
472 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
473 			"REPORT_EE_READ", report->id, raw_size-1);
474 		hid_debug_event(hdev, buff);
475 		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
476 				raw_data[2], raw_data[1]);
477 		hid_debug_event(hdev, buff);
478 		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
479 		hid_debug_event(hdev, buff);
480 		break;
481 	case REPORT_EE_WRITE:
482 		/* 3+1..20 data bytes with write area description */
483 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
484 			"REPORT_EE_WRITE", report->id, raw_size-1);
485 		hid_debug_event(hdev, buff);
486 		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
487 				raw_data[2], raw_data[1]);
488 		hid_debug_event(hdev, buff);
489 		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
490 		hid_debug_event(hdev, buff);
491 		if (raw_data[3] == 0) {
492 			snprintf(buff, BUFF_SZ, "\tNo data\n");
493 		} else if (raw_data[3] + 4 <= raw_size) {
494 			snprintf(buff, BUFF_SZ, "\tData: ");
495 			hid_debug_event(hdev, buff);
496 			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
497 		} else {
498 			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
499 		}
500 		hid_debug_event(hdev, buff);
501 		break;
502 	case REPORT_ERASE_MEMORY:
503 	case REPORT_BL_ERASE_MEMORY:
504 		/* 3 data bytes with pointer inside erase block */
505 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
506 			"REPORT_ERASE_MEMORY", report->id, raw_size-1);
507 		hid_debug_event(hdev, buff);
508 		switch (data->addr_sz) {
509 		case 2:
510 			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n",
511 					raw_data[2], raw_data[1]);
512 			break;
513 		case 3:
514 			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n",
515 					raw_data[3], raw_data[2], raw_data[1]);
516 			break;
517 		default:
518 			snprintf(buff, BUFF_SZ, "\tNot supported\n");
519 		}
520 		hid_debug_event(hdev, buff);
521 		break;
522 	case REPORT_READ_MEMORY:
523 	case REPORT_BL_READ_MEMORY:
524 		/* 4 data bytes with read area description */
525 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
526 			"REPORT_READ_MEMORY", report->id, raw_size-1);
527 		hid_debug_event(hdev, buff);
528 		switch (data->addr_sz) {
529 		case 2:
530 			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
531 					raw_data[2], raw_data[1]);
532 			hid_debug_event(hdev, buff);
533 			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
534 			break;
535 		case 3:
536 			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
537 					raw_data[3], raw_data[2], raw_data[1]);
538 			hid_debug_event(hdev, buff);
539 			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
540 			break;
541 		default:
542 			snprintf(buff, BUFF_SZ, "\tNot supported\n");
543 		}
544 		hid_debug_event(hdev, buff);
545 		break;
546 	case REPORT_WRITE_MEMORY:
547 	case REPORT_BL_WRITE_MEMORY:
548 		/* 4+1..32 data bytes with write adrea description */
549 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
550 			"REPORT_WRITE_MEMORY", report->id, raw_size-1);
551 		hid_debug_event(hdev, buff);
552 		switch (data->addr_sz) {
553 		case 2:
554 			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
555 					raw_data[2], raw_data[1]);
556 			hid_debug_event(hdev, buff);
557 			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
558 			hid_debug_event(hdev, buff);
559 			if (raw_data[3] == 0) {
560 				snprintf(buff, BUFF_SZ, "\tNo data\n");
561 			} else if (raw_data[3] + 4 <= raw_size) {
562 				snprintf(buff, BUFF_SZ, "\tData: ");
563 				hid_debug_event(hdev, buff);
564 				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
565 			} else {
566 				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
567 			}
568 			break;
569 		case 3:
570 			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
571 					raw_data[3], raw_data[2], raw_data[1]);
572 			hid_debug_event(hdev, buff);
573 			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
574 			hid_debug_event(hdev, buff);
575 			if (raw_data[4] == 0) {
576 				snprintf(buff, BUFF_SZ, "\tNo data\n");
577 			} else if (raw_data[4] + 5 <= raw_size) {
578 				snprintf(buff, BUFF_SZ, "\tData: ");
579 				hid_debug_event(hdev, buff);
580 				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
581 			} else {
582 				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
583 			}
584 			break;
585 		default:
586 			snprintf(buff, BUFF_SZ, "\tNot supported\n");
587 		}
588 		hid_debug_event(hdev, buff);
589 		break;
590 	case REPORT_SPLASH_RESTART:
591 		/* TODO */
592 		break;
593 	case REPORT_EXIT_KEYBOARD:
594 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
595 			"REPORT_EXIT_KEYBOARD", report->id, raw_size-1);
596 		hid_debug_event(hdev, buff);
597 		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
598 				raw_data[1] | (raw_data[2] << 8),
599 				raw_data[2], raw_data[1]);
600 		hid_debug_event(hdev, buff);
601 		break;
602 	case REPORT_VERSION:
603 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
604 			"REPORT_VERSION", report->id, raw_size-1);
605 		hid_debug_event(hdev, buff);
606 		break;
607 	case REPORT_DEVID:
608 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
609 			"REPORT_DEVID", report->id, raw_size-1);
610 		hid_debug_event(hdev, buff);
611 		break;
612 	case REPORT_SPLASH_SIZE:
613 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
614 			"REPORT_SPLASH_SIZE", report->id, raw_size-1);
615 		hid_debug_event(hdev, buff);
616 		break;
617 	case REPORT_HOOK_VERSION:
618 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
619 			"REPORT_HOOK_VERSION", report->id, raw_size-1);
620 		hid_debug_event(hdev, buff);
621 		break;
622 	case REPORT_EXIT_FLASHER:
623 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
624 			"REPORT_VERSION", report->id, raw_size-1);
625 		hid_debug_event(hdev, buff);
626 		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
627 				raw_data[1] | (raw_data[2] << 8),
628 				raw_data[2], raw_data[1]);
629 		hid_debug_event(hdev, buff);
630 		break;
631 	default:
632 		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
633 			"<unknown>", report->id, raw_size-1);
634 		hid_debug_event(hdev, buff);
635 		break;
636 	}
637 	wake_up_interruptible(&hdev->debug_wait);
638 	kfree(raw_data);
639 	kfree(buff);
640 }
641 
642 void picolcd_debug_raw_event(struct picolcd_data *data,
643 		struct hid_device *hdev, struct hid_report *report,
644 		u8 *raw_data, int size)
645 {
646 	char *buff;
647 
648 #define BUFF_SZ 256
649 	/* Avoid unnecessary overhead if debugfs is disabled */
650 	if (list_empty(&hdev->debug_list))
651 		return;
652 
653 	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
654 	if (!buff)
655 		return;
656 
657 	switch (report->id) {
658 	case REPORT_ERROR_CODE:
659 		/* 2 data bytes with affected report and error code */
660 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
661 			"REPORT_ERROR_CODE", report->id, size-1);
662 		hid_debug_event(hdev, buff);
663 		if (raw_data[2] < ARRAY_SIZE(error_codes))
664 			snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n",
665 					raw_data[2], error_codes[raw_data[2]], raw_data[1]);
666 		else
667 			snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n",
668 					raw_data[2], raw_data[1]);
669 		hid_debug_event(hdev, buff);
670 		break;
671 	case REPORT_KEY_STATE:
672 		/* 2 data bytes with key state */
673 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
674 			"REPORT_KEY_STATE", report->id, size-1);
675 		hid_debug_event(hdev, buff);
676 		if (raw_data[1] == 0)
677 			snprintf(buff, BUFF_SZ, "\tNo key pressed\n");
678 		else if (raw_data[2] == 0)
679 			snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n",
680 					raw_data[1], raw_data[1]);
681 		else
682 			snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n",
683 					raw_data[1], raw_data[1], raw_data[2], raw_data[2]);
684 		hid_debug_event(hdev, buff);
685 		break;
686 	case REPORT_IR_DATA:
687 		/* Up to 20 byes of IR scancode data */
688 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
689 			"REPORT_IR_DATA", report->id, size-1);
690 		hid_debug_event(hdev, buff);
691 		if (raw_data[1] == 0) {
692 			snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n");
693 			hid_debug_event(hdev, buff);
694 		} else if (raw_data[1] + 1 <= size) {
695 			snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ",
696 					raw_data[1]);
697 			hid_debug_event(hdev, buff);
698 			dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]);
699 			hid_debug_event(hdev, buff);
700 		} else {
701 			snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n",
702 					raw_data[1]-1);
703 			hid_debug_event(hdev, buff);
704 		}
705 		break;
706 	case REPORT_EE_DATA:
707 		/* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */
708 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
709 			"REPORT_EE_DATA", report->id, size-1);
710 		hid_debug_event(hdev, buff);
711 		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
712 				raw_data[2], raw_data[1]);
713 		hid_debug_event(hdev, buff);
714 		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
715 		hid_debug_event(hdev, buff);
716 		if (raw_data[3] == 0) {
717 			snprintf(buff, BUFF_SZ, "\tNo data\n");
718 			hid_debug_event(hdev, buff);
719 		} else if (raw_data[3] + 4 <= size) {
720 			snprintf(buff, BUFF_SZ, "\tData: ");
721 			hid_debug_event(hdev, buff);
722 			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
723 			hid_debug_event(hdev, buff);
724 		} else {
725 			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
726 			hid_debug_event(hdev, buff);
727 		}
728 		break;
729 	case REPORT_MEMORY:
730 		/* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRITE_MEMORY */
731 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
732 			"REPORT_MEMORY", report->id, size-1);
733 		hid_debug_event(hdev, buff);
734 		switch (data->addr_sz) {
735 		case 2:
736 			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
737 					raw_data[2], raw_data[1]);
738 			hid_debug_event(hdev, buff);
739 			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
740 			hid_debug_event(hdev, buff);
741 			if (raw_data[3] == 0) {
742 				snprintf(buff, BUFF_SZ, "\tNo data\n");
743 			} else if (raw_data[3] + 4 <= size) {
744 				snprintf(buff, BUFF_SZ, "\tData: ");
745 				hid_debug_event(hdev, buff);
746 				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
747 			} else {
748 				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
749 			}
750 			break;
751 		case 3:
752 			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
753 					raw_data[3], raw_data[2], raw_data[1]);
754 			hid_debug_event(hdev, buff);
755 			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
756 			hid_debug_event(hdev, buff);
757 			if (raw_data[4] == 0) {
758 				snprintf(buff, BUFF_SZ, "\tNo data\n");
759 			} else if (raw_data[4] + 5 <= size) {
760 				snprintf(buff, BUFF_SZ, "\tData: ");
761 				hid_debug_event(hdev, buff);
762 				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
763 			} else {
764 				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
765 			}
766 			break;
767 		default:
768 			snprintf(buff, BUFF_SZ, "\tNot supported\n");
769 		}
770 		hid_debug_event(hdev, buff);
771 		break;
772 	case REPORT_VERSION:
773 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
774 			"REPORT_VERSION", report->id, size-1);
775 		hid_debug_event(hdev, buff);
776 		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
777 				raw_data[2], raw_data[1]);
778 		hid_debug_event(hdev, buff);
779 		break;
780 	case REPORT_BL_ERASE_MEMORY:
781 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
782 			"REPORT_BL_ERASE_MEMORY", report->id, size-1);
783 		hid_debug_event(hdev, buff);
784 		/* TODO */
785 		break;
786 	case REPORT_BL_READ_MEMORY:
787 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
788 			"REPORT_BL_READ_MEMORY", report->id, size-1);
789 		hid_debug_event(hdev, buff);
790 		/* TODO */
791 		break;
792 	case REPORT_BL_WRITE_MEMORY:
793 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
794 			"REPORT_BL_WRITE_MEMORY", report->id, size-1);
795 		hid_debug_event(hdev, buff);
796 		/* TODO */
797 		break;
798 	case REPORT_DEVID:
799 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
800 			"REPORT_DEVID", report->id, size-1);
801 		hid_debug_event(hdev, buff);
802 		snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n",
803 				raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
804 		hid_debug_event(hdev, buff);
805 		snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n",
806 				raw_data[5]);
807 		hid_debug_event(hdev, buff);
808 		break;
809 	case REPORT_SPLASH_SIZE:
810 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
811 			"REPORT_SPLASH_SIZE", report->id, size-1);
812 		hid_debug_event(hdev, buff);
813 		snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n",
814 				(raw_data[2] << 8) | raw_data[1]);
815 		hid_debug_event(hdev, buff);
816 		snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n",
817 				(raw_data[4] << 8) | raw_data[3]);
818 		hid_debug_event(hdev, buff);
819 		break;
820 	case REPORT_HOOK_VERSION:
821 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
822 			"REPORT_HOOK_VERSION", report->id, size-1);
823 		hid_debug_event(hdev, buff);
824 		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
825 				raw_data[1], raw_data[2]);
826 		hid_debug_event(hdev, buff);
827 		break;
828 	default:
829 		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
830 			"<unknown>", report->id, size-1);
831 		hid_debug_event(hdev, buff);
832 		break;
833 	}
834 	wake_up_interruptible(&hdev->debug_wait);
835 	kfree(buff);
836 }
837 
838 void picolcd_init_devfs(struct picolcd_data *data,
839 		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
840 		struct hid_report *flash_r, struct hid_report *flash_w,
841 		struct hid_report *reset)
842 {
843 	struct hid_device *hdev = data->hdev;
844 
845 	mutex_init(&data->mutex_flash);
846 
847 	/* reset */
848 	if (reset)
849 		data->debug_reset = debugfs_create_file("reset", 0600,
850 				hdev->debug_dir, data, &picolcd_debug_reset_fops);
851 
852 	/* eeprom */
853 	if (eeprom_r || eeprom_w)
854 		data->debug_eeprom = debugfs_create_file("eeprom",
855 			(eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0),
856 			hdev->debug_dir, data, &picolcd_debug_eeprom_fops);
857 
858 	/* flash */
859 	if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8)
860 		data->addr_sz = flash_r->field[0]->report_count - 1;
861 	else
862 		data->addr_sz = -1;
863 	if (data->addr_sz == 2 || data->addr_sz == 3) {
864 		data->debug_flash = debugfs_create_file("flash",
865 			(flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
866 			hdev->debug_dir, data, &picolcd_debug_flash_fops);
867 	} else if (flash_r || flash_w)
868 		hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
869 }
870 
871 void picolcd_exit_devfs(struct picolcd_data *data)
872 {
873 	struct dentry *dent;
874 
875 	dent = data->debug_reset;
876 	data->debug_reset = NULL;
877 	debugfs_remove(dent);
878 	dent = data->debug_eeprom;
879 	data->debug_eeprom = NULL;
880 	debugfs_remove(dent);
881 	dent = data->debug_flash;
882 	data->debug_flash = NULL;
883 	debugfs_remove(dent);
884 	mutex_destroy(&data->mutex_flash);
885 }
886 
887