blob: 59ab8e157e6b249d025ea26d4bd0ba4b2bb7f227 [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{
397 u8 raw_data[70];
398 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
410 snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ",
411 report->id, raw_size);
412 hid_debug_event(hdev, buff);
413 if (raw_size + 5 > sizeof(raw_data)) {
414 kfree(buff);
415 hid_debug_event(hdev, " TOO BIG\n");
416 return;
417 } else {
418 raw_data[0] = report->id;
419 hid_output_report(report, raw_data);
420 dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
421 hid_debug_event(hdev, buff);
422 }
423
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);
647 kfree(buff);
648}
649
650void picolcd_debug_raw_event(struct picolcd_data *data,
651 struct hid_device *hdev, struct hid_report *report,
652 u8 *raw_data, int size)
653{
654 char *buff;
655
656#define BUFF_SZ 256
657 /* Avoid unnecessary overhead if debugfs is disabled */
Bruno Prémont63583c62012-08-19 19:33:02 +0200658 if (list_empty(&hdev->debug_list))
Bruno Prémontfabdbf22012-07-30 21:38:28 +0200659 return;
660
661 buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
662 if (!buff)
663 return;
664
665 switch (report->id) {
666 case REPORT_ERROR_CODE:
667 /* 2 data bytes with affected report and error code */
668 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
669 "REPORT_ERROR_CODE", report->id, size-1);
670 hid_debug_event(hdev, buff);
671 if (raw_data[2] < ARRAY_SIZE(error_codes))
672 snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n",
673 raw_data[2], error_codes[raw_data[2]], raw_data[1]);
674 else
675 snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n",
676 raw_data[2], raw_data[1]);
677 hid_debug_event(hdev, buff);
678 break;
679 case REPORT_KEY_STATE:
680 /* 2 data bytes with key state */
681 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
682 "REPORT_KEY_STATE", report->id, size-1);
683 hid_debug_event(hdev, buff);
684 if (raw_data[1] == 0)
685 snprintf(buff, BUFF_SZ, "\tNo key pressed\n");
686 else if (raw_data[2] == 0)
687 snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n",
688 raw_data[1], raw_data[1]);
689 else
690 snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n",
691 raw_data[1], raw_data[1], raw_data[2], raw_data[2]);
692 hid_debug_event(hdev, buff);
693 break;
694 case REPORT_IR_DATA:
695 /* Up to 20 byes of IR scancode data */
696 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
697 "REPORT_IR_DATA", report->id, size-1);
698 hid_debug_event(hdev, buff);
699 if (raw_data[1] == 0) {
700 snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n");
701 hid_debug_event(hdev, buff);
702 } else if (raw_data[1] + 1 <= size) {
703 snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ",
Bruno Prémontf2df5b72012-08-19 19:33:33 +0200704 raw_data[1]);
Bruno Prémontfabdbf22012-07-30 21:38:28 +0200705 hid_debug_event(hdev, buff);
Bruno Prémontf2df5b72012-08-19 19:33:33 +0200706 dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]);
Bruno Prémontfabdbf22012-07-30 21:38:28 +0200707 hid_debug_event(hdev, buff);
708 } else {
709 snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n",
710 raw_data[1]-1);
711 hid_debug_event(hdev, buff);
712 }
713 break;
714 case REPORT_EE_DATA:
715 /* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */
716 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
717 "REPORT_EE_DATA", report->id, size-1);
718 hid_debug_event(hdev, buff);
719 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
720 raw_data[2], raw_data[1]);
721 hid_debug_event(hdev, buff);
722 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
723 hid_debug_event(hdev, buff);
724 if (raw_data[3] == 0) {
725 snprintf(buff, BUFF_SZ, "\tNo data\n");
726 hid_debug_event(hdev, buff);
727 } else if (raw_data[3] + 4 <= size) {
728 snprintf(buff, BUFF_SZ, "\tData: ");
729 hid_debug_event(hdev, buff);
730 dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
731 hid_debug_event(hdev, buff);
732 } else {
733 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
734 hid_debug_event(hdev, buff);
735 }
736 break;
737 case REPORT_MEMORY:
738 /* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */
739 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
740 "REPORT_MEMORY", report->id, size-1);
741 hid_debug_event(hdev, buff);
742 switch (data->addr_sz) {
743 case 2:
744 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
745 raw_data[2], raw_data[1]);
746 hid_debug_event(hdev, buff);
747 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
748 hid_debug_event(hdev, buff);
749 if (raw_data[3] == 0) {
750 snprintf(buff, BUFF_SZ, "\tNo data\n");
751 } else if (raw_data[3] + 4 <= size) {
752 snprintf(buff, BUFF_SZ, "\tData: ");
753 hid_debug_event(hdev, buff);
754 dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
755 } else {
756 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
757 }
758 break;
759 case 3:
760 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
761 raw_data[3], raw_data[2], raw_data[1]);
762 hid_debug_event(hdev, buff);
763 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
764 hid_debug_event(hdev, buff);
765 if (raw_data[4] == 0) {
766 snprintf(buff, BUFF_SZ, "\tNo data\n");
767 } else if (raw_data[4] + 5 <= size) {
768 snprintf(buff, BUFF_SZ, "\tData: ");
769 hid_debug_event(hdev, buff);
770 dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
771 } else {
772 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
773 }
774 break;
775 default:
776 snprintf(buff, BUFF_SZ, "\tNot supported\n");
777 }
778 hid_debug_event(hdev, buff);
779 break;
780 case REPORT_VERSION:
781 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
782 "REPORT_VERSION", report->id, size-1);
783 hid_debug_event(hdev, buff);
784 snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
785 raw_data[2], raw_data[1]);
786 hid_debug_event(hdev, buff);
787 break;
788 case REPORT_BL_ERASE_MEMORY:
789 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
790 "REPORT_BL_ERASE_MEMORY", report->id, size-1);
791 hid_debug_event(hdev, buff);
792 /* TODO */
793 break;
794 case REPORT_BL_READ_MEMORY:
795 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
796 "REPORT_BL_READ_MEMORY", report->id, size-1);
797 hid_debug_event(hdev, buff);
798 /* TODO */
799 break;
800 case REPORT_BL_WRITE_MEMORY:
801 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
802 "REPORT_BL_WRITE_MEMORY", report->id, size-1);
803 hid_debug_event(hdev, buff);
804 /* TODO */
805 break;
806 case REPORT_DEVID:
807 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
808 "REPORT_DEVID", report->id, size-1);
809 hid_debug_event(hdev, buff);
810 snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n",
811 raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
812 hid_debug_event(hdev, buff);
813 snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n",
814 raw_data[5]);
815 hid_debug_event(hdev, buff);
816 break;
817 case REPORT_SPLASH_SIZE:
818 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
819 "REPORT_SPLASH_SIZE", report->id, size-1);
820 hid_debug_event(hdev, buff);
821 snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n",
822 (raw_data[2] << 8) | raw_data[1]);
823 hid_debug_event(hdev, buff);
824 snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n",
825 (raw_data[4] << 8) | raw_data[3]);
826 hid_debug_event(hdev, buff);
827 break;
828 case REPORT_HOOK_VERSION:
829 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
830 "REPORT_HOOK_VERSION", report->id, size-1);
831 hid_debug_event(hdev, buff);
832 snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
833 raw_data[1], raw_data[2]);
834 hid_debug_event(hdev, buff);
835 break;
836 default:
837 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
838 "<unknown>", report->id, size-1);
839 hid_debug_event(hdev, buff);
840 break;
841 }
842 wake_up_interruptible(&hdev->debug_wait);
843 kfree(buff);
844}
845
846void picolcd_init_devfs(struct picolcd_data *data,
847 struct hid_report *eeprom_r, struct hid_report *eeprom_w,
848 struct hid_report *flash_r, struct hid_report *flash_w,
849 struct hid_report *reset)
850{
851 struct hid_device *hdev = data->hdev;
852
853 mutex_init(&data->mutex_flash);
854
855 /* reset */
856 if (reset)
857 data->debug_reset = debugfs_create_file("reset", 0600,
858 hdev->debug_dir, data, &picolcd_debug_reset_fops);
859
860 /* eeprom */
861 if (eeprom_r || eeprom_w)
862 data->debug_eeprom = debugfs_create_file("eeprom",
863 (eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0),
864 hdev->debug_dir, data, &picolcd_debug_eeprom_fops);
865
866 /* flash */
867 if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8)
868 data->addr_sz = flash_r->field[0]->report_count - 1;
869 else
870 data->addr_sz = -1;
871 if (data->addr_sz == 2 || data->addr_sz == 3) {
872 data->debug_flash = debugfs_create_file("flash",
873 (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
874 hdev->debug_dir, data, &picolcd_debug_flash_fops);
875 } else if (flash_r || flash_w)
876 hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
877}
878
879void picolcd_exit_devfs(struct picolcd_data *data)
880{
881 struct dentry *dent;
882
883 dent = data->debug_reset;
884 data->debug_reset = NULL;
885 if (dent)
886 debugfs_remove(dent);
887 dent = data->debug_eeprom;
888 data->debug_eeprom = NULL;
889 if (dent)
890 debugfs_remove(dent);
891 dent = data->debug_flash;
892 data->debug_flash = NULL;
893 if (dent)
894 debugfs_remove(dent);
895 mutex_destroy(&data->mutex_flash);
896}
897