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