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