0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/hid.h>
0011 #include <linux/hid-debug.h>
0012
0013 #include <linux/fb.h>
0014 #include <linux/seq_file.h>
0015 #include <linux/debugfs.h>
0016
0017 #include <linux/module.h>
0018 #include <linux/uaccess.h>
0019
0020 #include "hid-picolcd.h"
0021
0022
0023 static int picolcd_debug_reset_show(struct seq_file *f, void *p)
0024 {
0025 if (picolcd_fbinfo((struct picolcd_data *)f->private))
0026 seq_printf(f, "all fb\n");
0027 else
0028 seq_printf(f, "all\n");
0029 return 0;
0030 }
0031
0032 static int picolcd_debug_reset_open(struct inode *inode, struct file *f)
0033 {
0034 return single_open(f, picolcd_debug_reset_show, inode->i_private);
0035 }
0036
0037 static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf,
0038 size_t count, loff_t *ppos)
0039 {
0040 struct picolcd_data *data = ((struct seq_file *)f->private_data)->private;
0041 char buf[32];
0042 size_t cnt = min(count, sizeof(buf)-1);
0043 if (copy_from_user(buf, user_buf, cnt))
0044 return -EFAULT;
0045
0046 while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n'))
0047 cnt--;
0048 buf[cnt] = '\0';
0049 if (strcmp(buf, "all") == 0) {
0050 picolcd_reset(data->hdev);
0051 picolcd_fb_reset(data, 1);
0052 } else if (strcmp(buf, "fb") == 0) {
0053 picolcd_fb_reset(data, 1);
0054 } else {
0055 return -EINVAL;
0056 }
0057 return count;
0058 }
0059
0060 static const struct file_operations picolcd_debug_reset_fops = {
0061 .owner = THIS_MODULE,
0062 .open = picolcd_debug_reset_open,
0063 .read = seq_read,
0064 .llseek = seq_lseek,
0065 .write = picolcd_debug_reset_write,
0066 .release = single_release,
0067 };
0068
0069
0070
0071
0072 static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
0073 size_t s, loff_t *off)
0074 {
0075 struct picolcd_data *data = f->private_data;
0076 struct picolcd_pending *resp;
0077 u8 raw_data[3];
0078 ssize_t ret = -EIO;
0079
0080 if (s == 0)
0081 return -EINVAL;
0082 if (*off > 0x0ff)
0083 return 0;
0084
0085
0086 raw_data[0] = *off & 0xff;
0087 raw_data[1] = (*off >> 8) & 0xff;
0088 raw_data[2] = s < 20 ? s : 20;
0089 if (*off + raw_data[2] > 0xff)
0090 raw_data[2] = 0x100 - *off;
0091 resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data,
0092 sizeof(raw_data));
0093 if (!resp)
0094 return -EIO;
0095
0096 if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
0097
0098 ret = resp->raw_data[2];
0099 if (ret > s)
0100 ret = s;
0101 if (copy_to_user(u, resp->raw_data+3, ret))
0102 ret = -EFAULT;
0103 else
0104 *off += ret;
0105 }
0106
0107 kfree(resp);
0108 return ret;
0109 }
0110
0111 static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
0112 size_t s, loff_t *off)
0113 {
0114 struct picolcd_data *data = f->private_data;
0115 struct picolcd_pending *resp;
0116 ssize_t ret = -EIO;
0117 u8 raw_data[23];
0118
0119 if (s == 0)
0120 return -EINVAL;
0121 if (*off > 0x0ff)
0122 return -ENOSPC;
0123
0124 memset(raw_data, 0, sizeof(raw_data));
0125 raw_data[0] = *off & 0xff;
0126 raw_data[1] = (*off >> 8) & 0xff;
0127 raw_data[2] = min_t(size_t, 20, s);
0128 if (*off + raw_data[2] > 0xff)
0129 raw_data[2] = 0x100 - *off;
0130
0131 if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
0132 return -EFAULT;
0133 resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
0134 sizeof(raw_data));
0135
0136 if (!resp)
0137 return -EIO;
0138
0139 if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
0140
0141 if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) {
0142 *off += raw_data[2];
0143 ret = raw_data[2];
0144 }
0145 }
0146 kfree(resp);
0147 return ret;
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157 static const struct file_operations picolcd_debug_eeprom_fops = {
0158 .owner = THIS_MODULE,
0159 .open = simple_open,
0160 .read = picolcd_debug_eeprom_read,
0161 .write = picolcd_debug_eeprom_write,
0162 .llseek = generic_file_llseek,
0163 };
0164
0165
0166
0167
0168
0169 static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
0170 {
0171 buf[0] = off & 0xff;
0172 buf[1] = (off >> 8) & 0xff;
0173 if (data->addr_sz == 3)
0174 buf[2] = (off >> 16) & 0xff;
0175 return data->addr_sz == 2 ? 2 : 3;
0176 }
0177
0178
0179 static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id,
0180 char __user *u, size_t s, loff_t *off)
0181 {
0182 struct picolcd_pending *resp;
0183 u8 raw_data[4];
0184 ssize_t ret = 0;
0185 int len_off, err = -EIO;
0186
0187 while (s > 0) {
0188 err = -EIO;
0189 len_off = _picolcd_flash_setaddr(data, raw_data, *off);
0190 raw_data[len_off] = s > 32 ? 32 : s;
0191 resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1);
0192 if (!resp || !resp->in_report)
0193 goto skip;
0194 if (resp->in_report->id == REPORT_MEMORY ||
0195 resp->in_report->id == REPORT_BL_READ_MEMORY) {
0196 if (memcmp(raw_data, resp->raw_data, len_off+1) != 0)
0197 goto skip;
0198 if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) {
0199 err = -EFAULT;
0200 goto skip;
0201 }
0202 *off += raw_data[len_off];
0203 s -= raw_data[len_off];
0204 ret += raw_data[len_off];
0205 err = 0;
0206 }
0207 skip:
0208 kfree(resp);
0209 if (err)
0210 return ret > 0 ? ret : err;
0211 }
0212 return ret;
0213 }
0214
0215 static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u,
0216 size_t s, loff_t *off)
0217 {
0218 struct picolcd_data *data = f->private_data;
0219
0220 if (s == 0)
0221 return -EINVAL;
0222 if (*off > 0x05fff)
0223 return 0;
0224 if (*off + s > 0x05fff)
0225 s = 0x06000 - *off;
0226
0227 if (data->status & PICOLCD_BOOTLOADER)
0228 return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off);
0229 else
0230 return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off);
0231 }
0232
0233
0234 static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id,
0235 loff_t *off)
0236 {
0237 struct picolcd_pending *resp;
0238 u8 raw_data[3];
0239 int len_off;
0240 ssize_t ret = -EIO;
0241
0242 if (*off & 0x3f)
0243 return -EINVAL;
0244
0245 len_off = _picolcd_flash_setaddr(data, raw_data, *off);
0246 resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off);
0247 if (!resp || !resp->in_report)
0248 goto skip;
0249 if (resp->in_report->id == REPORT_MEMORY ||
0250 resp->in_report->id == REPORT_BL_ERASE_MEMORY) {
0251 if (memcmp(raw_data, resp->raw_data, len_off) != 0)
0252 goto skip;
0253 ret = 0;
0254 }
0255 skip:
0256 kfree(resp);
0257 return ret;
0258 }
0259
0260
0261 static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id,
0262 const char __user *u, size_t s, loff_t *off)
0263 {
0264 struct picolcd_pending *resp;
0265 u8 raw_data[36];
0266 ssize_t ret = 0;
0267 int len_off, err = -EIO;
0268
0269 while (s > 0) {
0270 err = -EIO;
0271 len_off = _picolcd_flash_setaddr(data, raw_data, *off);
0272 raw_data[len_off] = s > 32 ? 32 : s;
0273 if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) {
0274 err = -EFAULT;
0275 break;
0276 }
0277 resp = picolcd_send_and_wait(data->hdev, report_id, raw_data,
0278 len_off+1+raw_data[len_off]);
0279 if (!resp || !resp->in_report)
0280 goto skip;
0281 if (resp->in_report->id == REPORT_MEMORY ||
0282 resp->in_report->id == REPORT_BL_WRITE_MEMORY) {
0283 if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0)
0284 goto skip;
0285 *off += raw_data[len_off];
0286 s -= raw_data[len_off];
0287 ret += raw_data[len_off];
0288 err = 0;
0289 }
0290 skip:
0291 kfree(resp);
0292 if (err)
0293 break;
0294 }
0295 return ret > 0 ? ret : err;
0296 }
0297
0298 static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u,
0299 size_t s, loff_t *off)
0300 {
0301 struct picolcd_data *data = f->private_data;
0302 ssize_t err, ret = 0;
0303 int report_erase, report_write;
0304
0305 if (s == 0)
0306 return -EINVAL;
0307 if (*off > 0x5fff)
0308 return -ENOSPC;
0309 if (s & 0x3f)
0310 return -EINVAL;
0311 if (*off & 0x3f)
0312 return -EINVAL;
0313
0314 if (data->status & PICOLCD_BOOTLOADER) {
0315 report_erase = REPORT_BL_ERASE_MEMORY;
0316 report_write = REPORT_BL_WRITE_MEMORY;
0317 } else {
0318 report_erase = REPORT_ERASE_MEMORY;
0319 report_write = REPORT_WRITE_MEMORY;
0320 }
0321 mutex_lock(&data->mutex_flash);
0322 while (s > 0) {
0323 err = _picolcd_flash_erase64(data, report_erase, off);
0324 if (err)
0325 break;
0326 err = _picolcd_flash_write(data, report_write, u, 64, off);
0327 if (err < 0)
0328 break;
0329 ret += err;
0330 *off += err;
0331 s -= err;
0332 if (err != 64)
0333 break;
0334 }
0335 mutex_unlock(&data->mutex_flash);
0336 return ret > 0 ? ret : err;
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 static const struct file_operations picolcd_debug_flash_fops = {
0351 .owner = THIS_MODULE,
0352 .open = simple_open,
0353 .read = picolcd_debug_flash_read,
0354 .write = picolcd_debug_flash_write,
0355 .llseek = generic_file_llseek,
0356 };
0357
0358
0359
0360
0361
0362 static const char * const error_codes[] = {
0363 "success", "parameter missing", "data_missing", "block readonly",
0364 "block not erasable", "block too big", "section overflow",
0365 "invalid command length", "invalid data length",
0366 };
0367
0368 static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
0369 const size_t data_len)
0370 {
0371 int i, j;
0372 for (i = j = 0; i < data_len && j + 4 < dst_sz; i++) {
0373 dst[j++] = hex_asc[(data[i] >> 4) & 0x0f];
0374 dst[j++] = hex_asc[data[i] & 0x0f];
0375 dst[j++] = ' ';
0376 }
0377 dst[j] = '\0';
0378 if (j > 0)
0379 dst[j-1] = '\n';
0380 if (i < data_len && j > 2)
0381 dst[j-2] = dst[j-3] = '.';
0382 }
0383
0384 void picolcd_debug_out_report(struct picolcd_data *data,
0385 struct hid_device *hdev, struct hid_report *report)
0386 {
0387 u8 *raw_data;
0388 int raw_size = (report->size >> 3) + 1;
0389 char *buff;
0390 #define BUFF_SZ 256
0391
0392
0393 if (list_empty(&hdev->debug_list))
0394 return;
0395
0396 buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
0397 if (!buff)
0398 return;
0399
0400 raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
0401 if (!raw_data) {
0402 kfree(buff);
0403 return;
0404 }
0405
0406 snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ",
0407 report->id, raw_size);
0408 hid_debug_event(hdev, buff);
0409 raw_data[0] = report->id;
0410 hid_output_report(report, raw_data);
0411 dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
0412 hid_debug_event(hdev, buff);
0413
0414 switch (report->id) {
0415 case REPORT_LED_STATE:
0416
0417 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0418 "REPORT_LED_STATE", report->id, raw_size-1);
0419 hid_debug_event(hdev, buff);
0420 snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]);
0421 hid_debug_event(hdev, buff);
0422 break;
0423 case REPORT_BRIGHTNESS:
0424
0425 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0426 "REPORT_BRIGHTNESS", report->id, raw_size-1);
0427 hid_debug_event(hdev, buff);
0428 snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]);
0429 hid_debug_event(hdev, buff);
0430 break;
0431 case REPORT_CONTRAST:
0432
0433 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0434 "REPORT_CONTRAST", report->id, raw_size-1);
0435 hid_debug_event(hdev, buff);
0436 snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]);
0437 hid_debug_event(hdev, buff);
0438 break;
0439 case REPORT_RESET:
0440
0441 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0442 "REPORT_RESET", report->id, raw_size-1);
0443 hid_debug_event(hdev, buff);
0444 snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n",
0445 raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]);
0446 hid_debug_event(hdev, buff);
0447 break;
0448 case REPORT_LCD_CMD:
0449
0450 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0451 "REPORT_LCD_CMD", report->id, raw_size-1);
0452 hid_debug_event(hdev, buff);
0453
0454 break;
0455 case REPORT_LCD_DATA:
0456
0457 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0458 "REPORT_LCD_CMD", report->id, raw_size-1);
0459
0460 hid_debug_event(hdev, buff);
0461 break;
0462 case REPORT_LCD_CMD_DATA:
0463
0464 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0465 "REPORT_LCD_CMD", report->id, raw_size-1);
0466
0467 hid_debug_event(hdev, buff);
0468 break;
0469 case REPORT_EE_READ:
0470
0471 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0472 "REPORT_EE_READ", report->id, raw_size-1);
0473 hid_debug_event(hdev, buff);
0474 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
0475 raw_data[2], raw_data[1]);
0476 hid_debug_event(hdev, buff);
0477 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
0478 hid_debug_event(hdev, buff);
0479 break;
0480 case REPORT_EE_WRITE:
0481
0482 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0483 "REPORT_EE_WRITE", report->id, raw_size-1);
0484 hid_debug_event(hdev, buff);
0485 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
0486 raw_data[2], raw_data[1]);
0487 hid_debug_event(hdev, buff);
0488 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
0489 hid_debug_event(hdev, buff);
0490 if (raw_data[3] == 0) {
0491 snprintf(buff, BUFF_SZ, "\tNo data\n");
0492 } else if (raw_data[3] + 4 <= raw_size) {
0493 snprintf(buff, BUFF_SZ, "\tData: ");
0494 hid_debug_event(hdev, buff);
0495 dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
0496 } else {
0497 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
0498 }
0499 hid_debug_event(hdev, buff);
0500 break;
0501 case REPORT_ERASE_MEMORY:
0502 case REPORT_BL_ERASE_MEMORY:
0503
0504 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0505 "REPORT_ERASE_MEMORY", report->id, raw_size-1);
0506 hid_debug_event(hdev, buff);
0507 switch (data->addr_sz) {
0508 case 2:
0509 snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n",
0510 raw_data[2], raw_data[1]);
0511 break;
0512 case 3:
0513 snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n",
0514 raw_data[3], raw_data[2], raw_data[1]);
0515 break;
0516 default:
0517 snprintf(buff, BUFF_SZ, "\tNot supported\n");
0518 }
0519 hid_debug_event(hdev, buff);
0520 break;
0521 case REPORT_READ_MEMORY:
0522 case REPORT_BL_READ_MEMORY:
0523
0524 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0525 "REPORT_READ_MEMORY", report->id, raw_size-1);
0526 hid_debug_event(hdev, buff);
0527 switch (data->addr_sz) {
0528 case 2:
0529 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
0530 raw_data[2], raw_data[1]);
0531 hid_debug_event(hdev, buff);
0532 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
0533 break;
0534 case 3:
0535 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
0536 raw_data[3], raw_data[2], raw_data[1]);
0537 hid_debug_event(hdev, buff);
0538 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
0539 break;
0540 default:
0541 snprintf(buff, BUFF_SZ, "\tNot supported\n");
0542 }
0543 hid_debug_event(hdev, buff);
0544 break;
0545 case REPORT_WRITE_MEMORY:
0546 case REPORT_BL_WRITE_MEMORY:
0547
0548 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0549 "REPORT_WRITE_MEMORY", report->id, raw_size-1);
0550 hid_debug_event(hdev, buff);
0551 switch (data->addr_sz) {
0552 case 2:
0553 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
0554 raw_data[2], raw_data[1]);
0555 hid_debug_event(hdev, buff);
0556 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
0557 hid_debug_event(hdev, buff);
0558 if (raw_data[3] == 0) {
0559 snprintf(buff, BUFF_SZ, "\tNo data\n");
0560 } else if (raw_data[3] + 4 <= raw_size) {
0561 snprintf(buff, BUFF_SZ, "\tData: ");
0562 hid_debug_event(hdev, buff);
0563 dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
0564 } else {
0565 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
0566 }
0567 break;
0568 case 3:
0569 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
0570 raw_data[3], raw_data[2], raw_data[1]);
0571 hid_debug_event(hdev, buff);
0572 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
0573 hid_debug_event(hdev, buff);
0574 if (raw_data[4] == 0) {
0575 snprintf(buff, BUFF_SZ, "\tNo data\n");
0576 } else if (raw_data[4] + 5 <= raw_size) {
0577 snprintf(buff, BUFF_SZ, "\tData: ");
0578 hid_debug_event(hdev, buff);
0579 dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
0580 } else {
0581 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
0582 }
0583 break;
0584 default:
0585 snprintf(buff, BUFF_SZ, "\tNot supported\n");
0586 }
0587 hid_debug_event(hdev, buff);
0588 break;
0589 case REPORT_SPLASH_RESTART:
0590
0591 break;
0592 case REPORT_EXIT_KEYBOARD:
0593 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0594 "REPORT_EXIT_KEYBOARD", report->id, raw_size-1);
0595 hid_debug_event(hdev, buff);
0596 snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
0597 raw_data[1] | (raw_data[2] << 8),
0598 raw_data[2], raw_data[1]);
0599 hid_debug_event(hdev, buff);
0600 break;
0601 case REPORT_VERSION:
0602 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0603 "REPORT_VERSION", report->id, raw_size-1);
0604 hid_debug_event(hdev, buff);
0605 break;
0606 case REPORT_DEVID:
0607 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0608 "REPORT_DEVID", report->id, raw_size-1);
0609 hid_debug_event(hdev, buff);
0610 break;
0611 case REPORT_SPLASH_SIZE:
0612 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0613 "REPORT_SPLASH_SIZE", report->id, raw_size-1);
0614 hid_debug_event(hdev, buff);
0615 break;
0616 case REPORT_HOOK_VERSION:
0617 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0618 "REPORT_HOOK_VERSION", report->id, raw_size-1);
0619 hid_debug_event(hdev, buff);
0620 break;
0621 case REPORT_EXIT_FLASHER:
0622 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0623 "REPORT_VERSION", report->id, raw_size-1);
0624 hid_debug_event(hdev, buff);
0625 snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
0626 raw_data[1] | (raw_data[2] << 8),
0627 raw_data[2], raw_data[1]);
0628 hid_debug_event(hdev, buff);
0629 break;
0630 default:
0631 snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
0632 "<unknown>", report->id, raw_size-1);
0633 hid_debug_event(hdev, buff);
0634 break;
0635 }
0636 wake_up_interruptible(&hdev->debug_wait);
0637 kfree(raw_data);
0638 kfree(buff);
0639 }
0640
0641 void picolcd_debug_raw_event(struct picolcd_data *data,
0642 struct hid_device *hdev, struct hid_report *report,
0643 u8 *raw_data, int size)
0644 {
0645 char *buff;
0646
0647 #define BUFF_SZ 256
0648
0649 if (list_empty(&hdev->debug_list))
0650 return;
0651
0652 buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
0653 if (!buff)
0654 return;
0655
0656 switch (report->id) {
0657 case REPORT_ERROR_CODE:
0658
0659 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0660 "REPORT_ERROR_CODE", report->id, size-1);
0661 hid_debug_event(hdev, buff);
0662 if (raw_data[2] < ARRAY_SIZE(error_codes))
0663 snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n",
0664 raw_data[2], error_codes[raw_data[2]], raw_data[1]);
0665 else
0666 snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n",
0667 raw_data[2], raw_data[1]);
0668 hid_debug_event(hdev, buff);
0669 break;
0670 case REPORT_KEY_STATE:
0671
0672 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0673 "REPORT_KEY_STATE", report->id, size-1);
0674 hid_debug_event(hdev, buff);
0675 if (raw_data[1] == 0)
0676 snprintf(buff, BUFF_SZ, "\tNo key pressed\n");
0677 else if (raw_data[2] == 0)
0678 snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n",
0679 raw_data[1], raw_data[1]);
0680 else
0681 snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n",
0682 raw_data[1], raw_data[1], raw_data[2], raw_data[2]);
0683 hid_debug_event(hdev, buff);
0684 break;
0685 case REPORT_IR_DATA:
0686
0687 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0688 "REPORT_IR_DATA", report->id, size-1);
0689 hid_debug_event(hdev, buff);
0690 if (raw_data[1] == 0) {
0691 snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n");
0692 hid_debug_event(hdev, buff);
0693 } else if (raw_data[1] + 1 <= size) {
0694 snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ",
0695 raw_data[1]);
0696 hid_debug_event(hdev, buff);
0697 dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]);
0698 hid_debug_event(hdev, buff);
0699 } else {
0700 snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n",
0701 raw_data[1]-1);
0702 hid_debug_event(hdev, buff);
0703 }
0704 break;
0705 case REPORT_EE_DATA:
0706
0707 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0708 "REPORT_EE_DATA", report->id, size-1);
0709 hid_debug_event(hdev, buff);
0710 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
0711 raw_data[2], raw_data[1]);
0712 hid_debug_event(hdev, buff);
0713 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
0714 hid_debug_event(hdev, buff);
0715 if (raw_data[3] == 0) {
0716 snprintf(buff, BUFF_SZ, "\tNo data\n");
0717 hid_debug_event(hdev, buff);
0718 } else if (raw_data[3] + 4 <= size) {
0719 snprintf(buff, BUFF_SZ, "\tData: ");
0720 hid_debug_event(hdev, buff);
0721 dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
0722 hid_debug_event(hdev, buff);
0723 } else {
0724 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
0725 hid_debug_event(hdev, buff);
0726 }
0727 break;
0728 case REPORT_MEMORY:
0729
0730 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0731 "REPORT_MEMORY", report->id, size-1);
0732 hid_debug_event(hdev, buff);
0733 switch (data->addr_sz) {
0734 case 2:
0735 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
0736 raw_data[2], raw_data[1]);
0737 hid_debug_event(hdev, buff);
0738 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
0739 hid_debug_event(hdev, buff);
0740 if (raw_data[3] == 0) {
0741 snprintf(buff, BUFF_SZ, "\tNo data\n");
0742 } else if (raw_data[3] + 4 <= size) {
0743 snprintf(buff, BUFF_SZ, "\tData: ");
0744 hid_debug_event(hdev, buff);
0745 dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
0746 } else {
0747 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
0748 }
0749 break;
0750 case 3:
0751 snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
0752 raw_data[3], raw_data[2], raw_data[1]);
0753 hid_debug_event(hdev, buff);
0754 snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
0755 hid_debug_event(hdev, buff);
0756 if (raw_data[4] == 0) {
0757 snprintf(buff, BUFF_SZ, "\tNo data\n");
0758 } else if (raw_data[4] + 5 <= size) {
0759 snprintf(buff, BUFF_SZ, "\tData: ");
0760 hid_debug_event(hdev, buff);
0761 dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
0762 } else {
0763 snprintf(buff, BUFF_SZ, "\tData overflowed\n");
0764 }
0765 break;
0766 default:
0767 snprintf(buff, BUFF_SZ, "\tNot supported\n");
0768 }
0769 hid_debug_event(hdev, buff);
0770 break;
0771 case REPORT_VERSION:
0772 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0773 "REPORT_VERSION", report->id, size-1);
0774 hid_debug_event(hdev, buff);
0775 snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
0776 raw_data[2], raw_data[1]);
0777 hid_debug_event(hdev, buff);
0778 break;
0779 case REPORT_BL_ERASE_MEMORY:
0780 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0781 "REPORT_BL_ERASE_MEMORY", report->id, size-1);
0782 hid_debug_event(hdev, buff);
0783
0784 break;
0785 case REPORT_BL_READ_MEMORY:
0786 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0787 "REPORT_BL_READ_MEMORY", report->id, size-1);
0788 hid_debug_event(hdev, buff);
0789
0790 break;
0791 case REPORT_BL_WRITE_MEMORY:
0792 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0793 "REPORT_BL_WRITE_MEMORY", report->id, size-1);
0794 hid_debug_event(hdev, buff);
0795
0796 break;
0797 case REPORT_DEVID:
0798 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0799 "REPORT_DEVID", report->id, size-1);
0800 hid_debug_event(hdev, buff);
0801 snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n",
0802 raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
0803 hid_debug_event(hdev, buff);
0804 snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n",
0805 raw_data[5]);
0806 hid_debug_event(hdev, buff);
0807 break;
0808 case REPORT_SPLASH_SIZE:
0809 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0810 "REPORT_SPLASH_SIZE", report->id, size-1);
0811 hid_debug_event(hdev, buff);
0812 snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n",
0813 (raw_data[2] << 8) | raw_data[1]);
0814 hid_debug_event(hdev, buff);
0815 snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n",
0816 (raw_data[4] << 8) | raw_data[3]);
0817 hid_debug_event(hdev, buff);
0818 break;
0819 case REPORT_HOOK_VERSION:
0820 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0821 "REPORT_HOOK_VERSION", report->id, size-1);
0822 hid_debug_event(hdev, buff);
0823 snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
0824 raw_data[1], raw_data[2]);
0825 hid_debug_event(hdev, buff);
0826 break;
0827 default:
0828 snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
0829 "<unknown>", report->id, size-1);
0830 hid_debug_event(hdev, buff);
0831 break;
0832 }
0833 wake_up_interruptible(&hdev->debug_wait);
0834 kfree(buff);
0835 }
0836
0837 void picolcd_init_devfs(struct picolcd_data *data,
0838 struct hid_report *eeprom_r, struct hid_report *eeprom_w,
0839 struct hid_report *flash_r, struct hid_report *flash_w,
0840 struct hid_report *reset)
0841 {
0842 struct hid_device *hdev = data->hdev;
0843
0844 mutex_init(&data->mutex_flash);
0845
0846
0847 if (reset)
0848 data->debug_reset = debugfs_create_file("reset", 0600,
0849 hdev->debug_dir, data, &picolcd_debug_reset_fops);
0850
0851
0852 if (eeprom_r || eeprom_w)
0853 data->debug_eeprom = debugfs_create_file("eeprom",
0854 (eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0),
0855 hdev->debug_dir, data, &picolcd_debug_eeprom_fops);
0856
0857
0858 if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8)
0859 data->addr_sz = flash_r->field[0]->report_count - 1;
0860 else
0861 data->addr_sz = -1;
0862 if (data->addr_sz == 2 || data->addr_sz == 3) {
0863 data->debug_flash = debugfs_create_file("flash",
0864 (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
0865 hdev->debug_dir, data, &picolcd_debug_flash_fops);
0866 } else if (flash_r || flash_w)
0867 hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
0868 }
0869
0870 void picolcd_exit_devfs(struct picolcd_data *data)
0871 {
0872 struct dentry *dent;
0873
0874 dent = data->debug_reset;
0875 data->debug_reset = NULL;
0876 debugfs_remove(dent);
0877 dent = data->debug_eeprom;
0878 data->debug_eeprom = NULL;
0879 debugfs_remove(dent);
0880 dent = data->debug_flash;
0881 data->debug_flash = NULL;
0882 debugfs_remove(dent);
0883 mutex_destroy(&data->mutex_flash);
0884 }
0885