Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Marvell Bluetooth driver: debugfs related functions
0004  *
0005  * Copyright (C) 2009, Marvell International Ltd.
0006  **/
0007 
0008 #include <linux/debugfs.h>
0009 #include <linux/slab.h>
0010 
0011 #include <net/bluetooth/bluetooth.h>
0012 #include <net/bluetooth/hci_core.h>
0013 
0014 #include "btmrvl_drv.h"
0015 
0016 struct btmrvl_debugfs_data {
0017     struct dentry *config_dir;
0018     struct dentry *status_dir;
0019 };
0020 
0021 static ssize_t btmrvl_hscfgcmd_write(struct file *file,
0022             const char __user *ubuf, size_t count, loff_t *ppos)
0023 {
0024     struct btmrvl_private *priv = file->private_data;
0025     long result, ret;
0026 
0027     ret = kstrtol_from_user(ubuf, count, 10, &result);
0028     if (ret)
0029         return ret;
0030 
0031     priv->btmrvl_dev.hscfgcmd = result;
0032 
0033     if (priv->btmrvl_dev.hscfgcmd) {
0034         btmrvl_prepare_command(priv);
0035         wake_up_interruptible(&priv->main_thread.wait_q);
0036     }
0037 
0038     return count;
0039 }
0040 
0041 static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,
0042                         size_t count, loff_t *ppos)
0043 {
0044     struct btmrvl_private *priv = file->private_data;
0045     char buf[16];
0046     int ret;
0047 
0048     ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
0049                         priv->btmrvl_dev.hscfgcmd);
0050 
0051     return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
0052 }
0053 
0054 static const struct file_operations btmrvl_hscfgcmd_fops = {
0055     .read   = btmrvl_hscfgcmd_read,
0056     .write  = btmrvl_hscfgcmd_write,
0057     .open   = simple_open,
0058     .llseek = default_llseek,
0059 };
0060 
0061 static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
0062                         size_t count, loff_t *ppos)
0063 {
0064     struct btmrvl_private *priv = file->private_data;
0065     long result, ret;
0066 
0067     ret = kstrtol_from_user(ubuf, count, 10, &result);
0068     if (ret)
0069         return ret;
0070 
0071     priv->btmrvl_dev.pscmd = result;
0072 
0073     if (priv->btmrvl_dev.pscmd) {
0074         btmrvl_prepare_command(priv);
0075         wake_up_interruptible(&priv->main_thread.wait_q);
0076     }
0077 
0078     return count;
0079 
0080 }
0081 
0082 static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,
0083                         size_t count, loff_t *ppos)
0084 {
0085     struct btmrvl_private *priv = file->private_data;
0086     char buf[16];
0087     int ret;
0088 
0089     ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.pscmd);
0090 
0091     return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
0092 }
0093 
0094 static const struct file_operations btmrvl_pscmd_fops = {
0095     .read = btmrvl_pscmd_read,
0096     .write = btmrvl_pscmd_write,
0097     .open = simple_open,
0098     .llseek = default_llseek,
0099 };
0100 
0101 static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
0102                         size_t count, loff_t *ppos)
0103 {
0104     struct btmrvl_private *priv = file->private_data;
0105     long result, ret;
0106 
0107     ret = kstrtol_from_user(ubuf, count, 10, &result);
0108     if (ret)
0109         return ret;
0110 
0111     priv->btmrvl_dev.hscmd = result;
0112     if (priv->btmrvl_dev.hscmd) {
0113         btmrvl_prepare_command(priv);
0114         wake_up_interruptible(&priv->main_thread.wait_q);
0115     }
0116 
0117     return count;
0118 }
0119 
0120 static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,
0121                         size_t count, loff_t *ppos)
0122 {
0123     struct btmrvl_private *priv = file->private_data;
0124     char buf[16];
0125     int ret;
0126 
0127     ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hscmd);
0128 
0129     return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
0130 }
0131 
0132 static const struct file_operations btmrvl_hscmd_fops = {
0133     .read   = btmrvl_hscmd_read,
0134     .write  = btmrvl_hscmd_write,
0135     .open   = simple_open,
0136     .llseek = default_llseek,
0137 };
0138 
0139 void btmrvl_debugfs_init(struct hci_dev *hdev)
0140 {
0141     struct btmrvl_private *priv = hci_get_drvdata(hdev);
0142     struct btmrvl_debugfs_data *dbg;
0143 
0144     if (!hdev->debugfs)
0145         return;
0146 
0147     dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
0148     priv->debugfs_data = dbg;
0149 
0150     if (!dbg) {
0151         BT_ERR("Can not allocate memory for btmrvl_debugfs_data.");
0152         return;
0153     }
0154 
0155     dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);
0156 
0157     debugfs_create_u8("psmode", 0644, dbg->config_dir,
0158               &priv->btmrvl_dev.psmode);
0159     debugfs_create_file("pscmd", 0644, dbg->config_dir,
0160                 priv, &btmrvl_pscmd_fops);
0161     debugfs_create_x16("gpiogap", 0644, dbg->config_dir,
0162                &priv->btmrvl_dev.gpio_gap);
0163     debugfs_create_u8("hsmode", 0644, dbg->config_dir,
0164               &priv->btmrvl_dev.hsmode);
0165     debugfs_create_file("hscmd", 0644, dbg->config_dir,
0166                 priv, &btmrvl_hscmd_fops);
0167     debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
0168                 priv, &btmrvl_hscfgcmd_fops);
0169 
0170     dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
0171     debugfs_create_u8("curpsmode", 0444, dbg->status_dir,
0172               &priv->adapter->psmode);
0173     debugfs_create_u8("psstate", 0444, dbg->status_dir,
0174               &priv->adapter->ps_state);
0175     debugfs_create_u8("hsstate", 0444, dbg->status_dir,
0176               &priv->adapter->hs_state);
0177     debugfs_create_u8("txdnldready", 0444, dbg->status_dir,
0178               &priv->btmrvl_dev.tx_dnld_rdy);
0179 }
0180 
0181 void btmrvl_debugfs_remove(struct hci_dev *hdev)
0182 {
0183     struct btmrvl_private *priv = hci_get_drvdata(hdev);
0184     struct btmrvl_debugfs_data *dbg = priv->debugfs_data;
0185 
0186     if (!dbg)
0187         return;
0188 
0189     debugfs_remove_recursive(dbg->config_dir);
0190     debugfs_remove_recursive(dbg->status_dir);
0191 
0192     kfree(dbg);
0193 }