linux/drivers/media/usb/uvc/uvc_debugfs.c
<<
>>
Prefs
   1/*
   2 *      uvc_debugfs.c --  USB Video Class driver - Debugging support
   3 *
   4 *      Copyright (C) 2011
   5 *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   6 *
   7 *      This program is free software; you can redistribute it and/or modify
   8 *      it under the terms of the GNU General Public License as published by
   9 *      the Free Software Foundation; either version 2 of the License, or
  10 *      (at your option) any later version.
  11 *
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/debugfs.h>
  16#include <linux/slab.h>
  17#include <linux/usb.h>
  18
  19#include "uvcvideo.h"
  20
  21/* -----------------------------------------------------------------------------
  22 * Statistics
  23 */
  24
  25#define UVC_DEBUGFS_BUF_SIZE    1024
  26
  27struct uvc_debugfs_buffer {
  28        size_t count;
  29        char data[UVC_DEBUGFS_BUF_SIZE];
  30};
  31
  32static int uvc_debugfs_stats_open(struct inode *inode, struct file *file)
  33{
  34        struct uvc_streaming *stream = inode->i_private;
  35        struct uvc_debugfs_buffer *buf;
  36
  37        buf = kmalloc(sizeof(*buf), GFP_KERNEL);
  38        if (buf == NULL)
  39                return -ENOMEM;
  40
  41        buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data));
  42
  43        file->private_data = buf;
  44        return 0;
  45}
  46
  47static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf,
  48                                      size_t nbytes, loff_t *ppos)
  49{
  50        struct uvc_debugfs_buffer *buf = file->private_data;
  51
  52        return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data,
  53                                       buf->count);
  54}
  55
  56static int uvc_debugfs_stats_release(struct inode *inode, struct file *file)
  57{
  58        kfree(file->private_data);
  59        file->private_data = NULL;
  60
  61        return 0;
  62}
  63
  64static const struct file_operations uvc_debugfs_stats_fops = {
  65        .owner = THIS_MODULE,
  66        .open = uvc_debugfs_stats_open,
  67        .llseek = no_llseek,
  68        .read = uvc_debugfs_stats_read,
  69        .release = uvc_debugfs_stats_release,
  70};
  71
  72/* -----------------------------------------------------------------------------
  73 * Global and stream initialization/cleanup
  74 */
  75
  76static struct dentry *uvc_debugfs_root_dir;
  77
  78int uvc_debugfs_init_stream(struct uvc_streaming *stream)
  79{
  80        struct usb_device *udev = stream->dev->udev;
  81        struct dentry *dent;
  82        char dir_name[32];
  83
  84        if (uvc_debugfs_root_dir == NULL)
  85                return -ENODEV;
  86
  87        sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum);
  88
  89        dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir);
  90        if (IS_ERR_OR_NULL(dent)) {
  91                uvc_printk(KERN_INFO, "Unable to create debugfs %s "
  92                           "directory.\n", dir_name);
  93                return -ENODEV;
  94        }
  95
  96        stream->debugfs_dir = dent;
  97
  98        dent = debugfs_create_file("stats", 0444, stream->debugfs_dir,
  99                                   stream, &uvc_debugfs_stats_fops);
 100        if (IS_ERR_OR_NULL(dent)) {
 101                uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n");
 102                uvc_debugfs_cleanup_stream(stream);
 103                return -ENODEV;
 104        }
 105
 106        return 0;
 107}
 108
 109void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
 110{
 111        if (stream->debugfs_dir == NULL)
 112                return;
 113
 114        debugfs_remove_recursive(stream->debugfs_dir);
 115        stream->debugfs_dir = NULL;
 116}
 117
 118int uvc_debugfs_init(void)
 119{
 120        struct dentry *dir;
 121
 122        dir = debugfs_create_dir("uvcvideo", usb_debug_root);
 123        if (IS_ERR_OR_NULL(dir)) {
 124                uvc_printk(KERN_INFO, "Unable to create debugfs directory\n");
 125                return -ENODATA;
 126        }
 127
 128        uvc_debugfs_root_dir = dir;
 129        return 0;
 130}
 131
 132void uvc_debugfs_cleanup(void)
 133{
 134        if (uvc_debugfs_root_dir != NULL)
 135                debugfs_remove_recursive(uvc_debugfs_root_dir);
 136}
 137