Path: blob/master/drivers/bluetooth/btmrvl_debugfs.c
15112 views
/**1* Marvell Bluetooth driver: debugfs related functions2*3* Copyright (C) 2009, Marvell International Ltd.4*5* This software file (the "File") is distributed by Marvell International6* Ltd. under the terms of the GNU General Public License Version 2, June 19917* (the "License"). You may use, redistribute and/or modify this File in8* accordance with the terms and conditions of the License, a copy of which9* is available by writing to the Free Software Foundation, Inc.,10* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the11* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.12*13*14* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE15* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE16* ARE EXPRESSLY DISCLAIMED. The License provides additional details about17* this warranty disclaimer.18**/1920#include <linux/debugfs.h>21#include <linux/slab.h>2223#include <net/bluetooth/bluetooth.h>24#include <net/bluetooth/hci_core.h>2526#include "btmrvl_drv.h"2728struct btmrvl_debugfs_data {29struct dentry *config_dir;30struct dentry *status_dir;3132/* config */33struct dentry *psmode;34struct dentry *pscmd;35struct dentry *hsmode;36struct dentry *hscmd;37struct dentry *gpiogap;38struct dentry *hscfgcmd;3940/* status */41struct dentry *curpsmode;42struct dentry *hsstate;43struct dentry *psstate;44struct dentry *txdnldready;45};4647static int btmrvl_open_generic(struct inode *inode, struct file *file)48{49file->private_data = inode->i_private;50return 0;51}5253static ssize_t btmrvl_hscfgcmd_write(struct file *file,54const char __user *ubuf, size_t count, loff_t *ppos)55{56struct btmrvl_private *priv = file->private_data;57char buf[16];58long result, ret;5960memset(buf, 0, sizeof(buf));6162if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))63return -EFAULT;6465ret = strict_strtol(buf, 10, &result);66if (ret)67return ret;6869priv->btmrvl_dev.hscfgcmd = result;7071if (priv->btmrvl_dev.hscfgcmd) {72btmrvl_prepare_command(priv);73wake_up_interruptible(&priv->main_thread.wait_q);74}7576return count;77}7879static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,80size_t count, loff_t *ppos)81{82struct btmrvl_private *priv = file->private_data;83char buf[16];84int ret;8586ret = snprintf(buf, sizeof(buf) - 1, "%d\n",87priv->btmrvl_dev.hscfgcmd);8889return simple_read_from_buffer(userbuf, count, ppos, buf, ret);90}9192static const struct file_operations btmrvl_hscfgcmd_fops = {93.read = btmrvl_hscfgcmd_read,94.write = btmrvl_hscfgcmd_write,95.open = btmrvl_open_generic,96.llseek = default_llseek,97};9899static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,100size_t count, loff_t *ppos)101{102struct btmrvl_private *priv = file->private_data;103char buf[16];104long result, ret;105106memset(buf, 0, sizeof(buf));107108if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))109return -EFAULT;110111ret = strict_strtol(buf, 10, &result);112if (ret)113return ret;114115priv->btmrvl_dev.psmode = result;116117return count;118}119120static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf,121size_t count, loff_t *ppos)122{123struct btmrvl_private *priv = file->private_data;124char buf[16];125int ret;126127ret = snprintf(buf, sizeof(buf) - 1, "%d\n",128priv->btmrvl_dev.psmode);129130return simple_read_from_buffer(userbuf, count, ppos, buf, ret);131}132133static const struct file_operations btmrvl_psmode_fops = {134.read = btmrvl_psmode_read,135.write = btmrvl_psmode_write,136.open = btmrvl_open_generic,137.llseek = default_llseek,138};139140static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,141size_t count, loff_t *ppos)142{143struct btmrvl_private *priv = file->private_data;144char buf[16];145long result, ret;146147memset(buf, 0, sizeof(buf));148149if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))150return -EFAULT;151152ret = strict_strtol(buf, 10, &result);153if (ret)154return ret;155156priv->btmrvl_dev.pscmd = result;157158if (priv->btmrvl_dev.pscmd) {159btmrvl_prepare_command(priv);160wake_up_interruptible(&priv->main_thread.wait_q);161}162163return count;164165}166167static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,168size_t count, loff_t *ppos)169{170struct btmrvl_private *priv = file->private_data;171char buf[16];172int ret;173174ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.pscmd);175176return simple_read_from_buffer(userbuf, count, ppos, buf, ret);177}178179static const struct file_operations btmrvl_pscmd_fops = {180.read = btmrvl_pscmd_read,181.write = btmrvl_pscmd_write,182.open = btmrvl_open_generic,183.llseek = default_llseek,184};185186static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,187size_t count, loff_t *ppos)188{189struct btmrvl_private *priv = file->private_data;190char buf[16];191long result, ret;192193memset(buf, 0, sizeof(buf));194195if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))196return -EFAULT;197198ret = strict_strtol(buf, 16, &result);199if (ret)200return ret;201202priv->btmrvl_dev.gpio_gap = result;203204return count;205}206207static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf,208size_t count, loff_t *ppos)209{210struct btmrvl_private *priv = file->private_data;211char buf[16];212int ret;213214ret = snprintf(buf, sizeof(buf) - 1, "0x%x\n",215priv->btmrvl_dev.gpio_gap);216217return simple_read_from_buffer(userbuf, count, ppos, buf, ret);218}219220static const struct file_operations btmrvl_gpiogap_fops = {221.read = btmrvl_gpiogap_read,222.write = btmrvl_gpiogap_write,223.open = btmrvl_open_generic,224.llseek = default_llseek,225};226227static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,228size_t count, loff_t *ppos)229{230struct btmrvl_private *priv = file->private_data;231char buf[16];232long result, ret;233234memset(buf, 0, sizeof(buf));235236if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))237return -EFAULT;238239ret = strict_strtol(buf, 10, &result);240if (ret)241return ret;242243priv->btmrvl_dev.hscmd = result;244if (priv->btmrvl_dev.hscmd) {245btmrvl_prepare_command(priv);246wake_up_interruptible(&priv->main_thread.wait_q);247}248249return count;250}251252static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,253size_t count, loff_t *ppos)254{255struct btmrvl_private *priv = file->private_data;256char buf[16];257int ret;258259ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hscmd);260261return simple_read_from_buffer(userbuf, count, ppos, buf, ret);262}263264static const struct file_operations btmrvl_hscmd_fops = {265.read = btmrvl_hscmd_read,266.write = btmrvl_hscmd_write,267.open = btmrvl_open_generic,268.llseek = default_llseek,269};270271static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,272size_t count, loff_t *ppos)273{274struct btmrvl_private *priv = file->private_data;275char buf[16];276long result, ret;277278memset(buf, 0, sizeof(buf));279280if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))281return -EFAULT;282283ret = strict_strtol(buf, 10, &result);284if (ret)285return ret;286287priv->btmrvl_dev.hsmode = result;288289return count;290}291292static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf,293size_t count, loff_t *ppos)294{295struct btmrvl_private *priv = file->private_data;296char buf[16];297int ret;298299ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hsmode);300301return simple_read_from_buffer(userbuf, count, ppos, buf, ret);302}303304static const struct file_operations btmrvl_hsmode_fops = {305.read = btmrvl_hsmode_read,306.write = btmrvl_hsmode_write,307.open = btmrvl_open_generic,308.llseek = default_llseek,309};310311static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,312size_t count, loff_t *ppos)313{314struct btmrvl_private *priv = file->private_data;315char buf[16];316int ret;317318ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->psmode);319320return simple_read_from_buffer(userbuf, count, ppos, buf, ret);321}322323static const struct file_operations btmrvl_curpsmode_fops = {324.read = btmrvl_curpsmode_read,325.open = btmrvl_open_generic,326.llseek = default_llseek,327};328329static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,330size_t count, loff_t *ppos)331{332struct btmrvl_private *priv = file->private_data;333char buf[16];334int ret;335336ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->ps_state);337338return simple_read_from_buffer(userbuf, count, ppos, buf, ret);339}340341static const struct file_operations btmrvl_psstate_fops = {342.read = btmrvl_psstate_read,343.open = btmrvl_open_generic,344.llseek = default_llseek,345};346347static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,348size_t count, loff_t *ppos)349{350struct btmrvl_private *priv = file->private_data;351char buf[16];352int ret;353354ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->hs_state);355356return simple_read_from_buffer(userbuf, count, ppos, buf, ret);357}358359static const struct file_operations btmrvl_hsstate_fops = {360.read = btmrvl_hsstate_read,361.open = btmrvl_open_generic,362.llseek = default_llseek,363};364365static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,366size_t count, loff_t *ppos)367{368struct btmrvl_private *priv = file->private_data;369char buf[16];370int ret;371372ret = snprintf(buf, sizeof(buf) - 1, "%d\n",373priv->btmrvl_dev.tx_dnld_rdy);374375return simple_read_from_buffer(userbuf, count, ppos, buf, ret);376}377378static const struct file_operations btmrvl_txdnldready_fops = {379.read = btmrvl_txdnldready_read,380.open = btmrvl_open_generic,381.llseek = default_llseek,382};383384void btmrvl_debugfs_init(struct hci_dev *hdev)385{386struct btmrvl_private *priv = hdev->driver_data;387struct btmrvl_debugfs_data *dbg;388389if (!hdev->debugfs)390return;391392dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);393priv->debugfs_data = dbg;394395if (!dbg) {396BT_ERR("Can not allocate memory for btmrvl_debugfs_data.");397return;398}399400dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);401402dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,403hdev->driver_data, &btmrvl_psmode_fops);404dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir,405hdev->driver_data, &btmrvl_pscmd_fops);406dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir,407hdev->driver_data, &btmrvl_gpiogap_fops);408dbg->hsmode = debugfs_create_file("hsmode", 0644, dbg->config_dir,409hdev->driver_data, &btmrvl_hsmode_fops);410dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir,411hdev->driver_data, &btmrvl_hscmd_fops);412dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,413hdev->driver_data, &btmrvl_hscfgcmd_fops);414415dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);416dbg->curpsmode = debugfs_create_file("curpsmode", 0444,417dbg->status_dir,418hdev->driver_data,419&btmrvl_curpsmode_fops);420dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir,421hdev->driver_data, &btmrvl_psstate_fops);422dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir,423hdev->driver_data, &btmrvl_hsstate_fops);424dbg->txdnldready = debugfs_create_file("txdnldready", 0444,425dbg->status_dir,426hdev->driver_data,427&btmrvl_txdnldready_fops);428}429430void btmrvl_debugfs_remove(struct hci_dev *hdev)431{432struct btmrvl_private *priv = hdev->driver_data;433struct btmrvl_debugfs_data *dbg = priv->debugfs_data;434435if (!dbg)436return;437438debugfs_remove(dbg->psmode);439debugfs_remove(dbg->pscmd);440debugfs_remove(dbg->gpiogap);441debugfs_remove(dbg->hsmode);442debugfs_remove(dbg->hscmd);443debugfs_remove(dbg->hscfgcmd);444debugfs_remove(dbg->config_dir);445446debugfs_remove(dbg->curpsmode);447debugfs_remove(dbg->psstate);448debugfs_remove(dbg->hsstate);449debugfs_remove(dbg->txdnldready);450debugfs_remove(dbg->status_dir);451452kfree(dbg);453}454455456