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-wiimote-debug.c (4855B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Debug support for HID Nintendo Wii / Wii U peripherals
      4 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
      5 */
      6
      7/*
      8 */
      9
     10#include <linux/debugfs.h>
     11#include <linux/module.h>
     12#include <linux/seq_file.h>
     13#include <linux/spinlock.h>
     14#include <linux/uaccess.h>
     15#include "hid-wiimote.h"
     16
     17struct wiimote_debug {
     18	struct wiimote_data *wdata;
     19	struct dentry *eeprom;
     20	struct dentry *drm;
     21};
     22
     23static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
     24								loff_t *off)
     25{
     26	struct wiimote_debug *dbg = f->private_data;
     27	struct wiimote_data *wdata = dbg->wdata;
     28	unsigned long flags;
     29	ssize_t ret;
     30	char buf[16];
     31	__u16 size = 0;
     32
     33	if (s == 0)
     34		return -EINVAL;
     35	if (*off > 0xffffff)
     36		return 0;
     37	if (s > 16)
     38		s = 16;
     39
     40	ret = wiimote_cmd_acquire(wdata);
     41	if (ret)
     42		return ret;
     43
     44	spin_lock_irqsave(&wdata->state.lock, flags);
     45	wdata->state.cmd_read_size = s;
     46	wdata->state.cmd_read_buf = buf;
     47	wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff);
     48	wiiproto_req_reeprom(wdata, *off, s);
     49	spin_unlock_irqrestore(&wdata->state.lock, flags);
     50
     51	ret = wiimote_cmd_wait(wdata);
     52	if (!ret)
     53		size = wdata->state.cmd_read_size;
     54
     55	spin_lock_irqsave(&wdata->state.lock, flags);
     56	wdata->state.cmd_read_buf = NULL;
     57	spin_unlock_irqrestore(&wdata->state.lock, flags);
     58
     59	wiimote_cmd_release(wdata);
     60
     61	if (ret)
     62		return ret;
     63	else if (size == 0)
     64		return -EIO;
     65
     66	if (copy_to_user(u, buf, size))
     67		return -EFAULT;
     68
     69	*off += size;
     70	ret = size;
     71
     72	return ret;
     73}
     74
     75static const struct file_operations wiidebug_eeprom_fops = {
     76	.owner = THIS_MODULE,
     77	.open = simple_open,
     78	.read = wiidebug_eeprom_read,
     79	.llseek = generic_file_llseek,
     80};
     81
     82static const char *wiidebug_drmmap[] = {
     83	[WIIPROTO_REQ_NULL] = "NULL",
     84	[WIIPROTO_REQ_DRM_K] = "K",
     85	[WIIPROTO_REQ_DRM_KA] = "KA",
     86	[WIIPROTO_REQ_DRM_KE] = "KE",
     87	[WIIPROTO_REQ_DRM_KAI] = "KAI",
     88	[WIIPROTO_REQ_DRM_KEE] = "KEE",
     89	[WIIPROTO_REQ_DRM_KAE] = "KAE",
     90	[WIIPROTO_REQ_DRM_KIE] = "KIE",
     91	[WIIPROTO_REQ_DRM_KAIE] = "KAIE",
     92	[WIIPROTO_REQ_DRM_E] = "E",
     93	[WIIPROTO_REQ_DRM_SKAI1] = "SKAI1",
     94	[WIIPROTO_REQ_DRM_SKAI2] = "SKAI2",
     95	[WIIPROTO_REQ_MAX] = NULL
     96};
     97
     98static int wiidebug_drm_show(struct seq_file *f, void *p)
     99{
    100	struct wiimote_debug *dbg = f->private;
    101	const char *str = NULL;
    102	unsigned long flags;
    103	__u8 drm;
    104
    105	spin_lock_irqsave(&dbg->wdata->state.lock, flags);
    106	drm = dbg->wdata->state.drm;
    107	spin_unlock_irqrestore(&dbg->wdata->state.lock, flags);
    108
    109	if (drm < WIIPROTO_REQ_MAX)
    110		str = wiidebug_drmmap[drm];
    111	if (!str)
    112		str = "unknown";
    113
    114	seq_printf(f, "%s\n", str);
    115
    116	return 0;
    117}
    118
    119static int wiidebug_drm_open(struct inode *i, struct file *f)
    120{
    121	return single_open(f, wiidebug_drm_show, i->i_private);
    122}
    123
    124static ssize_t wiidebug_drm_write(struct file *f, const char __user *u,
    125							size_t s, loff_t *off)
    126{
    127	struct seq_file *sf = f->private_data;
    128	struct wiimote_debug *dbg = sf->private;
    129	unsigned long flags;
    130	char buf[16];
    131	ssize_t len;
    132	int i;
    133
    134	if (s == 0)
    135		return -EINVAL;
    136
    137	len = min((size_t) 15, s);
    138	if (copy_from_user(buf, u, len))
    139		return -EFAULT;
    140
    141	buf[len] = 0;
    142
    143	for (i = 0; i < WIIPROTO_REQ_MAX; ++i) {
    144		if (!wiidebug_drmmap[i])
    145			continue;
    146		if (!strcasecmp(buf, wiidebug_drmmap[i]))
    147			break;
    148	}
    149
    150	if (i == WIIPROTO_REQ_MAX)
    151		i = simple_strtoul(buf, NULL, 16);
    152
    153	spin_lock_irqsave(&dbg->wdata->state.lock, flags);
    154	dbg->wdata->state.flags &= ~WIIPROTO_FLAG_DRM_LOCKED;
    155	wiiproto_req_drm(dbg->wdata, (__u8) i);
    156	if (i != WIIPROTO_REQ_NULL)
    157		dbg->wdata->state.flags |= WIIPROTO_FLAG_DRM_LOCKED;
    158	spin_unlock_irqrestore(&dbg->wdata->state.lock, flags);
    159
    160	return len;
    161}
    162
    163static const struct file_operations wiidebug_drm_fops = {
    164	.owner = THIS_MODULE,
    165	.open = wiidebug_drm_open,
    166	.read = seq_read,
    167	.llseek = seq_lseek,
    168	.write = wiidebug_drm_write,
    169	.release = single_release,
    170};
    171
    172int wiidebug_init(struct wiimote_data *wdata)
    173{
    174	struct wiimote_debug *dbg;
    175	unsigned long flags;
    176	int ret = -ENOMEM;
    177
    178	dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
    179	if (!dbg)
    180		return -ENOMEM;
    181
    182	dbg->wdata = wdata;
    183
    184	dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR,
    185		dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops);
    186	if (!dbg->eeprom)
    187		goto err;
    188
    189	dbg->drm = debugfs_create_file("drm", S_IRUSR,
    190			dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops);
    191	if (!dbg->drm)
    192		goto err_drm;
    193
    194	spin_lock_irqsave(&wdata->state.lock, flags);
    195	wdata->debug = dbg;
    196	spin_unlock_irqrestore(&wdata->state.lock, flags);
    197
    198	return 0;
    199
    200err_drm:
    201	debugfs_remove(dbg->eeprom);
    202err:
    203	kfree(dbg);
    204	return ret;
    205}
    206
    207void wiidebug_deinit(struct wiimote_data *wdata)
    208{
    209	struct wiimote_debug *dbg = wdata->debug;
    210	unsigned long flags;
    211
    212	if (!dbg)
    213		return;
    214
    215	spin_lock_irqsave(&wdata->state.lock, flags);
    216	wdata->debug = NULL;
    217	spin_unlock_irqrestore(&wdata->state.lock, flags);
    218
    219	debugfs_remove(dbg->drm);
    220	debugfs_remove(dbg->eeprom);
    221	kfree(dbg);
    222}