#include #include #include #include #include #include "hgicf.h" #include "cfg.h" 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"); }