cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-picolcd_debugfs.c (26894B)


      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