0
0
Fork 0
hgicf/hgic_fmac/procfs.c

1209 lines
45 KiB
C
Raw Normal View History

2023-05-16 09:13:19 +00:00
#include <linux/version.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wireless.h>
#include "hgicf.h"
#include "cfg.h"
#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 16, 0)
#define PDE_DATA(inode) pde_data(inode)
#endif
2023-05-16 09:13:19 +00:00
static int hgicf_signal_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d\r\n", hg->status.signal);
return 0;
}
static int hgicf_signal_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_signal_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_signal = {
.proc_open = hgicf_signal_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_evm_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d\r\n", hg->status.evm);
return 0;
}
static int hgicf_evm_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_evm_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_evm = {
.proc_open = hgicf_evm_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_conn_state_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if (hg->sta) {
hg->sta->hw_state = hgic_fwctrl_get_conn_state(&hg->ctrl);
seq_printf(seq, "%s\r\n", hgicf_hw_state(hg->sta->hw_state));
} else {
seq_printf(seq, "CONNECTED\r\n");
}
return 0;
}
static int hgicf_conn_state_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_conn_state_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_conn_state = {
.proc_open = hgicf_conn_state_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_txrate_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d\r\n", hg->status.tx_bitrate);
return 0;
}
static int hgicf_txrate_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_txrate_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_txrate = {
.proc_open = hgicf_txrate_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_testmode_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%s\r\n", hg->proc.testmode_buf);
return 0;
}
static int hgicf_testmode_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_testmode_show, PDE_DATA(inode));
}
static ssize_t hgicf_testmode_send_cmd(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
memset(hg->proc.testmode_buf, 0, HGIC_TESTMODE_BUFF_SIZE);
ret = copy_from_user(hg->proc.testmode_buf, buffer, count);
hgic_fwctrl_testmode_cmd(&hg->ctrl, hg->proc.testmode_buf, HGIC_TESTMODE_BUFF_SIZE);
return ret ? -EINVAL : count;
}
static const struct proc_ops hgicf_pops_testmode = {
.proc_open = hgicf_testmode_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_testmode_send_cmd,
.proc_release = single_release,
};
////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_status_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "fw info:%d.%d.%d.%d, svn version:%d, bootdl:%d\r\n",
(hg->fwinfo.version >> 24) & 0xff, (hg->fwinfo.version >> 16) & 0xff,
(hg->fwinfo.version >> 8) & 0xff, (hg->fwinfo.version & 0xff),
hg->fwinfo.svn_version, test_bit(HGICF_DEV_FLAGS_BOOTDL, &hg->flags));
return 0;
}
static int hgicf_status_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_status_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_status = {
.proc_open = hgicf_status_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_ota_show(struct seq_file *seq, void *v)
{
seq_printf(seq, "Enter OTA,SDK Version:20200402\r\n");
return 0;
}
static int hgicf_ota_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_ota_show, PDE_DATA(inode));
}
static ssize_t hgicf_ota_send_data(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
ssize_t ret = -1;
char *fw_path = NULL;
char *ptr = NULL;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if (file == NULL || buffer == NULL || seq == NULL || hg == NULL) {
hgic_dbg("%s: Input para error!\r\n", __FUNCTION__);
return -EINVAL;
}
fw_path = kzalloc(count + 1, GFP_KERNEL);
if (!fw_path) {
return -ENOMEM;
}
ret = copy_from_user(fw_path, buffer, count);
if (ret) {
hgic_dbg("%s: Error:copy_from_user:fw_path failed!\r\n", __FUNCTION__);
kfree(fw_path);
return -EFAULT;
}
ptr = &fw_path[count - 1];
while (*ptr == '\r' || *ptr == '\n') { *ptr-- = 0; }
hgic_dbg("ota firmware: %s\r\n", fw_path);
ret = hgic_ota_send_fw(&hg->ota, fw_path, HG_OTA_WRITE_MEM_TMO);
kfree(fw_path);
return (ret ? -EIO : count);
}
static const struct proc_ops hgicf_pops_ota = {
.proc_open = hgicf_ota_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_ota_send_data,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_temperature_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
int temp = hgic_fwctrl_get_temperature(&hg->ctrl);
if (temp < 0) { temp = 0; }
seq_printf(seq, "%d\r\n", temp);
return 0;
}
static int hgicf_temperature_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_temperature_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_temperature = {
.proc_open = hgicf_temperature_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_sleep_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d\r\n", test_bit(HGIC_BUS_FLAGS_SLEEP, &hg->bus->flags));
return 0;
}
static int hgicf_sleep_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_sleep_show, PDE_DATA(inode));
}
static ssize_t hgicf_enter_sleep(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int err = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u8 str[2] = {0, 0};
int sleep = 0;
err = copy_from_user(str, buffer, 1);
sleep = simple_strtol(str, 0, 10);
hgic_dbg("enter sleep :%d ...\r\n", sleep);
if (sleep) {
if(!test_bit(HGIC_BUS_FLAGS_SLEEP, &hg->bus->flags)){
err = hgic_fwctrl_enter_sleep(&hg->ctrl, 1);
if (!err) {
set_bit(HGIC_BUS_FLAGS_SLEEP, &hg->bus->flags);
}else{
hgic_err("sleep fail, ret=%d\r\n", err);
}
}
} else {
if(test_bit(HGIC_BUS_FLAGS_SLEEP, &hg->bus->flags)){
clear_bit(HGIC_BUS_FLAGS_SLEEP, &hg->bus->flags);
if (hg->bus->reinit) {
hg->bus->reinit(hg->bus);
}
err = hgic_fwctrl_enter_sleep(&hg->ctrl, 0);
if(err) hgic_err("exit sleep fail, ret=%d\r\n", err);
}
}
return count;
}
static const struct proc_ops hgicf_pops_sleep = {
.proc_open = hgicf_sleep_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_enter_sleep,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_iwpriv_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%s\r\n", hg->proc.iwpriv_buf);
memset(hg->proc.iwpriv_buf, 0, sizeof(hg->proc.iwpriv_buf));
return 0;
}
static int hgicf_iwpriv_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_iwpriv_show, PDE_DATA(inode));
}
static ssize_t hgicf_iwpriv_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
int i = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
char *cmd_buf = kzalloc(count + 1, GFP_KERNEL);
char *ifname, *cmd, *args;
struct iwreq wrqin;
struct net_device *ndev = NULL;
if (count <= 0) { return -1; }
memset(hg->proc.iwpriv_buf, 0, sizeof(hg->proc.iwpriv_buf));
if (cmd_buf) {
i = count - 1;
ret = copy_from_user(cmd_buf, buffer, count);
while (i >= 0 && (cmd_buf[i] == '\r' || cmd_buf[i] == '\n')) {
cmd_buf[i--] = 0;
}
ifname = cmd_buf;
cmd = strchr(ifname, ' ');
if (cmd == NULL) {
sprintf(hg->proc.iwpriv_buf, "invalid paramters:%s", cmd_buf);
goto __out;
}
*cmd++ = 0;
args = strchr(cmd, ' ');
if (args) { *args++ = 0; }
//hgic_dbg("ifname:%s, cmd:%s, args:%s\r\n", ifname, cmd, args);
if (hg->sta && strcmp(hg->sta->ndev->name, ifname) == 0) {
ndev = hg->sta->ndev;
} else if (hg->ap && strcmp(hg->ap->ndev->name, ifname) == 0) {
ndev = hg->ap->ndev;
} else {
strcpy(hg->proc.iwpriv_buf, "no such device");
goto __out;
}
memset(&wrqin, 0, sizeof(wrqin));
if (strcasecmp(cmd, "set") == 0) {
wrqin.u.data.pointer = args;
wrqin.u.data.length = args ? strlen(args) : 0;
ret = hgicf_ioctl_set_proc(ndev, &wrqin);
if (ret) {
sprintf(hg->proc.iwpriv_buf, "%s error:%d", args, ret);
} else {
sprintf(hg->proc.iwpriv_buf, "%s OK", args);
}
} else if (strcasecmp(cmd, "get") == 0 && args) {
wrqin.u.data.pointer = hg->proc.iwpriv_buf;
wrqin.u.data.length = strlen(args);
strcpy(hg->proc.iwpriv_buf, args);
ret = hgicf_ioctl_get_proc(ndev, &wrqin);
} else if (strcasecmp(cmd, "scan") == 0) {
wrqin.u.data.pointer = hg->proc.iwpriv_buf;
ret = hgicf_ioctl_scan(ndev, &wrqin);
strcpy(hg->proc.iwpriv_buf, ret ? "Fail" : "OK");
} else if (strcasecmp(cmd, "save") == 0) {
ret = hgicf_ioctl_savecfg(ndev, &wrqin);
strcpy(hg->proc.iwpriv_buf, ret ? "Fail" : "OK");
} else if (strcasecmp(cmd, "stat") == 0) {
wrqin.u.data.pointer = hg->proc.iwpriv_buf;
ret = hgicf_ioctl_stat(ndev, &wrqin);
} else if (strcasecmp(cmd, "e2p") == 0) {
strcpy(hg->proc.iwpriv_buf, "not support now");
} else {
strcpy(hg->proc.iwpriv_buf, "invalid parameters");
}
} else {
strcpy(hg->proc.iwpriv_buf, "no memory");
}
__out:
if (cmd_buf) {
kfree(cmd_buf);
}
return ret ? -EINVAL : count;
}
static const struct proc_ops hgicf_pops_iwpriv = {
.proc_open = hgicf_iwpriv_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_iwpriv_write,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_paired_stas_show(struct seq_file *seq, void *v)
{
int i = 0;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if (hg->paired_stas && hg->paired_stas_cnt) {
for (i = 0; i < hg->paired_stas_cnt; i++) {
seq_printf(seq, "%pM", hg->paired_stas + i * 6);
}
}
return 0;
}
static int hgicf_paired_stas_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_paired_stas_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_paired_stas = {
.proc_open = hgicf_paired_stas_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_radio_off_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "Radio %s\r\n", hg->radio_off ? "OFF" : "ON");
return 0;
}
static int hgicf_radio_off_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_radio_off_show, PDE_DATA(inode));
}
static ssize_t hgicf_radio_off_config(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u8 str[2] = {0, 0};
ret = copy_from_user(str, buffer, 1);
if(ret)
return -EINVAL;
hg->radio_off = simple_strtol(str, 0, 10);
hgic_dbg("radio %s \r\n", hg->radio_off ? "OFF" : "ON");
if (hg->radio_off) {
hgic_fwctrl_close_dev(&hg->ctrl);
} else {
hgic_fwctrl_open_dev(&hg->ctrl);
}
return count;
}
static const struct proc_ops hgicf_pops_radio_off = {
.proc_open = hgicf_radio_off_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_radio_off_config,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_sta_count_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d\r\n", hgic_fwctrl_get_sta_count(&hg->ctrl));
return 0;
}
static int hgicf_sta_count_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_sta_count_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_sta_count = {
.proc_open = hgicf_sta_count_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_ps_heartbeat_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_ps_heartbeat_set(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u8 str[32];
u32 ip[4] = {0};
u32 port = 0;
u32 ipaddr = 0;
u32 period = 0;
u32 hb_tmo = 300;
memset(str, 0, sizeof(str));
ret = copy_from_user(str, buffer, count > 32 ? 32 : count);
if(ret)
return -EINVAL;
sscanf(str, "%d.%d.%d.%d,%d,%d,%d", &ip[0], &ip[1], &ip[2], &ip[3], &port, &period, &hb_tmo);
ipaddr = ((ip[0] & 0xff) << 24) | ((ip[1] & 0xff) << 16) | (((ip[2] & 0xff) << 8)) | (ip[3] & 0xff);
hgic_fwctrl_set_ps_heartbeat(&hg->ctrl, ipaddr, port, period, hb_tmo);
return count;
}
static const struct proc_ops hgicf_pops_ps_heartbeat = {
.proc_open = hgicf_ps_heartbeat_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_ps_heartbeat_set,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_ps_heartbeat_resp_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_ps_heartbeat_resp_set(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u8 *ptr = kzalloc(count, GFP_KERNEL);
if (ptr) {
ret = copy_from_user(ptr, buffer, count);
if(!ret)
ret = hgic_fwctrl_set_ps_heartbeat_resp(&hg->ctrl, ptr, count);
kfree(ptr);
}
return ret ? -EINVAL: count;
}
static const struct proc_ops hgicf_pops_ps_heartbeat_resp = {
.proc_open = hgicf_ps_heartbeat_resp_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_ps_heartbeat_resp_set,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_ps_wakeup_data_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_ps_wakeup_data_set(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u8 *ptr = kzalloc(count, GFP_KERNEL);
if (ptr) {
ret = copy_from_user(ptr, buffer, count);
if(!ret){
ret = hgic_fwctrl_set_ps_wakeup_data(&hg->ctrl, ptr, count);
}
kfree(ptr);
}
return ret ? -EINVAL: count;
}
static const struct proc_ops hgicf_pops_ps_wakeup_data = {
.proc_open = hgicf_ps_wakeup_data_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_ps_wakeup_data_set,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_wakeup_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_wakeup_sta(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
u8 addr[6];
u8 addr_str[32];
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
ret = copy_from_user(addr_str, buffer, count > 32 ? 32 : count);
if(ret) return -EINVAL;
if (!hgic_pick_macaddr(addr_str, addr)) {
memset(addr, 0, 6);
}
ret = hgic_fwctrl_wakeup_sta(&hg->ctrl, addr);
return ret ? -EINVAL : count;
}
static const struct proc_ops hgicf_pops_wakeup = {
.proc_open = hgicf_wakeup_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_wakeup_sta,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_pair_state_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d\r\n", hg->status.pair_state);
return 0;
}
static int hgicf_pair_state_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_pair_state_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_pair_state = {
.proc_open = hgicf_pair_state_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_fw_ver_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%d.%d.%d.%d-%d\r\n",
(hg->fwinfo.version >> 24) & 0xff, (hg->fwinfo.version >> 16) & 0xff,
(hg->fwinfo.version >> 8) & 0xff, (hg->fwinfo.version & 0xff),
hg->fwinfo.svn_version);
return 0;
}
static int hgicf_fw_ver_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_fw_ver_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_fw_ver = {
.proc_open = hgicf_fw_ver_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_wkreason_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
int reason = hgic_fwctrl_get_wkreason(&hg->ctrl);
seq_printf(seq, "%d\r\n", reason);
return 0;
}
static int hgicf_wkreason_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_wkreason_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_wkreason = {
.proc_open = hgicf_wkreason_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_fwevent_show(struct seq_file *seq, void *v)
{
u8 event = 0;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if(down_timeout(&hg->evtq.sema, msecs_to_jiffies(100)))
return 0;
FWEVTQ_GET(&hg->evtq, event);
seq_printf(seq, "%d\r\n", event);
return 0;
}
static int hgicf_fwevent_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_fwevent_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_fwevent = {
.proc_open = hgicf_fwevent_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_mgmt_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_send_mgmt(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
u8 *buff;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
buff = kzalloc(count+1, GFP_KERNEL);
if(buff == NULL)
return -ENOMEM;
ret = copy_from_user(buff, buffer, count);
if(!ret)
ret = hgic_fwctrl_send_cust_mgmt(&hg->ctrl, buff, count);
kfree(buff);
return ret ? -EINVAL : count;
}
static ssize_t hgicf_mgmt_read(struct file *file, char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct sk_buff *skb = NULL;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if(!skb_queue_empty(&hg->custmgmt_q)){
skb = skb_dequeue(&hg->custmgmt_q);
if(skb){
ret = copy_to_user(buffer, skb->data, skb->len);
kfree(skb);
}
}
return ret;
}
static const struct proc_ops hgicf_pops_mgmt = {
.proc_open = hgicf_mgmt_open,
.proc_read = hgicf_mgmt_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_send_mgmt,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_battery_level_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
int soc = hgic_fwctrl_get_battery_level(&hg->ctrl);
seq_printf(seq, "%d\r\n", soc);
return 0;
}
static int hgicf_battery_level_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_battery_level_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_battery_level = {
.proc_open = hgicf_battery_level_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_fwdbginfo_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
struct sk_buff *skb = skb_dequeue(&hg->dbginfo_q);
if(skb){
seq_printf(seq, "%s", skb->data);
}
return 0;
}
static int hgicf_fwdbginfo_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_fwdbginfo_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_fwdbginfo = {
.proc_open = hgicf_fwdbginfo_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_pairing_sta_show(struct seq_file *seq, void *v)
{
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
seq_printf(seq, "%pM", hg->pairing_sta);
return 0;
}
static int hgicf_pairing_sta_open(struct inode *inode, struct file *file)
{
return single_open(file, hgicf_pairing_sta_show, PDE_DATA(inode));
}
static const struct proc_ops hgicf_pops_pairing_sta = {
.proc_open = hgicf_pairing_sta_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_dhcpc_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_dhcpc_read(struct file *file, char __user *buffer,
size_t count, loff_t *data)
{
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
return copy_to_user(buffer, &hg->dhcpc, sizeof(hg->dhcpc));
}
static const struct proc_ops hgicf_pops_dhcpc = {
.proc_open = hgicf_dhcpc_open,
.proc_read = hgicf_dhcpc_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_wkdata_buff_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_wkdata_buff_read(struct file *file, char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u8 *buff = (u8 *)kzalloc(1600, GFP_KERNEL);
if(buff){
ret = hgic_fwctrl_get_wkdata_buff(&hg->ctrl, buff, 1600);
if(ret > 0){
ret = copy_to_user(buffer, buff, ret);
//printk("wkdata buff:%d\r\n", ret);
}
kfree(buff);
return ret;
}
return -ENOMEM;
}
static const struct proc_ops hgicf_pops_wkdata_buff = {
.proc_open = hgicf_wkdata_buff_open,
.proc_read = hgicf_wkdata_buff_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_ps_wkdata_mask_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_ps_wkdata_mask_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
u16 buff[64];
u8 len = count>128 ? 128 : count;
ret = copy_from_user((u8 *)buff, buffer, len);
if(!ret){
ret = hgic_fwctrl_set_wkdata_mask(&hg->ctrl, buff[0], (u8 *)(buff+1), len - 2);
}
return ret ? -EINVAL : count;
}
static const struct proc_ops hgicf_pops_wkdata_mask = {
.proc_open = hgicf_ps_wkdata_mask_open,
.proc_write = hgicf_ps_wkdata_mask_write,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_cust_driverdata_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_cust_driverdata_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
u8 *buff;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if(count > 1500) count = 1500;
buff = kzalloc(count+1, GFP_KERNEL);
if(buff == NULL)
return -ENOMEM;
ret = copy_from_user(buff, buffer, count);
if(!ret)
ret = hgic_fwctrl_set_cust_driver_data(&hg->ctrl, buff, count);
kfree(buff);
return ret ? -EINVAL : count;
}
static ssize_t hgicf_cust_driverdata_read(struct file *file, char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
struct sk_buff *skb = NULL;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
if(!skb_queue_empty(&hg->cust_driverdata_q)){
skb = skb_dequeue(&hg->cust_driverdata_q);
if(skb){
ret = copy_to_user(buffer, skb->data, skb->len);
kfree(skb);
}
}
return ret;
}
static const struct proc_ops hgicf_pops_cust_driverdata = {
.proc_open = hgicf_cust_driverdata_open,
.proc_read = hgicf_cust_driverdata_read,
.proc_lseek = seq_lseek,
.proc_write = hgicf_cust_driverdata_write,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
static int hgicf_freqinfo_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, PDE_DATA(inode));
}
static ssize_t hgicf_freqinfo_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
int ret = 0;
u8 *buff;
struct seq_file *seq = (struct seq_file *)file->private_data;
struct hgicf_wdev *hg = (struct hgicf_wdev *)seq->private;
buff = kzalloc(count+1, GFP_KERNEL);
if(buff == NULL)
return -ENOMEM;
ret = copy_from_user(buff, buffer, count);
if(!ret)
ret = hgic_fwctrl_set_freqinfo(&hg->ctrl, buff, count);
kfree(buff);
return ret ? -EINVAL : count;
}
static const struct proc_ops hgicf_pops_freqinfo = {
.proc_open = hgicf_freqinfo_open,
.proc_lseek = seq_lseek,
.proc_write = hgicf_freqinfo_write,
.proc_release = single_release,
};
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
void hgicf_create_procfs(struct hgicf_wdev *hg)
{
hgic_dbg("enter\r\n");
hg->proc.rootdir = proc_mkdir("hgic", NULL);
if (hg->proc.rootdir == NULL) {
hgic_err("create proc dir: hgic failed\r\n");
return;
}
hg->proc.tx_bitrate = proc_create_data("tx_bitrate", 0x0444,
hg->proc.rootdir, &hgicf_pops_txrate, hg);
if (hg->proc.tx_bitrate == NULL) {
hgic_err("create proc file: tx_bitrate failed\r\n");
}
hg->proc.testmode = proc_create_data("testmode", 0x0666,
hg->proc.rootdir, &hgicf_pops_testmode, hg);
if (hg->proc.testmode == NULL) {
hgic_err("create proc file: testmode failed\r\n");
}
hg->proc.status = proc_create_data("status", 0x0444,
hg->proc.rootdir, &hgicf_pops_status, hg);
if (hg->proc.status == NULL) {
hgic_err("create proc file: status failed\r\n");
}
hg->proc.signal = proc_create_data("signal", 0x0444,
hg->proc.rootdir, &hgicf_pops_signal, hg);
if (hg->proc.signal == NULL) {
hgic_err("create proc file: signal failed\r\n");
}
hg->proc.evm = proc_create_data("evm", 0x0444,
hg->proc.rootdir, &hgicf_pops_evm, hg);
if (hg->proc.evm == NULL) {
hgic_err("create proc file: evm failed\r\n");
}
hg->proc.conn_state = proc_create_data("conn_state", 0x0444,
hg->proc.rootdir, &hgicf_pops_conn_state, hg);
if (hg->proc.conn_state == NULL) {
hgic_err("create proc file: conn_state failed\r\n");
}
hg->proc.ota = proc_create_data("ota", 0x0666,
hg->proc.rootdir, &hgicf_pops_ota, hg);
if (hg->proc.ota == NULL) {
hgic_err("create proc file: testmode failed\r\n");
}
hg->proc.temp = proc_create_data("temperature", 0x0444,
hg->proc.rootdir, &hgicf_pops_temperature, hg);
if (hg->proc.temp == NULL) {
hgic_err("create proc file: temperature failed\r\n");
}
hg->proc.sleep = proc_create_data("sleep", 0x0666,
hg->proc.rootdir, &hgicf_pops_sleep, hg);
if (hg->proc.sleep == NULL) {
hgic_err("create proc file: sleep failed\r\n");
}
hg->proc.iwpriv = proc_create_data("iwpriv", 0x0666,
hg->proc.rootdir, &hgicf_pops_iwpriv, hg);
if (hg->proc.iwpriv == NULL) {
hgic_err("create proc file: iwpriv failed\r\n");
}
hg->proc.paired_stas = proc_create_data("paired_stas", 0x0444,
hg->proc.rootdir, &hgicf_pops_paired_stas, hg);
if (hg->proc.paired_stas == NULL) {
hgic_err("create proc file: paired_stas failed\r\n");
}
hg->proc.radio_off = proc_create_data("radio_off", 0x0666,
hg->proc.rootdir, &hgicf_pops_radio_off, hg);
if (hg->proc.radio_off == NULL) {
hgic_err("create proc file: radio_off failed\r\n");
}
hg->proc.sta_count = proc_create_data("sta_count", 0x0444,
hg->proc.rootdir, &hgicf_pops_sta_count, hg);
if (hg->proc.sta_count == NULL) {
hgic_err("create proc file: sta_count failed\r\n");
}
hg->proc.heartbeat = proc_create_data("heartbeat", 0x0666,
hg->proc.rootdir, &hgicf_pops_ps_heartbeat, hg);
if (hg->proc.heartbeat == NULL) {
hgic_err("create proc file: wakeup failed\r\n");
}
hg->proc.heartbeat_resp = proc_create_data("heartbeat_resp", 0x0666,
hg->proc.rootdir, &hgicf_pops_ps_heartbeat_resp, hg);
if (hg->proc.heartbeat_resp == NULL) {
hgic_err("create proc file: wakeup failed\r\n");
}
hg->proc.wakeup_data = proc_create_data("wakeup_data", 0x0666,
hg->proc.rootdir, &hgicf_pops_ps_wakeup_data, hg);
if (hg->proc.wakeup_data == NULL) {
hgic_err("create proc file: wakeup failed\r\n");
}
hg->proc.wakeup = proc_create_data("wakeup", 0x0666,
hg->proc.rootdir, &hgicf_pops_wakeup, hg);
if (hg->proc.wakeup == NULL) {
hgic_err("create proc file: wakeup failed\r\n");
}
hg->proc.pair_state = proc_create_data("pair_state", 0x0444,
hg->proc.rootdir, &hgicf_pops_pair_state, hg);
if (hg->proc.pair_state == NULL) {
hgic_err("create proc file: pair_state failed\r\n");
}
hg->proc.fw_ver = proc_create_data("fw_ver", 0x0444,
hg->proc.rootdir, &hgicf_pops_fw_ver, hg);
if (hg->proc.fw_ver == NULL) {
hgic_err("create proc file: fw_ver failed\r\n");
}
hg->proc.wkreason = proc_create_data("wkreason", 0x0444,
hg->proc.rootdir, &hgicf_pops_wkreason, hg);
if (hg->proc.wkreason == NULL) {
hgic_err("create proc file: wkreason failed\r\n");
}
hg->proc.fwevent = proc_create_data("event", 0x0444,
hg->proc.rootdir, &hgicf_pops_fwevent, hg);
if (hg->proc.fwevent == NULL) {
hgic_err("create proc file: event failed\r\n");
}
hg->proc.mgmt = proc_create_data("mgmt", 0x0666,
hg->proc.rootdir, &hgicf_pops_mgmt, hg);
if (hg->proc.mgmt == NULL) {
hgic_err("create proc file: mgmt failed\r\n");
}
hg->proc.battery_level = proc_create_data("battery_level", 0x0444,
hg->proc.rootdir, &hgicf_pops_battery_level, hg);
if (hg->proc.battery_level == NULL) {
hgic_err("create proc file: battery_soc failed\r\n");
}
hg->proc.fwdbginfo = proc_create_data("fwdbginfo", 0x0444,
hg->proc.rootdir, &hgicf_pops_fwdbginfo, hg);
if (hg->proc.fwdbginfo == NULL) {
hgic_err("create proc file: fwdbginfo failed\r\n");
}
hg->proc.pairing_sta = proc_create_data("pairing_sta", 0x0444,
hg->proc.rootdir, &hgicf_pops_pairing_sta, hg);
if (hg->proc.pairing_sta == NULL) {
hgic_err("create proc file: pairing_sta failed\r\n");
}
hg->proc.dhcpc = proc_create_data("dhcpc", 0x0444,
hg->proc.rootdir, &hgicf_pops_dhcpc, hg);
if (hg->proc.dhcpc == NULL) {
hgic_err("create proc file: dhcpc failed\r\n");
}
hg->proc.wkdata_buff = proc_create_data("wkdata_buff", 0x0444,
hg->proc.rootdir, &hgicf_pops_wkdata_buff, hg);
if (hg->proc.wkdata_buff == NULL) {
hgic_err("create proc file: wkdata_buff failed\r\n");
}
hg->proc.wkdata_mask = proc_create_data("wkdata_mask", 0x0666,
hg->proc.rootdir, &hgicf_pops_wkdata_mask, hg);
if (hg->proc.wkdata_mask == NULL) {
hgic_err("create proc file: wkdata_mask failed\r\n");
}
hg->proc.cust_driverdata = proc_create_data("cust_driverdata", 0x0666,
hg->proc.rootdir, &hgicf_pops_cust_driverdata, hg);
if (hg->proc.cust_driverdata == NULL) {
hgic_err("create proc file: cust_driverdata failed\r\n");
}
hg->proc.freqinfo = proc_create_data("freqinfo", 0x0444,
hg->proc.rootdir, &hgicf_pops_freqinfo, hg);
if (hg->proc.freqinfo == NULL) {
hgic_err("create proc file: freqinfo failed\r\n");
}
hgic_dbg("leave\r\n");
}
void hgicf_delete_procfs(struct hgicf_wdev *hg)
{
hgic_dbg("enter\r\n");
if (hg->proc.rootdir) {
if (hg->proc.tx_bitrate) {
remove_proc_entry("tx_bitrate", hg->proc.rootdir);
hg->proc.tx_bitrate = NULL;
}
if (hg->proc.testmode) {
remove_proc_entry("testmode", hg->proc.rootdir);
hg->proc.testmode = NULL;
}
if (hg->proc.status) {
remove_proc_entry("status", hg->proc.rootdir);
hg->proc.status = NULL;
}
if (hg->proc.signal) {
remove_proc_entry("signal", hg->proc.rootdir);
hg->proc.signal = NULL;
}
if (hg->proc.evm) {
remove_proc_entry("evm", hg->proc.rootdir);
hg->proc.evm = NULL;
}
if (hg->proc.conn_state) {
remove_proc_entry("conn_state", hg->proc.rootdir);
hg->proc.conn_state = NULL;
}
if (hg->proc.ota) {
remove_proc_entry("ota", hg->proc.rootdir);
hg->proc.ota = NULL;
}
if (hg->proc.temp) {
remove_proc_entry("temperature", hg->proc.rootdir);
hg->proc.temp = NULL;
}
if (hg->proc.sleep) {
remove_proc_entry("sleep", hg->proc.rootdir);
hg->proc.sleep = NULL;
}
if (hg->proc.iwpriv) {
remove_proc_entry("iwpriv", hg->proc.rootdir);
hg->proc.iwpriv = NULL;
}
if (hg->proc.paired_stas) {
remove_proc_entry("paired_stas", hg->proc.rootdir);
hg->proc.paired_stas = NULL;
}
if (hg->proc.radio_off) {
remove_proc_entry("radio_off", hg->proc.rootdir);
hg->proc.radio_off = NULL;
}
if (hg->proc.sta_count) {
remove_proc_entry("sta_count", hg->proc.rootdir);
hg->proc.sta_count = NULL;
}
if (hg->proc.heartbeat) {
remove_proc_entry("heartbeat", hg->proc.rootdir);
hg->proc.heartbeat = NULL;
}
if (hg->proc.heartbeat_resp) {
remove_proc_entry("heartbeat_resp", hg->proc.rootdir);
hg->proc.heartbeat_resp = NULL;
}
if (hg->proc.wakeup_data) {
remove_proc_entry("wakeup_data", hg->proc.rootdir);
hg->proc.wakeup_data = NULL;
}
if (hg->proc.wakeup) {
remove_proc_entry("wakeup", hg->proc.rootdir);
hg->proc.wakeup = NULL;
}
if (hg->proc.pair_state) {
remove_proc_entry("pair_state", hg->proc.rootdir);
hg->proc.pair_state = NULL;
}
if (hg->proc.fw_ver) {
remove_proc_entry("fw_ver", hg->proc.rootdir);
hg->proc.fw_ver = NULL;
}
if (hg->proc.wkreason) {
remove_proc_entry("wkreason", hg->proc.rootdir);
hg->proc.wkreason = NULL;
}
if (hg->proc.fwevent) {
remove_proc_entry("event", hg->proc.rootdir);
hg->proc.fwevent = NULL;
}
if (hg->proc.mgmt) {
remove_proc_entry("mgmt", hg->proc.rootdir);
hg->proc.mgmt = NULL;
}
if (hg->proc.battery_level) {
remove_proc_entry("battery_level", hg->proc.rootdir);
hg->proc.battery_level = NULL;
}
if (hg->proc.fwdbginfo) {
remove_proc_entry("fwdbginfo", hg->proc.rootdir);
hg->proc.fwdbginfo = NULL;
}
if (hg->proc.pairing_sta) {
remove_proc_entry("pairing_sta", hg->proc.rootdir);
hg->proc.pairing_sta = NULL;
}
if (hg->proc.dhcpc) {
remove_proc_entry("dhcpc", hg->proc.rootdir);
hg->proc.dhcpc = NULL;
}
if (hg->proc.wkdata_buff) {
remove_proc_entry("wkdata_buff", hg->proc.rootdir);
hg->proc.wkdata_buff = NULL;
}
if (hg->proc.wkdata_mask) {
remove_proc_entry("wkdata_mask", hg->proc.rootdir);
hg->proc.wkdata_mask = NULL;
}
if (hg->proc.cust_driverdata) {
remove_proc_entry("cust_driverdata", hg->proc.rootdir);
hg->proc.cust_driverdata = NULL;
}
if (hg->proc.freqinfo) {
remove_proc_entry("freqinfo", hg->proc.rootdir);
hg->proc.freqinfo = NULL;
}
remove_proc_entry("hgic", NULL);
hg->proc.rootdir = NULL;
}
hgic_dbg("leave\r\n");
}