aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-11-17 08:12:11 -0500
committerJiri Kosina <jkosina@suse.cz>2011-11-22 17:10:58 -0500
commit1d3452c63d4b62329d34d7634f67a3dbec21ca87 (patch)
tree5538195cda1a066e83aa5bee1da479fed004281b /drivers/hid
parent43e5e7c60ee7039f538ccfaaa4e99829719d9bea (diff)
HID: wiimote: Allow direct eeprom access
The wiimote provides direct access to parts of its eeprom. This implements read support for small chunks of the eeprom. This isn't very fast but prevents the reader from blocking the wiimote stream for too long. Write support is not yet supported as the wiimote breaks if we overwrite its memory. Use hidraw to reverse-engineer the eeprom before implementing write support here. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote-core.c10
-rw-r--r--drivers/hid/hid-wiimote-debug.c76
-rw-r--r--drivers/hid/hid-wiimote.h7
3 files changed, 85 insertions, 8 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 919abbaba840..2fd2f0337b8d 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -320,14 +320,8 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
320 wiimote_queue(wdata, cmd, sizeof(cmd)); 320 wiimote_queue(wdata, cmd, sizeof(cmd));
321} 321}
322 322
323#define wiiproto_req_rreg(wdata, os, sz) \ 323void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, __u32 offset,
324 wiiproto_req_rmem((wdata), false, (os), (sz)) 324 __u16 size)
325
326#define wiiproto_req_reeprom(wdata, os, sz) \
327 wiiproto_req_rmem((wdata), true, (os), (sz))
328
329static void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom,
330 __u32 offset, __u16 size)
331{ 325{
332 __u8 cmd[7]; 326 __u8 cmd[7];
333 327
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c
index 6282e3c1a362..f81243c86790 100644
--- a/drivers/hid/hid-wiimote-debug.c
+++ b/drivers/hid/hid-wiimote-debug.c
@@ -10,12 +10,80 @@
10 * any later version. 10 * any later version.
11 */ 11 */
12 12
13#include <linux/debugfs.h>
13#include <linux/module.h> 14#include <linux/module.h>
14#include <linux/spinlock.h> 15#include <linux/spinlock.h>
16#include <linux/uaccess.h>
15#include "hid-wiimote.h" 17#include "hid-wiimote.h"
16 18
17struct wiimote_debug { 19struct wiimote_debug {
18 struct wiimote_data *wdata; 20 struct wiimote_data *wdata;
21 struct dentry *eeprom;
22};
23
24static int wiidebug_eeprom_open(struct inode *i, struct file *f)
25{
26 f->private_data = i->i_private;
27 return 0;
28}
29
30static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
31 loff_t *off)
32{
33 struct wiimote_debug *dbg = f->private_data;
34 struct wiimote_data *wdata = dbg->wdata;
35 unsigned long flags;
36 ssize_t ret;
37 char buf[16];
38 __u16 size;
39
40 if (s == 0)
41 return -EINVAL;
42 if (*off > 0xffffff)
43 return 0;
44 if (s > 16)
45 s = 16;
46
47 ret = wiimote_cmd_acquire(wdata);
48 if (ret)
49 return ret;
50
51 spin_lock_irqsave(&wdata->state.lock, flags);
52 wdata->state.cmd_read_size = s;
53 wdata->state.cmd_read_buf = buf;
54 wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff);
55 wiiproto_req_reeprom(wdata, *off, s);
56 spin_unlock_irqrestore(&wdata->state.lock, flags);
57
58 ret = wiimote_cmd_wait(wdata);
59 if (!ret)
60 size = wdata->state.cmd_read_size;
61
62 spin_lock_irqsave(&wdata->state.lock, flags);
63 wdata->state.cmd_read_buf = NULL;
64 spin_unlock_irqrestore(&wdata->state.lock, flags);
65
66 wiimote_cmd_release(wdata);
67
68 if (ret)
69 return ret;
70 else if (size == 0)
71 return -EIO;
72
73 if (copy_to_user(u, buf, size))
74 return -EFAULT;
75
76 *off += size;
77 ret = size;
78
79 return ret;
80}
81
82static const struct file_operations wiidebug_eeprom_fops = {
83 .owner = THIS_MODULE,
84 .open = wiidebug_eeprom_open,
85 .read = wiidebug_eeprom_read,
86 .llseek = generic_file_llseek,
19}; 87};
20 88
21int wiidebug_init(struct wiimote_data *wdata) 89int wiidebug_init(struct wiimote_data *wdata)
@@ -29,6 +97,13 @@ int wiidebug_init(struct wiimote_data *wdata)
29 97
30 dbg->wdata = wdata; 98 dbg->wdata = wdata;
31 99
100 dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR,
101 dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops);
102 if (!dbg->eeprom) {
103 kfree(dbg);
104 return -ENOMEM;
105 }
106
32 spin_lock_irqsave(&wdata->state.lock, flags); 107 spin_lock_irqsave(&wdata->state.lock, flags);
33 wdata->debug = dbg; 108 wdata->debug = dbg;
34 spin_unlock_irqrestore(&wdata->state.lock, flags); 109 spin_unlock_irqrestore(&wdata->state.lock, flags);
@@ -48,5 +123,6 @@ void wiidebug_deinit(struct wiimote_data *wdata)
48 wdata->debug = NULL; 123 wdata->debug = NULL;
49 spin_unlock_irqrestore(&wdata->state.lock, flags); 124 spin_unlock_irqrestore(&wdata->state.lock, flags);
50 125
126 debugfs_remove(dbg->eeprom);
51 kfree(dbg); 127 kfree(dbg);
52} 128}
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 89b8851dbf1f..7b6765797f81 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -120,6 +120,13 @@ extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
120extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, 120extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,
121 __u8 *rmem, __u8 size); 121 __u8 *rmem, __u8 size);
122 122
123#define wiiproto_req_rreg(wdata, os, sz) \
124 wiiproto_req_rmem((wdata), false, (os), (sz))
125#define wiiproto_req_reeprom(wdata, os, sz) \
126 wiiproto_req_rmem((wdata), true, (os), (sz))
127extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom,
128 __u32 offset, __u16 size);
129
123#ifdef CONFIG_HID_WIIMOTE_EXT 130#ifdef CONFIG_HID_WIIMOTE_EXT
124 131
125extern int wiiext_init(struct wiimote_data *wdata); 132extern int wiiext_init(struct wiimote_data *wdata);