linux/drivers/bluetooth/btmrvl_debugfs.c
<<
>>
Prefs
   1/**
   2 * Marvell Bluetooth driver: debugfs related functions
   3 *
   4 * Copyright (C) 2009, Marvell International Ltd.
   5 *
   6 * This software file (the "File") is distributed by Marvell International
   7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
   8 * (the "License").  You may use, redistribute and/or modify this File in
   9 * accordance with the terms and conditions of the License, a copy of which
  10 * is available by writing to the Free Software Foundation, Inc.,
  11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13 *
  14 *
  15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  17 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  18 * this warranty disclaimer.
  19 **/
  20
  21#include <linux/debugfs.h>
  22#include <linux/slab.h>
  23
  24#include <net/bluetooth/bluetooth.h>
  25#include <net/bluetooth/hci_core.h>
  26
  27#include "btmrvl_drv.h"
  28
  29struct btmrvl_debugfs_data {
  30        struct dentry *config_dir;
  31        struct dentry *status_dir;
  32};
  33
  34static ssize_t btmrvl_hscfgcmd_write(struct file *file,
  35                        const char __user *ubuf, size_t count, loff_t *ppos)
  36{
  37        struct btmrvl_private *priv = file->private_data;
  38        long result, ret;
  39
  40        ret = kstrtol_from_user(ubuf, count, 10, &result);
  41        if (ret)
  42                return ret;
  43
  44        priv->btmrvl_dev.hscfgcmd = result;
  45
  46        if (priv->btmrvl_dev.hscfgcmd) {
  47                btmrvl_prepare_command(priv);
  48                wake_up_interruptible(&priv->main_thread.wait_q);
  49        }
  50
  51        return count;
  52}
  53
  54static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,
  55                                                size_t count, loff_t *ppos)
  56{
  57        struct btmrvl_private *priv = file->private_data;
  58        char buf[16];
  59        int ret;
  60
  61        ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
  62                                                priv->btmrvl_dev.hscfgcmd);
  63
  64        return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
  65}
  66
  67static const struct file_operations btmrvl_hscfgcmd_fops = {
  68        .read   = btmrvl_hscfgcmd_read,
  69        .write  = btmrvl_hscfgcmd_write,
  70        .open   = simple_open,
  71        .llseek = default_llseek,
  72};
  73
  74static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
  75                                                size_t count, loff_t *ppos)
  76{
  77        struct btmrvl_private *priv = file->private_data;
  78        long result, ret;
  79
  80        ret = kstrtol_from_user(ubuf, count, 10, &result);
  81        if (ret)
  82                return ret;
  83
  84        priv->btmrvl_dev.pscmd = result;
  85
  86        if (priv->btmrvl_dev.pscmd) {
  87                btmrvl_prepare_command(priv);
  88                wake_up_interruptible(&priv->main_thread.wait_q);
  89        }
  90
  91        return count;
  92
  93}
  94
  95static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,
  96                                                size_t count, loff_t *ppos)
  97{
  98        struct btmrvl_private *priv = file->private_data;
  99        char buf[16];
 100        int ret;
 101
 102        ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.pscmd);
 103
 104        return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 105}
 106
 107static const struct file_operations btmrvl_pscmd_fops = {
 108        .read = btmrvl_pscmd_read,
 109        .write = btmrvl_pscmd_write,
 110        .open = simple_open,
 111        .llseek = default_llseek,
 112};
 113
 114static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
 115                                                size_t count, loff_t *ppos)
 116{
 117        struct btmrvl_private *priv = file->private_data;
 118        long result, ret;
 119
 120        ret = kstrtol_from_user(ubuf, count, 10, &result);
 121        if (ret)
 122                return ret;
 123
 124        priv->btmrvl_dev.hscmd = result;
 125        if (priv->btmrvl_dev.hscmd) {
 126                btmrvl_prepare_command(priv);
 127                wake_up_interruptible(&priv->main_thread.wait_q);
 128        }
 129
 130        return count;
 131}
 132
 133static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,
 134                                                size_t count, loff_t *ppos)
 135{
 136        struct btmrvl_private *priv = file->private_data;
 137        char buf[16];
 138        int ret;
 139
 140        ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hscmd);
 141
 142        return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 143}
 144
 145static const struct file_operations btmrvl_hscmd_fops = {
 146        .read   = btmrvl_hscmd_read,
 147        .write  = btmrvl_hscmd_write,
 148        .open   = simple_open,
 149        .llseek = default_llseek,
 150};
 151
 152void btmrvl_debugfs_init(struct hci_dev *hdev)
 153{
 154        struct btmrvl_private *priv = hci_get_drvdata(hdev);
 155        struct btmrvl_debugfs_data *dbg;
 156
 157        if (!hdev->debugfs)
 158                return;
 159
 160        dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
 161        priv->debugfs_data = dbg;
 162
 163        if (!dbg) {
 164                BT_ERR("Can not allocate memory for btmrvl_debugfs_data.");
 165                return;
 166        }
 167
 168        dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);
 169
 170        debugfs_create_u8("psmode", 0644, dbg->config_dir,
 171                          &priv->btmrvl_dev.psmode);
 172        debugfs_create_file("pscmd", 0644, dbg->config_dir,
 173                            priv, &btmrvl_pscmd_fops);
 174        debugfs_create_x16("gpiogap", 0644, dbg->config_dir,
 175                           &priv->btmrvl_dev.gpio_gap);
 176        debugfs_create_u8("hsmode", 0644, dbg->config_dir,
 177                          &priv->btmrvl_dev.hsmode);
 178        debugfs_create_file("hscmd", 0644, dbg->config_dir,
 179                            priv, &btmrvl_hscmd_fops);
 180        debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
 181                            priv, &btmrvl_hscfgcmd_fops);
 182
 183        dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
 184        debugfs_create_u8("curpsmode", 0444, dbg->status_dir,
 185                          &priv->adapter->psmode);
 186        debugfs_create_u8("psstate", 0444, dbg->status_dir,
 187                          &priv->adapter->ps_state);
 188        debugfs_create_u8("hsstate", 0444, dbg->status_dir,
 189                          &priv->adapter->hs_state);
 190        debugfs_create_u8("txdnldready", 0444, dbg->status_dir,
 191                          &priv->btmrvl_dev.tx_dnld_rdy);
 192}
 193
 194void btmrvl_debugfs_remove(struct hci_dev *hdev)
 195{
 196        struct btmrvl_private *priv = hci_get_drvdata(hdev);
 197        struct btmrvl_debugfs_data *dbg = priv->debugfs_data;
 198
 199        if (!dbg)
 200                return;
 201
 202        debugfs_remove_recursive(dbg->config_dir);
 203        debugfs_remove_recursive(dbg->status_dir);
 204
 205        kfree(dbg);
 206}
 207