Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Debug support for HID Nintendo Wii / Wii U peripherals
0004  * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
0005  */
0006 
0007 /*
0008  */
0009 
0010 #include <linux/debugfs.h>
0011 #include <linux/module.h>
0012 #include <linux/seq_file.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/uaccess.h>
0015 #include "hid-wiimote.h"
0016 
0017 struct wiimote_debug {
0018     struct wiimote_data *wdata;
0019     struct dentry *eeprom;
0020     struct dentry *drm;
0021 };
0022 
0023 static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
0024                                 loff_t *off)
0025 {
0026     struct wiimote_debug *dbg = f->private_data;
0027     struct wiimote_data *wdata = dbg->wdata;
0028     unsigned long flags;
0029     ssize_t ret;
0030     char buf[16];
0031     __u16 size = 0;
0032 
0033     if (s == 0)
0034         return -EINVAL;
0035     if (*off > 0xffffff)
0036         return 0;
0037     if (s > 16)
0038         s = 16;
0039 
0040     ret = wiimote_cmd_acquire(wdata);
0041     if (ret)
0042         return ret;
0043 
0044     spin_lock_irqsave(&wdata->state.lock, flags);
0045     wdata->state.cmd_read_size = s;
0046     wdata->state.cmd_read_buf = buf;
0047     wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff);
0048     wiiproto_req_reeprom(wdata, *off, s);
0049     spin_unlock_irqrestore(&wdata->state.lock, flags);
0050 
0051     ret = wiimote_cmd_wait(wdata);
0052     if (!ret)
0053         size = wdata->state.cmd_read_size;
0054 
0055     spin_lock_irqsave(&wdata->state.lock, flags);
0056     wdata->state.cmd_read_buf = NULL;
0057     spin_unlock_irqrestore(&wdata->state.lock, flags);
0058 
0059     wiimote_cmd_release(wdata);
0060 
0061     if (ret)
0062         return ret;
0063     else if (size == 0)
0064         return -EIO;
0065 
0066     if (copy_to_user(u, buf, size))
0067         return -EFAULT;
0068 
0069     *off += size;
0070     ret = size;
0071 
0072     return ret;
0073 }
0074 
0075 static const struct file_operations wiidebug_eeprom_fops = {
0076     .owner = THIS_MODULE,
0077     .open = simple_open,
0078     .read = wiidebug_eeprom_read,
0079     .llseek = generic_file_llseek,
0080 };
0081 
0082 static const char *wiidebug_drmmap[] = {
0083     [WIIPROTO_REQ_NULL] = "NULL",
0084     [WIIPROTO_REQ_DRM_K] = "K",
0085     [WIIPROTO_REQ_DRM_KA] = "KA",
0086     [WIIPROTO_REQ_DRM_KE] = "KE",
0087     [WIIPROTO_REQ_DRM_KAI] = "KAI",
0088     [WIIPROTO_REQ_DRM_KEE] = "KEE",
0089     [WIIPROTO_REQ_DRM_KAE] = "KAE",
0090     [WIIPROTO_REQ_DRM_KIE] = "KIE",
0091     [WIIPROTO_REQ_DRM_KAIE] = "KAIE",
0092     [WIIPROTO_REQ_DRM_E] = "E",
0093     [WIIPROTO_REQ_DRM_SKAI1] = "SKAI1",
0094     [WIIPROTO_REQ_DRM_SKAI2] = "SKAI2",
0095     [WIIPROTO_REQ_MAX] = NULL
0096 };
0097 
0098 static int wiidebug_drm_show(struct seq_file *f, void *p)
0099 {
0100     struct wiimote_debug *dbg = f->private;
0101     const char *str = NULL;
0102     unsigned long flags;
0103     __u8 drm;
0104 
0105     spin_lock_irqsave(&dbg->wdata->state.lock, flags);
0106     drm = dbg->wdata->state.drm;
0107     spin_unlock_irqrestore(&dbg->wdata->state.lock, flags);
0108 
0109     if (drm < WIIPROTO_REQ_MAX)
0110         str = wiidebug_drmmap[drm];
0111     if (!str)
0112         str = "unknown";
0113 
0114     seq_printf(f, "%s\n", str);
0115 
0116     return 0;
0117 }
0118 
0119 static int wiidebug_drm_open(struct inode *i, struct file *f)
0120 {
0121     return single_open(f, wiidebug_drm_show, i->i_private);
0122 }
0123 
0124 static ssize_t wiidebug_drm_write(struct file *f, const char __user *u,
0125                             size_t s, loff_t *off)
0126 {
0127     struct seq_file *sf = f->private_data;
0128     struct wiimote_debug *dbg = sf->private;
0129     unsigned long flags;
0130     char buf[16];
0131     ssize_t len;
0132     int i;
0133 
0134     if (s == 0)
0135         return -EINVAL;
0136 
0137     len = min((size_t) 15, s);
0138     if (copy_from_user(buf, u, len))
0139         return -EFAULT;
0140 
0141     buf[len] = 0;
0142 
0143     for (i = 0; i < WIIPROTO_REQ_MAX; ++i) {
0144         if (!wiidebug_drmmap[i])
0145             continue;
0146         if (!strcasecmp(buf, wiidebug_drmmap[i]))
0147             break;
0148     }
0149 
0150     if (i == WIIPROTO_REQ_MAX)
0151         i = simple_strtoul(buf, NULL, 16);
0152 
0153     spin_lock_irqsave(&dbg->wdata->state.lock, flags);
0154     dbg->wdata->state.flags &= ~WIIPROTO_FLAG_DRM_LOCKED;
0155     wiiproto_req_drm(dbg->wdata, (__u8) i);
0156     if (i != WIIPROTO_REQ_NULL)
0157         dbg->wdata->state.flags |= WIIPROTO_FLAG_DRM_LOCKED;
0158     spin_unlock_irqrestore(&dbg->wdata->state.lock, flags);
0159 
0160     return len;
0161 }
0162 
0163 static const struct file_operations wiidebug_drm_fops = {
0164     .owner = THIS_MODULE,
0165     .open = wiidebug_drm_open,
0166     .read = seq_read,
0167     .llseek = seq_lseek,
0168     .write = wiidebug_drm_write,
0169     .release = single_release,
0170 };
0171 
0172 int wiidebug_init(struct wiimote_data *wdata)
0173 {
0174     struct wiimote_debug *dbg;
0175     unsigned long flags;
0176     int ret = -ENOMEM;
0177 
0178     dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
0179     if (!dbg)
0180         return -ENOMEM;
0181 
0182     dbg->wdata = wdata;
0183 
0184     dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR,
0185         dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops);
0186     if (!dbg->eeprom)
0187         goto err;
0188 
0189     dbg->drm = debugfs_create_file("drm", S_IRUSR,
0190             dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops);
0191     if (!dbg->drm)
0192         goto err_drm;
0193 
0194     spin_lock_irqsave(&wdata->state.lock, flags);
0195     wdata->debug = dbg;
0196     spin_unlock_irqrestore(&wdata->state.lock, flags);
0197 
0198     return 0;
0199 
0200 err_drm:
0201     debugfs_remove(dbg->eeprom);
0202 err:
0203     kfree(dbg);
0204     return ret;
0205 }
0206 
0207 void wiidebug_deinit(struct wiimote_data *wdata)
0208 {
0209     struct wiimote_debug *dbg = wdata->debug;
0210     unsigned long flags;
0211 
0212     if (!dbg)
0213         return;
0214 
0215     spin_lock_irqsave(&wdata->state.lock, flags);
0216     wdata->debug = NULL;
0217     spin_unlock_irqrestore(&wdata->state.lock, flags);
0218 
0219     debugfs_remove(dbg->drm);
0220     debugfs_remove(dbg->eeprom);
0221     kfree(dbg);
0222 }