linux/drivers/hid/hid-picolcd_debugfs.c
<<
>>
Prefs
   1/***************************************************************************
   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>
  22
  23#include <linux/fb.h>
  24#include <linux/seq_file.h>
  25#include <linux/debugfs.h>
  26
  27#include <linux/module.h>
  28#include <linux/uaccess.h>
  29
  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;
 137        raw_data[2] = min_t(size_t, 20, s);
 138        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 */
 372static const char * const error_codes[] = {
 373        "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;
 382        for (i = j = 0; i < data_len && j + 4 < dst_sz; i++) {
 383                dst[j++] = hex_asc[(data[i] >> 4) & 0x0f];
 384                dst[j++] = hex_asc[data[i] & 0x0f];
 385                dst[j++] = ' ';
 386        }
 387        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] = '.';
 392}
 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 */
 403        if (list_empty(&hdev->debug_list))
 404                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 */
 658        if (list_empty(&hdev->debug_list))
 659                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: ",
 704                                        raw_data[1]);
 705                        hid_debug_event(hdev, buff);
 706                        dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]);
 707                        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
 898
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.