20 #include <linux/hid.h>
29 #include <linux/module.h>
35 static int picolcd_debug_reset_show(
struct seq_file *
f,
void *
p)
44 static int picolcd_debug_reset_open(
struct inode *
inode,
struct file *f)
49 static ssize_t picolcd_debug_reset_write(
struct file *f,
const char __user *user_buf,
50 size_t count, loff_t *ppos)
54 size_t cnt =
min(count,
sizeof(buf)-1);
58 while (cnt > 0 && (buf[cnt-1] ==
' ' || buf[cnt-1] ==
'\n'))
61 if (
strcmp(buf,
"all") == 0) {
64 }
else if (
strcmp(buf,
"fb") == 0) {
74 .open = picolcd_debug_reset_open,
77 .write = picolcd_debug_reset_write,
84 static ssize_t picolcd_debug_eeprom_read(
struct file *f,
char __user *
u,
85 size_t s, loff_t *off)
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;
123 static ssize_t picolcd_debug_eeprom_write(
struct file *f,
const char __user *u,
124 size_t s, loff_t *off)
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;
172 .read = picolcd_debug_eeprom_read,
173 .write = picolcd_debug_eeprom_write,
181 static int _picolcd_flash_setaddr(
struct picolcd_data *data,
u8 *buf,
long off)
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;
192 char __user *u,
size_t s, loff_t *off)
201 len_off = _picolcd_flash_setaddr(data, raw_data, *off);
202 raw_data[len_off] = s > 32 ? 32 :
s;
214 *off += raw_data[len_off];
215 s -= raw_data[len_off];
216 ret += raw_data[len_off];
222 return ret > 0 ? ret :
err;
227 static ssize_t picolcd_debug_flash_read(
struct file *f,
char __user *u,
228 size_t s, loff_t *off)
236 if (*off + s > 0x05fff)
257 len_off = _picolcd_flash_setaddr(data, raw_data, *off);
274 const char __user *u,
size_t s, loff_t *off)
279 int len_off, err = -
EIO;
283 len_off = _picolcd_flash_setaddr(data, raw_data, *off);
284 raw_data[len_off] = s > 32 ? 32 :
s;
290 len_off+1+raw_data[len_off]);
295 if (
memcmp(raw_data, resp->
raw_data, len_off+1+raw_data[len_off]) != 0)
297 *off += raw_data[len_off];
298 s -= raw_data[len_off];
299 ret += raw_data[len_off];
307 return ret > 0 ? ret :
err;
310 static ssize_t picolcd_debug_flash_write(
struct file *f,
const char __user *u,
311 size_t s, loff_t *off)
315 int report_erase, report_write;
335 err = _picolcd_flash_erase64(data, report_erase, off);
338 err = _picolcd_flash_write(data, report_write, u, 64, off);
348 return ret > 0 ? ret :
err;
365 .read = picolcd_debug_flash_read,
366 .write = picolcd_debug_flash_write,
374 static 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",
380 static void dump_buff_as_hex(
char *
dst,
size_t dst_sz,
const u8 *data,
384 for (i = j = 0; i < data_len && j + 4 < dst_sz; i++) {
385 dst[j++] =
hex_asc[(data[
i] >> 4) & 0x0f];
392 if (i < data_len && j > 2)
393 dst[j-2] = dst[j-3] =
'.';
400 int raw_size = (report->
size >> 3) + 1;
413 report->
id, raw_size);
415 if (raw_size + 5 >
sizeof(raw_data)) {
420 raw_data[0] = report->
id;
422 dump_buff_as_hex(buff,
BUFF_SZ, raw_data, raw_size);
426 switch (report->
id) {
430 "REPORT_LED_STATE", report->
id, raw_size-1);
438 "REPORT_BRIGHTNESS", report->
id, raw_size-1);
446 "REPORT_CONTRAST", report->
id, raw_size-1);
454 "REPORT_RESET", report->
id, raw_size-1);
457 raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]);
463 "REPORT_LCD_CMD", report->
id, raw_size-1);
470 "REPORT_LCD_CMD", report->
id, raw_size-1);
477 "REPORT_LCD_CMD", report->
id, raw_size-1);
484 "REPORT_EE_READ", report->
id, raw_size-1);
487 raw_data[2], raw_data[1]);
495 "REPORT_EE_WRITE", report->
id, raw_size-1);
498 raw_data[2], raw_data[1]);
502 if (raw_data[3] == 0) {
504 }
else if (raw_data[3] + 4 <= raw_size) {
507 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+4, raw_data[3]);
517 "REPORT_ERASE_MEMORY", report->
id, raw_size-1);
519 switch (data->addr_sz) {
521 snprintf(buff,
BUFF_SZ,
"\tAddress inside 64 byte block: 0x%02x%02x\n",
522 raw_data[2], raw_data[1]);
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]);
537 "REPORT_READ_MEMORY", report->
id, raw_size-1);
539 switch (data->addr_sz) {
542 raw_data[2], raw_data[1]);
548 raw_data[3], raw_data[2], raw_data[1]);
561 "REPORT_WRITE_MEMORY", report->
id, raw_size-1);
563 switch (data->addr_sz) {
566 raw_data[2], raw_data[1]);
570 if (raw_data[3] == 0) {
572 }
else if (raw_data[3] + 4 <= raw_size) {
575 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+4, raw_data[3]);
582 raw_data[3], raw_data[2], raw_data[1]);
586 if (raw_data[4] == 0) {
588 }
else if (raw_data[4] + 5 <= raw_size) {
591 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+5, raw_data[4]);
606 "REPORT_EXIT_KEYBOARD", report->
id, raw_size-1);
609 raw_data[1] | (raw_data[2] << 8),
610 raw_data[2], raw_data[1]);
615 "REPORT_VERSION", report->
id, raw_size-1);
620 "REPORT_DEVID", report->
id, raw_size-1);
625 "REPORT_SPLASH_SIZE", report->
id, raw_size-1);
630 "REPORT_HOOK_VERSION", report->
id, raw_size-1);
635 "REPORT_VERSION", report->
id, raw_size-1);
638 raw_data[1] | (raw_data[2] << 8),
639 raw_data[2], raw_data[1]);
644 "<unknown>", report->
id, raw_size-1);
667 switch (report->
id) {
671 "REPORT_ERROR_CODE", report->
id, size-1);
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]);
677 snprintf(buff,
BUFF_SZ,
"\tError code 0x%02x in reply to report 0x%02x\n",
678 raw_data[2], raw_data[1]);
684 "REPORT_KEY_STATE", report->
id, size-1);
686 if (raw_data[1] == 0)
688 else if (raw_data[2] == 0)
690 raw_data[1], raw_data[1]);
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]);
699 "REPORT_IR_DATA", report->
id, size-1);
701 if (raw_data[1] == 0) {
704 }
else if (raw_data[1] + 1 <= size) {
708 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+2, raw_data[1]);
719 "REPORT_EE_DATA", report->
id, size-1);
722 raw_data[2], raw_data[1]);
726 if (raw_data[3] == 0) {
729 }
else if (raw_data[3] + 4 <= size) {
732 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+4, raw_data[3]);
742 "REPORT_MEMORY", report->
id, size-1);
744 switch (data->addr_sz) {
747 raw_data[2], raw_data[1]);
751 if (raw_data[3] == 0) {
753 }
else if (raw_data[3] + 4 <= size) {
756 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+4, raw_data[3]);
763 raw_data[3], raw_data[2], raw_data[1]);
767 if (raw_data[4] == 0) {
769 }
else if (raw_data[4] + 5 <= size) {
772 dump_buff_as_hex(buff,
BUFF_SZ, raw_data+5, raw_data[4]);
784 "REPORT_VERSION", report->
id, size-1);
787 raw_data[2], raw_data[1]);
792 "REPORT_BL_ERASE_MEMORY", report->
id, size-1);
798 "REPORT_BL_READ_MEMORY", report->
id, size-1);
804 "REPORT_BL_WRITE_MEMORY", report->
id, size-1);
810 "REPORT_DEVID", report->
id, size-1);
813 raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
821 "REPORT_SPLASH_SIZE", report->
id, size-1);
824 (raw_data[2] << 8) | raw_data[1]);
827 (raw_data[4] << 8) | raw_data[3]);
832 "REPORT_HOOK_VERSION", report->
id, size-1);
835 raw_data[1], raw_data[2]);
840 "<unknown>", report->
id, size-1);
860 hdev->
debug_dir, data, &picolcd_debug_reset_fops);
863 if (eeprom_r || eeprom_w)
866 hdev->
debug_dir, data, &picolcd_debug_eeprom_fops);
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;
873 if (data->addr_sz == 2 || data->addr_sz == 3) {
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");
885 dent = data->debug_reset;
886 data->debug_reset =
NULL;
889 dent = data->debug_eeprom;
890 data->debug_eeprom =
NULL;
893 dent = data->debug_flash;
894 data->debug_flash =
NULL;