2 * Copyright (c) 2010-2011 by Luc Verhaegen <libv@codethink.co.uk>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/mutex.h>
20 #include <linux/uaccess.h>
21 #include <linux/debugfs.h>
24 #include "services_headers.h"
25 #include "pvr_pdump.h"
26 #include "pvr_pdumpfs.h"
28 static struct mutex pdumpfs_mutex[1];
31 PDUMPFS_MODE_DISABLED,
32 PDUMPFS_MODE_STANDARD,
36 static enum pdumpfs_mode pdumpfs_mode =
37 #if defined(CONFIG_PVR_PDUMP_MODE_STANDARD)
39 #elif defined(CONFIG_PVR_PDUMP_MODE_FULL)
46 static u32 pdumpfs_frame_number;
49 pdumpfs_frame_set(u32 frame)
51 mutex_lock(pdumpfs_mutex);
53 pdumpfs_frame_number = frame;
55 mutex_unlock(pdumpfs_mutex);
59 pdumpfs_capture_enabled(void)
63 mutex_lock(pdumpfs_mutex);
65 if (pdumpfs_mode == PDUMPFS_MODE_FULL)
70 mutex_unlock(pdumpfs_mutex);
76 pdumpfs_flags_check(u32 flags)
80 if (flags & PDUMP_FLAGS_NEVER)
83 mutex_lock(pdumpfs_mutex);
85 if (pdumpfs_mode == PDUMPFS_MODE_FULL)
87 else if ((pdumpfs_mode == PDUMPFS_MODE_STANDARD) &&
88 (flags & PDUMP_FLAGS_CONTINUOUS))
93 mutex_unlock(pdumpfs_mutex);
99 pdumpfs_write_data(void *buffer, size_t size, bool from_user)
101 mutex_lock(pdumpfs_mutex);
103 mutex_unlock(pdumpfs_mutex);
109 pdumpfs_write_string(char *string)
111 mutex_lock(pdumpfs_mutex);
113 mutex_unlock(pdumpfs_mutex);
119 static const struct {
121 enum pdumpfs_mode mode;
122 } pdumpfs_modes[] = {
123 {"disabled", PDUMPFS_MODE_DISABLED},
124 {"standard", PDUMPFS_MODE_STANDARD},
125 {"full", PDUMPFS_MODE_FULL},
126 {NULL, PDUMPFS_MODE_DISABLED}
130 pdumpfs_mode_read(struct file *filp, char __user *buf, size_t size,
138 mutex_lock(pdumpfs_mutex);
140 for (i = 0; pdumpfs_modes[i].name; i++)
141 if (pdumpfs_modes[i].mode == pdumpfs_mode)
142 snprintf(tmp, sizeof(tmp), "%s\n",
143 pdumpfs_modes[i].name);
145 mutex_unlock(pdumpfs_mutex);
147 if (strlen(tmp) < *f_pos)
150 if ((strlen(tmp) + 1) < (*f_pos + size))
151 size = strlen(tmp) + 1 - *f_pos;
153 if (copy_to_user(buf, tmp + *f_pos, size))
161 pdumpfs_mode_write(struct file *filp, const char __user *buf, size_t size,
167 if (*f_pos > sizeof(tmp))
170 if (size > (sizeof(tmp) - *f_pos))
171 size = sizeof(tmp) - *f_pos;
173 if (copy_from_user(tmp + *f_pos, buf, size))
178 mutex_lock(pdumpfs_mutex);
180 for (i = 0; pdumpfs_modes[i].name; i++)
181 if (!strnicmp(tmp, pdumpfs_modes[i].name,
182 strlen(pdumpfs_modes[i].name))) {
183 pdumpfs_mode = pdumpfs_modes[i].mode;
184 mutex_unlock(pdumpfs_mutex);
188 mutex_unlock(pdumpfs_mutex);
192 static const struct file_operations pdumpfs_mode_fops = {
193 .owner = THIS_MODULE,
195 .read = pdumpfs_mode_read,
196 .write = pdumpfs_mode_write,
200 pdumpfs_modes_possible_read(struct file *filp, char __user *buf, size_t size,
203 unsigned int i, skip = *f_pos, pos = 0;
205 for (i = 0; pdumpfs_modes[i].name; i++) {
209 else if (size > pos) {
210 if (copy_to_user(buf + pos, " ", 1))
217 int len = strlen(pdumpfs_modes[i].name);
221 } else if (size > pos) {
222 len = min(len - skip, size - pos);
224 if (copy_to_user(buf + pos,
225 pdumpfs_modes[i].name + skip,
239 static const struct file_operations pdumpfs_modes_possible_fops = {
240 .owner = THIS_MODULE,
242 .read = pdumpfs_modes_possible_read,
245 static struct dentry *pdumpfs_dir;
248 pdumpfs_file_create(const char *name, mode_t mode,
249 const struct file_operations *fops)
251 struct dentry *tmp = NULL;
253 tmp = debugfs_create_file(name, mode, pdumpfs_dir, NULL, fops);
255 pr_err("%s: failed to create pvr/%s file.\n", __func__, name);
259 pdumpfs_fs_init(void)
261 if (!pvr_debugfs_dir) {
262 pr_err("%s: debugfs pvr/ directory does not exist.\n",
267 pdumpfs_dir = debugfs_create_dir("pdump", pvr_debugfs_dir);
269 pr_err("%s: failed to create top level directory.\n",
274 pdumpfs_file_create("mode", S_IRUSR | S_IWUSR,
276 pdumpfs_file_create("modes_possible", S_IRUSR,
277 &pdumpfs_modes_possible_fops);
283 pdumpfs_fs_destroy(void)
286 debugfs_remove_recursive(pdumpfs_dir);
292 mutex_init(pdumpfs_mutex);
300 pdumpfs_cleanup(void)
302 pdumpfs_fs_destroy();