Root/
1 | /* |
2 | * Debug support for HID Nintendo Wiimote devices |
3 | * Copyright (c) 2011 David Herrmann |
4 | */ |
5 | |
6 | /* |
7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the Free |
9 | * Software Foundation; either version 2 of the License, or (at your option) |
10 | * any later version. |
11 | */ |
12 | |
13 | #include <linux/debugfs.h> |
14 | #include <linux/module.h> |
15 | #include <linux/seq_file.h> |
16 | #include <linux/spinlock.h> |
17 | #include <linux/uaccess.h> |
18 | #include "hid-wiimote.h" |
19 | |
20 | struct wiimote_debug { |
21 | struct wiimote_data *wdata; |
22 | struct dentry *eeprom; |
23 | struct dentry *drm; |
24 | }; |
25 | |
26 | static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, |
27 | loff_t *off) |
28 | { |
29 | struct wiimote_debug *dbg = f->private_data; |
30 | struct wiimote_data *wdata = dbg->wdata; |
31 | unsigned long flags; |
32 | ssize_t ret; |
33 | char buf[16]; |
34 | __u16 size; |
35 | |
36 | if (s == 0) |
37 | return -EINVAL; |
38 | if (*off > 0xffffff) |
39 | return 0; |
40 | if (s > 16) |
41 | s = 16; |
42 | |
43 | ret = wiimote_cmd_acquire(wdata); |
44 | if (ret) |
45 | return ret; |
46 | |
47 | spin_lock_irqsave(&wdata->state.lock, flags); |
48 | wdata->state.cmd_read_size = s; |
49 | wdata->state.cmd_read_buf = buf; |
50 | wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff); |
51 | wiiproto_req_reeprom(wdata, *off, s); |
52 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
53 | |
54 | ret = wiimote_cmd_wait(wdata); |
55 | if (!ret) |
56 | size = wdata->state.cmd_read_size; |
57 | |
58 | spin_lock_irqsave(&wdata->state.lock, flags); |
59 | wdata->state.cmd_read_buf = NULL; |
60 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
61 | |
62 | wiimote_cmd_release(wdata); |
63 | |
64 | if (ret) |
65 | return ret; |
66 | else if (size == 0) |
67 | return -EIO; |
68 | |
69 | if (copy_to_user(u, buf, size)) |
70 | return -EFAULT; |
71 | |
72 | *off += size; |
73 | ret = size; |
74 | |
75 | return ret; |
76 | } |
77 | |
78 | static const struct file_operations wiidebug_eeprom_fops = { |
79 | .owner = THIS_MODULE, |
80 | .open = simple_open, |
81 | .read = wiidebug_eeprom_read, |
82 | .llseek = generic_file_llseek, |
83 | }; |
84 | |
85 | static const char *wiidebug_drmmap[] = { |
86 | [WIIPROTO_REQ_NULL] = "NULL", |
87 | [WIIPROTO_REQ_DRM_K] = "K", |
88 | [WIIPROTO_REQ_DRM_KA] = "KA", |
89 | [WIIPROTO_REQ_DRM_KE] = "KE", |
90 | [WIIPROTO_REQ_DRM_KAI] = "KAI", |
91 | [WIIPROTO_REQ_DRM_KEE] = "KEE", |
92 | [WIIPROTO_REQ_DRM_KAE] = "KAE", |
93 | [WIIPROTO_REQ_DRM_KIE] = "KIE", |
94 | [WIIPROTO_REQ_DRM_KAIE] = "KAIE", |
95 | [WIIPROTO_REQ_DRM_E] = "E", |
96 | [WIIPROTO_REQ_DRM_SKAI1] = "SKAI1", |
97 | [WIIPROTO_REQ_DRM_SKAI2] = "SKAI2", |
98 | [WIIPROTO_REQ_MAX] = NULL |
99 | }; |
100 | |
101 | static int wiidebug_drm_show(struct seq_file *f, void *p) |
102 | { |
103 | struct wiimote_debug *dbg = f->private; |
104 | const char *str = NULL; |
105 | unsigned long flags; |
106 | __u8 drm; |
107 | |
108 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); |
109 | drm = dbg->wdata->state.drm; |
110 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); |
111 | |
112 | if (drm < WIIPROTO_REQ_MAX) |
113 | str = wiidebug_drmmap[drm]; |
114 | if (!str) |
115 | str = "unknown"; |
116 | |
117 | seq_printf(f, "%s\n", str); |
118 | |
119 | return 0; |
120 | } |
121 | |
122 | static int wiidebug_drm_open(struct inode *i, struct file *f) |
123 | { |
124 | return single_open(f, wiidebug_drm_show, i->i_private); |
125 | } |
126 | |
127 | static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, |
128 | size_t s, loff_t *off) |
129 | { |
130 | struct wiimote_debug *dbg = f->private_data; |
131 | unsigned long flags; |
132 | char buf[16]; |
133 | ssize_t len; |
134 | int i; |
135 | |
136 | if (s == 0) |
137 | return -EINVAL; |
138 | |
139 | len = min((size_t) 15, s); |
140 | if (copy_from_user(buf, u, len)) |
141 | return -EFAULT; |
142 | |
143 | buf[15] = 0; |
144 | |
145 | for (i = 0; i < WIIPROTO_REQ_MAX; ++i) { |
146 | if (!wiidebug_drmmap[i]) |
147 | continue; |
148 | if (!strcasecmp(buf, wiidebug_drmmap[i])) |
149 | break; |
150 | } |
151 | |
152 | if (i == WIIPROTO_REQ_MAX) |
153 | i = simple_strtoul(buf, NULL, 10); |
154 | |
155 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); |
156 | wiiproto_req_drm(dbg->wdata, (__u8) i); |
157 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); |
158 | |
159 | return len; |
160 | } |
161 | |
162 | static const struct file_operations wiidebug_drm_fops = { |
163 | .owner = THIS_MODULE, |
164 | .open = wiidebug_drm_open, |
165 | .read = seq_read, |
166 | .llseek = seq_lseek, |
167 | .write = wiidebug_drm_write, |
168 | .release = single_release, |
169 | }; |
170 | |
171 | int wiidebug_init(struct wiimote_data *wdata) |
172 | { |
173 | struct wiimote_debug *dbg; |
174 | unsigned long flags; |
175 | int ret = -ENOMEM; |
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 | if (!dbg->eeprom) |
186 | goto err; |
187 | |
188 | dbg->drm = debugfs_create_file("drm", S_IRUSR, |
189 | dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops); |
190 | if (!dbg->drm) |
191 | goto err_drm; |
192 | |
193 | spin_lock_irqsave(&wdata->state.lock, flags); |
194 | wdata->debug = dbg; |
195 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
196 | |
197 | return 0; |
198 | |
199 | err_drm: |
200 | debugfs_remove(dbg->eeprom); |
201 | err: |
202 | kfree(dbg); |
203 | return ret; |
204 | } |
205 | |
206 | void wiidebug_deinit(struct wiimote_data *wdata) |
207 | { |
208 | struct wiimote_debug *dbg = wdata->debug; |
209 | unsigned long flags; |
210 | |
211 | if (!dbg) |
212 | return; |
213 | |
214 | spin_lock_irqsave(&wdata->state.lock, flags); |
215 | wdata->debug = NULL; |
216 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
217 | |
218 | debugfs_remove(dbg->drm); |
219 | debugfs_remove(dbg->eeprom); |
220 | kfree(dbg); |
221 | } |
222 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9