brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 00f9be5 Raw
213 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Debug support for HID Nintendo Wii / Wii U peripherals4 * 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] = NULL96};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 177	dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);178	if (!dbg)179		return -ENOMEM;180 181	dbg->wdata = wdata;182 183	dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR,184		dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops);185 186	dbg->drm = debugfs_create_file("drm", S_IRUSR,187			dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops);188 189	spin_lock_irqsave(&wdata->state.lock, flags);190	wdata->debug = dbg;191	spin_unlock_irqrestore(&wdata->state.lock, flags);192 193	return 0;194 195}196 197void wiidebug_deinit(struct wiimote_data *wdata)198{199	struct wiimote_debug *dbg = wdata->debug;200	unsigned long flags;201 202	if (!dbg)203		return;204 205	spin_lock_irqsave(&wdata->state.lock, flags);206	wdata->debug = NULL;207	spin_unlock_irqrestore(&wdata->state.lock, flags);208 209	debugfs_remove(dbg->drm);210	debugfs_remove(dbg->eeprom);211	kfree(dbg);212}213