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