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