2 * @file microdia-debugfs.c
3 * @author Brian johnson
6 * @brief Debugfs interface for direct device manipulation
8 * @note Copyright (C) Brian Johnson
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/debugfs.h>
28 #include <linux/seq_file.h>
33 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
34 #undef DEFINE_SIMPLE_ATTRIBUTE
35 #define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
36 static void __fops ## _set_wrapper(void *data, __u64 val) \
40 static __u64 __fops ## _get_wrapper(void *data) \
43 __get(data, &value); \
46 static int __fops ## _open(struct inode *inode, struct file *file) \
48 __simple_attr_check_format(__fmt, 0ull); \
49 return simple_attr_open(inode, file, \
50 __fops ## _get_wrapper, \
51 __fops ## _set_wrapper, \
54 static struct file_operations __fops = { \
55 .owner = THIS_MODULE, \
56 .open = __fops ## _open, \
57 .release = simple_attr_close, \
58 .read = simple_attr_read, \
59 .write = simple_attr_write, \
65 * Name of our directory in debugfs
67 static const char *debug_dir_name
= "microdia";
71 * Dentry for our debug dir (for cleanup)
73 static struct dentry
*debug_dir
;
75 struct kref debug_ref
;
78 * debugfs entry for dynamically changing the log level
80 static struct dentry
*dent_log_level
;
82 static int debugfs_u16_set(void *data
, __u64 val
)
88 static int debugfs_u16_get(void *data
, __u64
*val
)
94 static int debugfs_u8_set(void *data
, __u64 val
)
100 static int debugfs_u8_get(void *data
, __u64
*val
)
106 static void *bridge_dump_start(struct seq_file
*m
, loff_t
*pos
)
108 loff_t
*spos
= kmalloc(sizeof(loff_t
), GFP_KERNEL
);
110 return ERR_PTR(-ENOMEM
);
112 if (*pos
< 0 || *pos
> 31)
119 static void *bridge_dump_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
121 loff_t
*spos
= (loff_t
*)v
;
125 return ERR_PTR(-EACCES
);
130 static void bridge_dump_stop(struct seq_file
*m
, void *v
)
137 * @brief Print out the values of registers 0x1000-0x1200 of the bridge
145 static int bridge_dump_show(struct seq_file
*m
, void *v
)
148 loff_t
*spos
= (loff_t
*)v
;
149 __u16 reg
= 0x1000 + (*spos
* 16);
150 struct usb_microdia
*dev
= m
->private;
152 if (usb_microdia_control_read(dev
, reg
, values
, 16) < 0)
155 seq_printf(m
, "0x%X %02X %02X %02X %02X %02X %02X %02X %02X "
156 "%02X %02X %02X %02X %02X %02X %02X %02X\n", reg
,
157 values
[0], values
[1], values
[2], values
[3],
158 values
[4], values
[5], values
[6], values
[7],
159 values
[8], values
[9], values
[10], values
[11],
160 values
[12], values
[13], values
[14], values
[15]);
165 static struct seq_operations bridge_dump_seq_ops
= {
166 .start
= bridge_dump_start
,
167 .next
= bridge_dump_next
,
168 .stop
= bridge_dump_stop
,
169 .show
= bridge_dump_show
172 static int bridge_dump_open(struct inode
*inode
, struct file
*file
)
175 ret
= seq_open(file
, &bridge_dump_seq_ops
);
177 ((struct seq_file
*)file
->private_data
)->private =
182 static struct file_operations bridge_dump_ops
= {
183 .owner
= THIS_MODULE
,
184 .open
= bridge_dump_open
,
187 .release
= seq_release
,
191 * @brief Set the value for a specific register of the bridge
199 int bridge_value_set(void *data
, __u64 val
)
201 struct usb_microdia
*dev
= data
;
202 __u8 value
= (__u64
)val
;
204 if (dev
->debug
.bridge_addr
>= 0x1000 &&
205 dev
->debug
.bridge_addr
<= 0x11ff) {
206 usb_microdia_control_write(dev
,
207 dev
->debug
.bridge_addr
,
215 * @brief Print out the value of a specific register of the bridge
223 int bridge_value_get(void *data
, __u64
*val
)
225 struct usb_microdia
*dev
= data
;
228 if (dev
->debug
.bridge_addr
>= 0x1000 &&
229 dev
->debug
.bridge_addr
<= 0x11ff) {
230 if (usb_microdia_control_read(dev
,
231 dev
->debug
.bridge_addr
,
241 * @brief Set the value (8-bit) for a specific register of the sensor
249 int sensor_value8_set(void *data
, __u64 val
)
251 struct usb_microdia
*dev
= data
;
252 __u8 value
= (__u8
)val
;
254 sn9c20x_write_i2c_data(dev
, 1,
255 dev
->debug
.sensor_addr
,
262 * @brief Print out the value (8-bit) of a specific register of the sensor
270 int sensor_value8_get(void *data
, __u64
*val
)
272 struct usb_microdia
*dev
= data
;
275 if (sn9c20x_read_i2c_data(dev
, 1,
276 dev
->debug
.sensor_addr
,
285 * @brief Set the value (16-bit) for a specific register of the sensor
293 int sensor_value16_set(void *data
, __u64 val
)
295 struct usb_microdia
*dev
= data
;
297 buf
[0] = (val
>> 8) & 0xFF;
300 sn9c20x_write_i2c_data(dev
, 2,
301 dev
->debug
.sensor_addr
,
308 * @brief Print out the value (16-bit) of a specific register of the sensor
316 int sensor_value16_get(void *data
, __u64
*val
)
318 struct usb_microdia
*dev
= data
;
321 if (sn9c20x_read_i2c_data(dev
, 2,
322 dev
->debug
.sensor_addr
,
324 *val
= ((buf
[0] << 8) | buf
[1]) & 0xFFFF;
331 * @brief Set the value (32-bit) for a specific register of the sensor
339 int sensor_value32_set(void *data
, __u64 val
)
341 struct usb_microdia
*dev
= data
;
343 buf
[0] = (val
>> 24) & 0xFF;
344 buf
[1] = (val
>> 16) & 0xFF;
345 buf
[2] = (val
>> 8) & 0xFF;
348 sn9c20x_write_i2c_data(dev
, 4,
349 dev
->debug
.sensor_addr
,
356 * @brief Print out the value (32-bit) of a specific register of the sensor
364 int sensor_value32_get(void *data
, __u64
*val
)
366 struct usb_microdia
*dev
= data
;
369 if (sn9c20x_read_i2c_data(dev
, 4,
370 dev
->debug
.sensor_addr
,
372 *val
= ((buf
[0] << 24) | (buf
[1] << 16)
373 | (buf
[2] << 8) | buf
[3]) & 0xFFFFFFFF;
379 DEFINE_SIMPLE_ATTRIBUTE(fops_x16
,
384 DEFINE_SIMPLE_ATTRIBUTE(fops_x8
,
389 DEFINE_SIMPLE_ATTRIBUTE(bridge_value_ops
,
394 DEFINE_SIMPLE_ATTRIBUTE(sensor_value8_ops
,
399 DEFINE_SIMPLE_ATTRIBUTE(sensor_value16_ops
,
404 DEFINE_SIMPLE_ATTRIBUTE(sensor_value32_ops
,
409 void debugfs_delete(struct kref
*ref
)
412 debugfs_remove(debug_dir
);
415 void microdia_init_debugfs()
417 debug_dir
= debugfs_create_dir(debug_dir_name
, NULL
);
419 dent_log_level
= debugfs_create_u8("log_level",
423 kref_init(&debug_ref
);
427 void microdia_uninit_debugfs()
430 debugfs_remove(dent_log_level
);
431 kref_put(&debug_ref
, debugfs_delete
);
435 * @brief Create the 'debug' entries.
437 * This function permits to create all the entries in the 'debug' filesystem.
439 * @param dev device structure
441 * @returns 0 if all is OK
443 int microdia_create_debugfs_files(struct usb_microdia
*dev
)
447 snprintf(device_name
, 9, "video%d", dev
->vdev
->minor
);
448 dev
->debug
.dent_device
=
449 debugfs_create_dir(device_name
, debug_dir
);
450 if (dev
->debug
.dent_device
) {
451 dev
->debug
.bridge_addr
= 0x1000;
452 dev
->debug
.sensor_addr
= 0x00;
453 dev
->debug
.dent_bridge_addr
=
454 debugfs_create_file("bridge.address",
456 dev
->debug
.dent_device
,
457 &dev
->debug
.bridge_addr
,
459 dev
->debug
.dent_bridge_val
=
460 debugfs_create_file("bridge.value",
462 dev
->debug
.dent_device
,
463 dev
, &bridge_value_ops
);
464 dev
->debug
.dent_bridge_dump
=
465 debugfs_create_file("bridge.dump",
467 dev
->debug
.dent_device
,
468 dev
, &bridge_dump_ops
);
469 dev
->debug
.dent_sensor_addr
=
470 debugfs_create_file("sensor.address",
472 dev
->debug
.dent_device
,
473 &dev
->debug
.sensor_addr
,
475 dev
->debug
.dent_sensor_val8
=
476 debugfs_create_file("sensor.value8",
478 dev
->debug
.dent_device
,
479 dev
, &sensor_value8_ops
);
480 dev
->debug
.dent_sensor_val16
=
481 debugfs_create_file("sensor.value16",
483 dev
->debug
.dent_device
,
484 dev
, &sensor_value16_ops
);
485 dev
->debug
.dent_sensor_val32
=
486 debugfs_create_file("sensor.value32",
488 dev
->debug
.dent_device
,
489 dev
, &sensor_value32_ops
);
492 kref_get(&debug_ref
);
497 * @brief Remove the 'debugfs' entries.
499 * This function permits to remove all the entries in the 'debug' filesystem.
501 * @param dev device structure
503 * @returns 0 if all is OK
505 int microdia_remove_debugfs_files(struct usb_microdia
*dev
)
507 if (dev
->debug
.dent_bridge_val
)
508 debugfs_remove(dev
->debug
.dent_bridge_val
);
509 if (dev
->debug
.dent_bridge_addr
)
510 debugfs_remove(dev
->debug
.dent_bridge_addr
);
511 if (dev
->debug
.dent_bridge_dump
)
512 debugfs_remove(dev
->debug
.dent_bridge_dump
);
513 if (dev
->debug
.dent_sensor_addr
)
514 debugfs_remove(dev
->debug
.dent_sensor_addr
);
515 if (dev
->debug
.dent_sensor_val8
)
516 debugfs_remove(dev
->debug
.dent_sensor_val8
);
517 if (dev
->debug
.dent_sensor_val16
)
518 debugfs_remove(dev
->debug
.dent_sensor_val16
);
519 if (dev
->debug
.dent_sensor_val32
)
520 debugfs_remove(dev
->debug
.dent_sensor_val32
);
521 if (dev
->debug
.dent_device
)
522 debugfs_remove(dev
->debug
.dent_device
);
523 kref_put(&debug_ref
, debugfs_delete
);