2 * @file microdia-debugfs.c
3 * @author Brian johnson
7 * @brief Driver for Microdia USB video camera
9 * @note Copyright (C) Brian Johnson
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <linux/debugfs.h>
29 #include <linux/seq_file.h>
34 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
35 #undef DEFINE_SIMPLE_ATTRIBUTE
36 #define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
37 static void __fops ## _set_wrapper(void *data, __u64 val) \
41 static __u64 __fops ## _get_wrapper(void *data) \
44 __get(data, &value); \
47 static int __fops ## _open(struct inode *inode, struct file *file) \
49 __simple_attr_check_format(__fmt, 0ull); \
50 return simple_attr_open(inode, file, \
51 __fops ## _get_wrapper, \
52 __fops ## _set_wrapper, \
55 static struct file_operations __fops = { \
56 .owner = THIS_MODULE, \
57 .open = __fops ## _open, \
58 .release = simple_attr_close, \
59 .read = simple_attr_read, \
60 .write = simple_attr_write, \
66 * Name of our directory in debugfs
68 static const char *debug_dir_name
= "microdia";
72 * Dentry for our debug dir (for cleanup)
74 static struct dentry
*debug_dir
;
76 struct kref debug_ref
;
79 * debugfs entry for dynamically changing the log level
81 static struct dentry
*dent_log_level
;
83 static int debugfs_u16_set(void *data
, __u64 val
)
89 static int debugfs_u16_get(void *data
, __u64
*val
)
95 static int debugfs_u8_set(void *data
, __u64 val
)
101 static int debugfs_u8_get(void *data
, __u64
*val
)
107 static void *bridge_dump_start(struct seq_file
*m
, loff_t
*pos
)
109 loff_t
*spos
= kmalloc(sizeof(loff_t
), GFP_KERNEL
);
111 return ERR_PTR(-ENOMEM
);
113 if (*pos
< 0 || *pos
> 31)
120 static void *bridge_dump_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
122 loff_t
*spos
= (loff_t
*)v
;
126 return ERR_PTR(-EACCES
);
131 static void bridge_dump_stop(struct seq_file
*m
, void *v
)
137 static int bridge_dump_show(struct seq_file
*m
, void *v
)
140 loff_t
*spos
= (loff_t
*)v
;
141 __u16 reg
= 0x1000 + (*spos
* 16);
142 struct usb_microdia
*dev
= m
->private;
144 if (usb_microdia_control_read(dev
, reg
, values
, 16) < 0)
147 seq_printf(m
, "0x%X %02X %02X %02X %02X %02X %02X %02X %02X "
148 "%02X %02X %02X %02X %02X %02X %02X %02X\n", reg
,
149 values
[0], values
[1], values
[2], values
[3],
150 values
[4], values
[5], values
[6], values
[7],
151 values
[8], values
[9], values
[10], values
[11],
152 values
[12], values
[13], values
[14], values
[15]);
157 static struct seq_operations bridge_dump_seq_ops
= {
158 .start
= bridge_dump_start
,
159 .next
= bridge_dump_next
,
160 .stop
= bridge_dump_stop
,
161 .show
= bridge_dump_show
164 static int bridge_dump_open(struct inode
*inode
, struct file
*file
)
167 ret
= seq_open(file
, &bridge_dump_seq_ops
);
169 ((struct seq_file
*)file
->private_data
)->private =
174 static struct file_operations bridge_dump_ops
= {
175 .owner
= THIS_MODULE
,
176 .open
= bridge_dump_open
,
179 .release
= seq_release
,
182 int bridge_value_set(void *data
, __u64 val
)
184 struct usb_microdia
*dev
= data
;
185 __u8 value
= (__u64
)val
;
187 if (dev
->debug
.bridge_addr
>= 0x1000 &&
188 dev
->debug
.bridge_addr
<= 0x11ff) {
189 usb_microdia_control_write(dev
,
190 dev
->debug
.bridge_addr
,
197 int bridge_value_get(void *data
, __u64
*val
)
199 struct usb_microdia
*dev
= data
;
202 if (dev
->debug
.bridge_addr
>= 0x1000 &&
203 dev
->debug
.bridge_addr
<= 0x11ff) {
204 if (usb_microdia_control_read(dev
,
205 dev
->debug
.bridge_addr
,
214 int sensor_value8_set(void *data
, __u64 val
)
216 struct usb_microdia
*dev
= data
;
217 __u8 value
= (__u8
)val
;
219 sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
,
220 1, dev
->debug
.sensor_addr
,
221 dev
->sensor_flags
, &value
);
226 int sensor_value8_get(void *data
, __u64
*val
)
228 struct usb_microdia
*dev
= data
;
231 if (sn9c20x_read_i2c_data(dev
, dev
->sensor_slave_address
,
232 1, dev
->debug
.sensor_addr
,
233 dev
->sensor_flags
, &value
) >= 0) {
240 int sensor_value16_set(void *data
, __u64 val
)
242 struct usb_microdia
*dev
= data
;
244 buf
[0] = (val
>> 8) & 0xFF;
247 sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
,
248 2, dev
->debug
.sensor_addr
,
249 dev
->sensor_flags
, buf
);
254 int sensor_value16_get(void *data
, __u64
*val
)
256 struct usb_microdia
*dev
= data
;
259 if (sn9c20x_read_i2c_data(dev
, dev
->sensor_slave_address
,
260 2, dev
->debug
.sensor_addr
,
261 dev
->sensor_flags
, buf
) >= 0) {
262 *val
= ((buf
[0] << 8) | buf
[1]) & 0xFFFF;
268 int sensor_value32_set(void *data
, __u64 val
)
270 struct usb_microdia
*dev
= data
;
272 buf
[0] = (val
>> 24) & 0xFF;
273 buf
[1] = (val
>> 16) & 0xFF;
274 buf
[2] = (val
>> 8) & 0xFF;
277 sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
,
278 4, dev
->debug
.sensor_addr
,
279 dev
->sensor_flags
, buf
);
284 int sensor_value32_get(void *data
, __u64
*val
)
286 struct usb_microdia
*dev
= data
;
289 if (sn9c20x_read_i2c_data(dev
, dev
->sensor_slave_address
,
290 4, dev
->debug
.sensor_addr
,
291 dev
->sensor_flags
, buf
) >= 0) {
292 *val
= ((buf
[0] << 24) | (buf
[1] << 16)
293 | (buf
[2] << 8) | buf
[3]) & 0xFFFFFFFF;
299 DEFINE_SIMPLE_ATTRIBUTE(fops_x16
,
304 DEFINE_SIMPLE_ATTRIBUTE(fops_x8
,
309 DEFINE_SIMPLE_ATTRIBUTE(bridge_value_ops
,
314 DEFINE_SIMPLE_ATTRIBUTE(sensor_value8_ops
,
319 DEFINE_SIMPLE_ATTRIBUTE(sensor_value16_ops
,
324 DEFINE_SIMPLE_ATTRIBUTE(sensor_value32_ops
,
329 void debugfs_delete(struct kref
*ref
)
332 debugfs_remove(debug_dir
);
335 void microdia_init_debugfs()
337 debug_dir
= debugfs_create_dir(debug_dir_name
, NULL
);
339 dent_log_level
= debugfs_create_u8("log_level",
343 kref_init(&debug_ref
);
347 void microdia_uninit_debugfs()
350 debugfs_remove(dent_log_level
);
351 kref_put(&debug_ref
, debugfs_delete
);
355 * @brief Create the 'debug' entries.
357 * This function permits to create all the entries in the 'debug' filesystem.
359 * @param usb_microdia device structure
361 * @returns 0 if all is OK
363 int microdia_create_debugfs_files(struct usb_microdia
*dev
)
367 snprintf(device_name
, 9, "video%d", dev
->vdev
->minor
);
368 dev
->debug
.dent_device
=
369 debugfs_create_dir(device_name
, debug_dir
);
370 if (dev
->debug
.dent_device
) {
371 dev
->debug
.bridge_addr
= 0x1000;
372 dev
->debug
.sensor_addr
= 0x00;
373 dev
->debug
.dent_bridge_addr
=
374 debugfs_create_file("bridge.address",
376 dev
->debug
.dent_device
,
377 &dev
->debug
.bridge_addr
,
379 dev
->debug
.dent_bridge_val
=
380 debugfs_create_file("bridge.value",
382 dev
->debug
.dent_device
,
383 dev
, &bridge_value_ops
);
384 dev
->debug
.dent_bridge_dump
=
385 debugfs_create_file("bridge.dump",
387 dev
->debug
.dent_device
,
388 dev
, &bridge_dump_ops
);
389 dev
->debug
.dent_sensor_addr
=
390 debugfs_create_file("sensor.address",
392 dev
->debug
.dent_device
,
393 &dev
->debug
.sensor_addr
,
395 dev
->debug
.dent_sensor_val8
=
396 debugfs_create_file("sensor.value8",
398 dev
->debug
.dent_device
,
399 dev
, &sensor_value8_ops
);
400 dev
->debug
.dent_sensor_val16
=
401 debugfs_create_file("sensor.value16",
403 dev
->debug
.dent_device
,
404 dev
, &sensor_value16_ops
);
405 dev
->debug
.dent_sensor_val32
=
406 debugfs_create_file("sensor.value32",
408 dev
->debug
.dent_device
,
409 dev
, &sensor_value32_ops
);
412 kref_get(&debug_ref
);
417 * @brief Remove the 'debugfs' entries.
419 * This function permits to remove all the entries in the 'debug' filesystem.
421 * @param usb_microdia device structure
423 * @returns 0 if all is OK
425 int microdia_remove_debugfs_files(struct usb_microdia
*dev
)
427 if (dev
->debug
.dent_bridge_val
)
428 debugfs_remove(dev
->debug
.dent_bridge_val
);
429 if (dev
->debug
.dent_bridge_addr
)
430 debugfs_remove(dev
->debug
.dent_bridge_addr
);
431 if (dev
->debug
.dent_bridge_dump
)
432 debugfs_remove(dev
->debug
.dent_bridge_dump
);
433 if (dev
->debug
.dent_sensor_addr
)
434 debugfs_remove(dev
->debug
.dent_sensor_addr
);
435 if (dev
->debug
.dent_sensor_val8
)
436 debugfs_remove(dev
->debug
.dent_sensor_val8
);
437 if (dev
->debug
.dent_sensor_val16
)
438 debugfs_remove(dev
->debug
.dent_sensor_val16
);
439 if (dev
->debug
.dent_sensor_val32
)
440 debugfs_remove(dev
->debug
.dent_sensor_val32
);
441 if (dev
->debug
.dent_device
)
442 debugfs_remove(dev
->debug
.dent_device
);
443 kref_put(&debug_ref
, debugfs_delete
);