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