luckfox-pico-sdk/sysdrv/drv_ko/wifi/atbm6441/hal_apollo/atbm_ioctl.c
2023-08-08 20:36:47 +08:00

2363 lines
56 KiB
C

//#include <stdio.h>
#ifdef LINUX_OS
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kthread.h>
#include <asm/ioctl.h>
#endif
#include "apollo.h"
#include "wsm.h"
#include "debug.h"
#include "atbm_ioctl.h"
#include "sta_info.h"
#include "hwio.h"
#include "sbus.h"
#include "dcxo_dpll.h"
#ifdef LINUX_OS
#define MAX_STATUS_LSIT_CNT (10)
struct atbm_info {
dev_t devid;
struct cdev *my_cdev;
struct class *my_class;
struct device *my_device;
struct atbm_common *hw_priv;
};
struct status_async{
u8 is_connected;
u8 type; /* 0: connect msg, 1: driver msg, 2:scan complete, 3:wakeup host reason, 4:disconnect reason, 5:connect fail reason, 6:customer event*/
u8 driver_mode; /* TYPE1 0: rmmod, 1: insmod; TYPE3\4\5 reason */
u8 list_empty;
struct HostConnectEvent event;
u8 event_buffer[MAX_SDIO_EVENT_BUFFER_LEN];
};
struct atbm_status_event {
struct list_head link;
struct status_async status;
};
struct atbm_info atbm_info;
static struct fasync_struct *connect_async;
static spinlock_t s_status_queue_lock;
static struct list_head s_status_head;
static int s_cur_status_list_cnt = 0;
#endif
struct timer_info
{
struct atbm_timer_list timer;
struct wsm_scan_state_req scan_state;
struct workqueue_struct *workqueue;
struct work_struct work;
int scan_ok;
};
struct check_alive_info
{
struct atbm_timer_list timer;
struct workqueue_struct *workqueue;
struct work_struct work;
int period; //ms
int tmo_cnt;
int cur_cnt;
int is_start;
int in_check;
};
static struct timer_info timer_info;
static struct check_alive_info check_alive_info;
static struct wsm_scan_result_req result;
static struct wsm_update_req update_req;
extern struct atbm_common *g_hw_priv;
extern int hw_net_cfg_ok;
int is_pre_rmmod = 0;
extern void atbm_clear_wakeup_reg( struct atbm_common *dev);
extern void wsm_cmd_lock(struct atbm_common *hw_priv);
extern void wsm_cmd_unlock(struct atbm_common *hw_priv);
#ifdef LINUX_OS
static int atbm_ioctl_notify_add(u8 type, u8 is_connected, u8 driver_mode, struct HostConnectEvent *conn_event, u8 *event_buffer)
{
int first;
struct atbm_status_event *event = NULL;
atbm_printk_err("%s enter\n", __func__);
if (s_cur_status_list_cnt >= MAX_STATUS_LSIT_CNT)
{
atbm_printk_err("%s: status event list is full.\n", __func__);
return -1;
}
if ((type == 6) && (event_buffer == NULL))
{
atbm_printk_err("%s: event_buffer is full.\n", __func__);
return -1;
}
#ifdef CONFIG_ATBM_SDIO_ATCMD
if ((type == 7) && (event_buffer == NULL))
{
atbm_printk_err("%s: event_buffer is full.\n", __func__);
return -1;
}
#endif
event = atbm_kzalloc(sizeof(struct atbm_status_event), GFP_KERNEL);
if(event == NULL)
{
atbm_printk_err("%s: event atbm_kzalloc is null.\n", __func__);
WARN_ON(1);
return -1;
}
if (conn_event != NULL)
{
memcpy(&(event->status.event), conn_event, sizeof(struct HostConnectEvent));
}
if (event_buffer != NULL)
{
memcpy(&(event->status.event_buffer), event_buffer, MAX_SDIO_EVENT_BUFFER_LEN);
}
event->status.type = type;
event->status.driver_mode = driver_mode;
event->status.is_connected = is_connected;
spin_lock_bh(&s_status_queue_lock);
first = list_empty(&s_status_head);
list_add_tail(&event->link, &s_status_head);
s_cur_status_list_cnt++;
spin_unlock_bh(&s_status_queue_lock);
atbm_printk_err("%s need async notify usr layer\n", __func__);
return 1;//need async notify usr layer
}
#endif
//notify connect status
void atbm_ioctl_connect_async(struct HostConnectEvent *event, char is_connected)
{
#ifdef LINUX_OS
int ret = 0;
if (is_connected)
{
if (NULL == event)
{
atbm_printk_err("%s: event data is null.\n", __func__);
return;
}
ret = atbm_ioctl_notify_add(0, 1, 0, event, NULL);
}
else
{
ret = atbm_ioctl_notify_add(0, 0, 0, NULL, NULL);
}
if (ret > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
//notify driver need to insmod&rmmod
void atbm_ioctl_driver_async(int insmod)
{
DEBUG_PRINTF("called\n");
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(1, 0, insmod, NULL, NULL) > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
//notify wakeup host reason
void atbm_ioctl_wakeup_async(int reason)
{
DEBUG_PRINTF("called\n");
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(3, 0, reason, NULL, NULL) > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
//notify network disconnect reason
void atbm_ioctl_disconn_async(int reason)
{
DEBUG_PRINTF("called\n");
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(4, 0, reason, NULL, NULL) > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
//notify network connect error reason
void atbm_ioctl_conn_err_async(int reason)
{
DEBUG_PRINTF("called\n");
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(5, 0, reason, NULL, NULL) > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
//upload customer private event info
void atbm_ioctl_customer_private_event_async(u8 *event_buffer)
{
DEBUG_PRINTF("called\n");
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(6, 0, 0, NULL, event_buffer) > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
#ifdef CONFIG_ATBM_SDIO_ATCMD
void atbm_ioctl_atcmd_event_async(u8 *event_buffer)
{
DEBUG_PRINTF("called\n");
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(7, 0, 0, NULL, event_buffer) > 0)
{
DEBUG_PRINTF("called\n");
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
}
#endif
int atbm_wsm_ps(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_powersave_mode_req ps_mode;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&ps_mode, 0, sizeof(ps_mode));
if (0 != copy_from_user(&ps_mode, (struct wsm_powersave_mode_req *)data, sizeof(struct wsm_powersave_mode_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_set_psmode(hw_priv,&ps_mode,sizeof(ps_mode));
if (ret)
{
atbm_printk_err("%s: wsm_set_psmode err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_connect(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
int if_id = 0;
int i = 0;
struct wsm_join join;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
for (i=0; i<ATBM_WIFI_MAX_VIFS; i++)
{
if (hw_priv->vif_list[i])
{
if_id = i;
break;
}
}
if (ATBM_WIFI_MAX_VIFS == i)
{
atbm_printk_err("%s: hw_priv->vif_list is null.\n", __func__);
ret = -1;
goto err;
}
memset(&join, 0, sizeof(join));
if (0 != copy_from_user(&join, (struct wsm_join *)data, sizeof(struct wsm_join)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
if (if_id)
{
join.flags |= WSM_FLAG_MAC_INSTANCE_1;
}
else
{
join.flags &= ~WSM_FLAG_MAC_INSTANCE_1;
}
if (join.ssidLength > sizeof(join.ssid))
{
join.ssidLength = sizeof(join.ssid);
}
if (wsm_join(hw_priv, &join, if_id))
{
atbm_printk_err("%s: join err.\n", __func__);
ret = -1;
}
err:
return ret;
}
int atbm_wsm_get_status(struct atbm_common *hw_priv, unsigned int buff)
{
int ret = 0;
struct wsm_sdio_getconfig_cnf cnf;
memset(&cnf, 0, sizeof(cnf));
ret = wsm_get_config(hw_priv, &cnf, sizeof(cnf));
if (!ret)
{
if (0 != copy_to_user((struct wsm_sdio_getconfig_cnf *)buff, &cnf, sizeof(struct wsm_sdio_getconfig_cnf)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
else
{
atbm_printk_err("%s: wsm_get_config err\n", __func__);
}
return ret;
}
int atbm_wsm_tcp_filter(struct atbm_common *hw_priv, unsigned int data, int set_flag)
{
int ret = 0;
struct wsm_tcp_filter_req req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&req, 0, sizeof(req));
if (set_flag)
{
if (0 != copy_from_user(&req, (struct wsm_tcp_filter_req *)data, sizeof(struct wsm_tcp_filter_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_set_tcp_filter(hw_priv, &req, sizeof(req));
if (ret)
{
atbm_printk_err("%s: wsm_set_tcp_filter err.\n", __func__);
}
else
{
memcpy(&hw_priv->tcp_filter_req, &req, sizeof(req));
}
}
else
{
ret = wsm_get_tcp_filter(hw_priv, &req, sizeof(req));
if (ret)
{
atbm_printk_err("%s: wsm_get_tcp_filter err.\n", __func__);
ret = -1;
goto err;
}
if (0 != copy_to_user((struct wsm_tcp_filter_req *)data, &req, sizeof(req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
err:
return ret;
}
void scan_complete_work(struct work_struct *work)
{
if (timer_info.scan_ok)
{
#ifdef LINUX_OS
if (atbm_ioctl_notify_add(2, 0, 0, NULL, NULL) > 0)
{
kill_fasync (&connect_async, SIGIO, POLL_IN);
}
#endif
timer_info.scan_state.scan_state = 0;
}
else
{
struct wsm_scan_state_req *state_req = &(timer_info.scan_state);
wsm_get_scan_state(g_hw_priv, state_req, sizeof(struct wsm_scan_state_req));
}
}
void scan_complete_check(unsigned long data)
{
if (!timer_info.scan_state.scan_state)
{
timer_info.scan_ok = 1;
queue_work(timer_info.workqueue, &timer_info.work);
return;
}
queue_work(timer_info.workqueue, &timer_info.work);
atbm_mod_timer(&timer_info.timer, jiffies+msecs_to_jiffies(500));
}
int atbm_wsm_set_scan(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_scan_req req;
static int first_create = 1;
if (!timer_info.scan_state.scan_state)
{
memset(&req, 0, sizeof(req));
ret = wsm_set_scan(hw_priv, &req);
if (ret)
{
atbm_printk_err("%s: wsm_set_scan err.\n", __func__);
}
else
{
if (first_create)
{
memset(&timer_info, 0, sizeof(timer_info));
timer_info.workqueue = alloc_workqueue("scan_workqueue", 0, 0);
INIT_WORK(&timer_info.work, scan_complete_work);
atbm_init_timer(&timer_info.timer);
timer_info.timer.function = scan_complete_check;
timer_info.timer.data = 0;
first_create = 0;
}
timer_info.scan_state.scan_state = 1;
timer_info.scan_ok = 0;
atbm_mod_timer(&timer_info.timer, jiffies);
}
}
return ret;
}
int atbm_wsm_get_scan_state(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
if (0 != copy_to_user((char *)data, &(timer_info.scan_state.scan_state), sizeof(timer_info.scan_state.scan_state)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
err:
return ret;
}
int atbm_wsm_get_scan_info(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&result, 0, sizeof(result));
if (0 != copy_from_user(&result, (struct wsm_scan_result_req *)data, sizeof(struct wsm_scan_result_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_get_scan_info(hw_priv, &result, sizeof(result));
if (ret)
{
atbm_printk_err("%s: wsm_get_scan_info err.\n", __func__);
goto err;
}
if (result.status)
{
atbm_printk_err("%s: driver scanning.\n", __func__);
ret = -1;
goto err;
}
if (0 != copy_to_user((struct wsm_scan_result_req *)data, &result, sizeof(struct wsm_scan_result_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
err:
return ret;
}
int atbm_wsm_set_wifi_mode(struct atbm_common *hw_priv, char is_ap)
{
int ret = 0;
struct wsm_wifi_set_req mode_req;
struct atbm_vif * vif;
if (0 != is_ap && 1 != is_ap)
{
atbm_printk_err("%s: is_ap value err.\n", __func__);
ret = -1;
goto err;
}
memset(&mode_req, 0, sizeof(mode_req));
mode_req.is_ap = is_ap;
vif =__ABwifi_hwpriv_to_vifpriv(hw_priv,0);
if(vif == NULL)
{
atbm_printk_err("%s: vif is null.\n", __func__);
ret = -1;
goto err;
}
if(is_ap){
vif->type = NL80211_IFTYPE_AP;
}
else {
vif->type = NL80211_IFTYPE_STATION;
}
atbm_printk_err("%s:[%d][%d][%p]\n",__func__,vif->type,is_ap,vif);
ret = wsm_set_wifimode(hw_priv, &mode_req, sizeof(mode_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_wifimode err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_set_ap_cfg(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_ap_cfg_req ap_cfg_req;
struct atbm_vif * vif;
vif =__ABwifi_hwpriv_to_vifpriv(hw_priv,0);
if(vif == NULL){
atbm_printk_err("%s: vif is null.\n", __func__);
ret = -1;
goto err;
}
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&ap_cfg_req, 0, sizeof(ap_cfg_req));
if (0 != copy_from_user(&ap_cfg_req, (struct wsm_ap_cfg_req *)data, sizeof(struct wsm_ap_cfg_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
if(ap_cfg_req.join_parameter.keyMgmt == KEY_MGMT_NONE){
vif->ap_info.group_key.key_type = IEEE80211_ENC_TYPE;
vif->ap_info.key.key_type = IEEE80211_ENC_TYPE;
}
else if((ap_cfg_req.join_parameter.keyMgmt == KEY_MGMT_WEP) ||
(ap_cfg_req.join_parameter.keyMgmt == KEY_MGMT_WEP_SHARED)){
atbm_printk_err("%s:wep\n",__func__);
vif->ap_info.group_key.key_type = IEEE80211_ENC_WEP;
vif->ap_info.key.key_type = IEEE80211_ENC_WEP;
vif->ap_info.group_key.conf.iv_len = WEP_IV_LEN;
vif->ap_info.group_key.conf.icv_len = WEP_ICV_LEN;
vif->ap_info.key.conf.iv_len = WEP_IV_LEN;
vif->ap_info.key.conf.icv_len = WEP_ICV_LEN;
}else if(ap_cfg_req.join_parameter.keyMgmt == KEY_MGMT_WPA){
atbm_printk_err("%s:tkip\n",__func__);
vif->ap_info.group_key.key_type = IEEE80211_ENC_TKIP;
vif->ap_info.key.key_type = IEEE80211_ENC_TKIP;
vif->ap_info.group_key.conf.iv_len = TKIP_IV_LEN;
vif->ap_info.group_key.conf.icv_len = TKIP_ICV_LEN;
vif->ap_info.key.conf.iv_len = TKIP_IV_LEN;
vif->ap_info.key.conf.icv_len = TKIP_ICV_LEN;
}else if(KEY_MGMT_WPA2 == ap_cfg_req.join_parameter.keyMgmt){
atbm_printk_err("%s:aes\n",__func__);
vif->ap_info.group_key.key_type = IEEE80211_ENC_AES;
vif->ap_info.key.key_type = IEEE80211_ENC_AES;
vif->ap_info.group_key.conf.iv_len = CCMP_HDR_LEN;
vif->ap_info.group_key.conf.icv_len = CCMP_MIC_LEN;
vif->ap_info.key.conf.iv_len = CCMP_HDR_LEN;
vif->ap_info.key.conf.icv_len = CCMP_MIC_LEN;
}
vif->type = NL80211_IFTYPE_AP;
memcpy(&vif->group_key,&vif->ap_info.group_key,sizeof(struct ieee80211_key));
if (ap_cfg_req.join_parameter.ssidLength > sizeof(ap_cfg_req.join_parameter.ssid))
{
ap_cfg_req.join_parameter.ssidLength = sizeof(ap_cfg_req.join_parameter.ssid);
}
ret = wsm_set_ap_cfg(hw_priv, &ap_cfg_req, sizeof(ap_cfg_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_ap_cfg err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_set_wifi_channel(struct atbm_common *hw_priv, char channel)
{
int ret = 0;
struct wsm_wifi_set_req channel_req;
if (channel <= 0 || channel > 14)
{
atbm_printk_err("%s: channel value err.\n", __func__);
ret = -1;
goto err;
}
memset(&channel_req, 0, sizeof(channel_req));
channel_req.channel = channel;
ret = wsm_set_wifichannel(hw_priv, &channel_req, sizeof(channel_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_wifichannel err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_set_country(struct atbm_common *hw_priv, char country)
{
int ret = 0;
struct wsm_wifi_set_req country_req;
if (country >= COUNTRY_MAX)
{
atbm_printk_err("%s: country value err.\n", __func__);
ret = -1;
goto err;
}
memset(&country_req, 0, sizeof(country_req));
country_req.countryId = country;
ret = wsm_set_countryId(hw_priv, &country_req, sizeof(country_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_countryId err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_get_country(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_wifi_set_req country_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&country_req, 0, sizeof(country_req));
ret = wsm_get_countryId(hw_priv, &country_req, sizeof(country_req));
if (ret)
{
atbm_printk_err("%s: wsm_get_countryId err.\n", __func__);
goto err;
}
if (0 != copy_to_user((char *)data, &(country_req.countryId), sizeof(country_req.countryId)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
err:
return ret;
}
int atbm_wsm_get_sta_list(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_sta_list_req stalist_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&stalist_req, 0, sizeof(stalist_req));
ret = wsm_get_stalist(hw_priv, &stalist_req, sizeof(stalist_req));
if (ret)
{
atbm_printk_err("%s: wsm_get_stalist err.\n", __func__);
goto err;
}
if (0 != copy_to_user((struct wsm_sta_list_req *)data, &stalist_req, sizeof(struct wsm_sta_list_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
err:
return ret;
}
int atbm_wsm_smartcfg_start(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req smartcfg_req;
memset(&smartcfg_req, 0, sizeof(smartcfg_req));
ret = wsm_smart_cfg_start(hw_priv, &smartcfg_req, sizeof(smartcfg_req));
if (ret)
{
atbm_printk_err("%s: wsm_smart_cfg_start err.\n", __func__);
}
return ret;
}
int atbm_wsm_smartcfg_stop(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req smartcfg_req;
memset(&smartcfg_req, 0, sizeof(smartcfg_req));
ret = wsm_smart_cfg_stop(hw_priv, &smartcfg_req, sizeof(smartcfg_req));
if (ret)
{
atbm_printk_err("%s: wsm_smart_cfg_stop err.\n", __func__);
}
return ret;
}
int atbm_wsm_ap_touch_start(struct atbm_common *hw_priv, char data)
{
int ret = 0;
struct wsm_ap_touch_req ap_touch_req;
memset(&ap_touch_req, 0, sizeof(ap_touch_req));
ap_touch_req.is_no_notify = data?1:0;
ret = wsm_ap_touch_start(hw_priv, &ap_touch_req, sizeof(ap_touch_req));
if (ret)
{
atbm_printk_err("%s: wsm_ap_touch_start err.\n", __func__);
}
return ret;
}
int atbm_wsm_ap_touch_stop(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req ap_touch_req;
memset(&ap_touch_req, 0, sizeof(ap_touch_req));
ret = wsm_ap_touch_stop(hw_priv, &ap_touch_req, sizeof(ap_touch_req));
if (ret)
{
atbm_printk_err("%s: wsm_ap_touch_stop err.\n", __func__);
}
return ret;
}
int atbm_wsm_etf_start_tx(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_etf_req etf_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&etf_req, 0, sizeof(etf_req));
if (0 != copy_from_user(&etf_req, (struct wsm_etf_req *)data, sizeof(struct wsm_etf_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_etf_start_tx(hw_priv, &etf_req, sizeof(etf_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_start_tx err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_etf_single_tone(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_etf_req etf_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&etf_req, 0, sizeof(etf_req));
if (0 != copy_from_user(&etf_req, (struct wsm_etf_req *)data, sizeof(struct wsm_etf_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_etf_single_tone(hw_priv, &etf_req, sizeof(etf_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_single_tone err.\n", __func__);
ret = -1;
}
err:
return ret;
}
int atbm_wsm_etf_stop_tx(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req stop_tx_req;
memset(&stop_tx_req, 0, sizeof(stop_tx_req));
ret = wsm_etf_stop_tx(hw_priv, &stop_tx_req, sizeof(stop_tx_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_stop_tx err.\n", __func__);
}
return ret;
}
int atbm_wsm_etf_start_rx(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_etf_req etf_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&etf_req, 0, sizeof(etf_req));
if (0 != copy_from_user(&etf_req, (struct wsm_etf_req *)data, sizeof(struct wsm_etf_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_etf_start_rx(hw_priv, &etf_req, sizeof(etf_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_start_rx err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_etf_start_rx_no_drop(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_etf_req etf_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&etf_req, 0, sizeof(etf_req));
if (0 != copy_from_user(&etf_req, (struct wsm_etf_req *)data, sizeof(struct wsm_etf_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_etf_start_rx_no_drop(hw_priv, &etf_req, sizeof(etf_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_start_rx err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_etf_stop_rx(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req stop_rx_req;
memset(&stop_rx_req, 0, sizeof(stop_rx_req));
ret = wsm_etf_stop_rx(hw_priv, &stop_rx_req, sizeof(stop_rx_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_stop_rx err.\n", __func__);
}
return ret;
}
int atbm_wsm_etf_reset_rx(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req reset_rx_req;
memset(&reset_rx_req, 0, sizeof(reset_rx_req));
ret = wsm_etf_reset_rx(hw_priv, &reset_rx_req, sizeof(reset_rx_req));
if (ret)
{
atbm_printk_err("%s: wsm_etf_reset_rx err.\n", __func__);
}
return ret;
}
int atbm_wsm_set_adaptive(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_adaptive_req adaptive_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&adaptive_req, 0, sizeof(adaptive_req));
if (0 != copy_from_user(&adaptive_req, (struct wsm_adaptive_req *)data, sizeof(struct wsm_adaptive_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_set_adaptive(hw_priv, &adaptive_req, sizeof(adaptive_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_adaptive err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_get_version(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_version_req ver_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&ver_req, 0, sizeof(ver_req));
ret = wsm_get_ver(hw_priv, &ver_req, sizeof(ver_req));
if (ret)
{
atbm_printk_err("%s: wsm_get_ver err.\n", __func__);
goto err;
}
if (0 != copy_to_user((struct wsm_version_req *)data, &ver_req, sizeof(ver_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
err:
return ret;
}
int atbm_wsm_get_sdk_version(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_version_req ver_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&ver_req, 0, sizeof(ver_req));
ret = wsm_get_sdk_ver(hw_priv, &ver_req, sizeof(ver_req));
if (ret)
{
atbm_printk_err("%s: wsm_get_sdk_ver err.\n", __func__);
goto err;
}
if (0 != copy_to_user((struct wsm_version_req *)data, &ver_req, sizeof(ver_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
goto err;
}
err:
return ret;
}
int atbm_wsm_update_fw(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&update_req, 0, sizeof(update_req));
if (0 != copy_from_user(&update_req, (struct wsm_update_req *)data, sizeof(update_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_update_fw(hw_priv, &update_req, sizeof(update_req));
if (ret)
{
atbm_printk_err("%s: wsm_update_fw err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_set_listen_itvl(struct atbm_common *hw_priv, char interval)
{
int ret = 0;
struct wsm_listen_itvl_req itvl_req;
if (interval <= 0 || interval > 20)
{
atbm_printk_err("%s: interval value err.\n", __func__);
ret = -1;
goto err;
}
memset(&itvl_req, 0, sizeof(itvl_req));
itvl_req.interval = interval;
ret = wsm_set_listen_itvl(hw_priv, &itvl_req, sizeof(itvl_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_listen_itvl err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_send_at_cmd(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_at_cmd_req cmd_req;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&cmd_req, 0, sizeof(cmd_req));
if (0 != copy_from_user(&cmd_req, (struct wsm_at_cmd_req *)data, sizeof(cmd_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_send_at_cmd(hw_priv, &cmd_req, sizeof(cmd_req));
if (ret)
{
atbm_printk_err("%s: wsm_send_at_cmd err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_set_dbg_print(struct atbm_common *hw_priv, char enable)
{
int ret = 0;
struct wsm_dbg_print_enable_req dbg_req;
memset(&dbg_req, 0, sizeof(dbg_req));
dbg_req.enable = enable?1:0;
ret = wsm_set_dbg_print(hw_priv, &dbg_req, sizeof(dbg_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_dbg_print err.\n", __func__);
}
return ret;
}
int atbm_wsm_fw_sleep(struct atbm_common *hw_priv)
{
int ret = 0;
atbm_control_dbg(ATBM_CONTROL_DEBUG_SLEEP, "%s enter fw_version %d ...\n", __func__, hw_priv->wsm_caps.firmwareVersion);
if (hw_priv->wsm_caps.firmwareVersion < 13549)
{
struct wsm_generic_req sleep_req;
if (check_alive_info.is_start)
{
atbm_del_timer(&check_alive_info.timer);
}
memset(&sleep_req, 0, sizeof(sleep_req));
ret = wsm_fw_sleep(hw_priv, &sleep_req, sizeof(sleep_req));
if (ret)
{
atbm_printk_err("%s: wsm_fw_sleep err.\n", __func__);
if (check_alive_info.is_start)
{
atbm_mod_timer(&check_alive_info.timer,jiffies+msecs_to_jiffies(check_alive_info.period));
}
}
else
{
if (check_alive_info.is_start)
{
destroy_workqueue(check_alive_info.workqueue);
check_alive_info.is_start = 0;
}
printk("atbm_wsm_fw_sleep ok! old rmmod version...\n");
}
}
else if (!is_pre_rmmod)
{
if (check_alive_info.is_start)
{
atbm_del_timer(&check_alive_info.timer);
}
msleep(2);
printk("sleep lock wait cmd over...\n");
wsm_cmd_lock(hw_priv);
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
is_pre_rmmod = 1;
atbm_clear_wakeup_reg(hw_priv);
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
wsm_cmd_unlock(hw_priv);
hw_priv->sbus_ops->irq_unsubscribe(hw_priv->sbus_priv);
hw_priv->close_driver = 1;
if(hw_priv->sbus_ops->sbus_xmit_func_deinit)
hw_priv->sbus_ops->sbus_xmit_func_deinit(hw_priv->sbus_priv);
if(hw_priv->sbus_ops->sbus_rev_func_deinit)
hw_priv->sbus_ops->sbus_rev_func_deinit(hw_priv->sbus_priv);
printk("atbm_wsm_fw_sleep ok! new rmmod version...\n");
}
atbm_control_dbg(ATBM_CONTROL_DEBUG_SLEEP, "%s exit, ret=%d...\n", __func__, ret);
return ret;
}
int atbm_wsm_get_rate(struct atbm_common *hw_priv, unsigned int buff)
{
int ret = 0;
struct wsm_get_rate_req rate_req;
memset(&rate_req, 0, sizeof(rate_req));
ret = wsm_get_tx_rate(hw_priv, &rate_req, sizeof(rate_req));
if (!ret)
{
if (0 != copy_to_user((struct wsm_get_rate_req *)buff, &rate_req, sizeof(struct wsm_get_rate_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
else
{
atbm_printk_err("%s: wsm_get_tx_rate err\n", __func__);
}
return ret;
}
int atbm_wsm_send_ipc_data(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
struct wsm_ipc_data_req data_req;
if (0 == data)
{
atbm_printk_err("%s: ipc data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&data_req, 0, sizeof(data_req));
if (0 != copy_from_user(&data_req, (struct wsm_ipc_data_req *)data, sizeof(data_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_send_ipc_data(hw_priv, &data_req, sizeof(data_req));
if (ret)
{
atbm_printk_err("%s: wsm_send_ipc_data err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_get_rssi(struct atbm_common *hw_priv, unsigned int buff)
{
int ret = 0;
struct wsm_rssi_req rssi_req;
memset(&rssi_req, 0, sizeof(rssi_req));
ret = wsm_get_rssi(hw_priv, &rssi_req, sizeof(rssi_req));
if (!ret)
{
if (0 != copy_to_user((struct wsm_rssi_req *)buff, &rssi_req, sizeof(struct wsm_rssi_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
else
{
atbm_printk_err("%s: wsm_get_rssi err\n", __func__);
}
return ret;
}
int atbm_wsm_get_time(struct atbm_common *hw_priv, unsigned int buff)
{
int ret = 0;
struct wsm_time_req time_req;
memset(&time_req, 0, sizeof(time_req));
ret = wsm_get_time(hw_priv, &time_req, sizeof(time_req));
if (!ret && !time_req.status)
{
if (0 != copy_to_user((struct wsm_time_req *)buff, &time_req, sizeof(struct wsm_time_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
else
{
atbm_printk_err("%s: wsm_get_time err\n", __func__);
ret = -1;
}
return ret;
}
int atbm_wsm_clear_wifi_config(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req clear_req;
memset(&clear_req, 0, sizeof(clear_req));
ret = wsm_clear_wifi_config(hw_priv, &clear_req, sizeof(clear_req));
if (ret)
{
atbm_printk_err("%s: wsm_clear_wifi_config err.\n", __func__);
}
return ret;
}
int atbm_wsm_get_etf_rx_info(struct atbm_common *hw_priv, unsigned int buff)
{
int ret = 0;
struct wsm_etf_rx_info_req rx_info_req;
memset(&rx_info_req, 0, sizeof(rx_info_req));
ret = wsm_get_etf_rx_info(hw_priv, &rx_info_req, sizeof(rx_info_req));
if (!ret && !rx_info_req.status)
{
if (0 != copy_to_user((struct wsm_etf_rx_info_req *)buff, &rx_info_req, sizeof(struct wsm_etf_rx_info_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
else
{
atbm_printk_err("%s: wsm_get_etf_rx_info err\n", __func__);
ret = -1;
}
return ret;
}
int atbm_wsm_pre_rmmod(struct atbm_common *hw_priv)
{
if (hw_priv->wsm_caps.firmwareVersion < 13549){
printk("atbm_wsm_pre_rmmod old rmmod version...\n");
is_pre_rmmod = 1;
}
else {
printk("atbm_wsm_pre_rmmod new rmmod version...\n");
atbm_wsm_fw_sleep(hw_priv);
}
return 0;
}
int atbm_wsm_is_tx_buffer_empty(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
char is_empty = 0;
if (atbm_skb_queue_empty(&hw_priv->tx_frame_queue))
{
is_empty = 1;
}
if (0 != copy_to_user((char *)buff, &is_empty, sizeof(char)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
atbm_control_dbg(ATBM_CONTROL_DEBUG_SLEEP, "%s empty=%d ret=%d\n", __func__, is_empty, ret);
return ret;
}
int atbm_wsm_set_wakeup_event(struct atbm_common *hw_priv, int wakeup_event)
{
int ret = 0;
struct wsm_wakeup_event_req req;
memset(&req, 0, sizeof(req));
req.event = wakeup_event;
ret = wsm_set_wakeup_event(hw_priv, &req, sizeof(struct wsm_wakeup_event_req));
if (ret)
{
atbm_printk_err("%s: wsm_set_wakeup_event err\n", __func__);
}
return ret;
}
int atbm_wsm_add_netpattern_info(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_netpattern_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_netpattern_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_add_netpattern_info(hw_priv, &req, sizeof(struct wsm_netpattern_info));
if (ret)
{
atbm_printk_err("%s: wsm_add_netpattern_info err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_del_netpattern_info(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_netpattern_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_netpattern_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_del_netpattern_info(hw_priv, &req, sizeof(struct wsm_netpattern_info));
if (ret)
{
atbm_printk_err("%s: wsm_del_netpattern_info err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_add_conn_param_info(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_conn_param_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_conn_param_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_add_conn_param_info(hw_priv, &req, sizeof(struct wsm_conn_param_info));
if (ret)
{
atbm_printk_err("%s: wsm_add_conn_param_info err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_del_conn_param_info(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_conn_param_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_conn_param_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_del_conn_param_info(hw_priv, &req, sizeof(struct wsm_conn_param_info));
if (ret)
{
atbm_printk_err("%s: wsm_del_conn_param_info err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_set_wk_ssid(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_wakeup_ssid_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_wakeup_ssid_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_set_wakeup_ssid(hw_priv, &req, sizeof(struct wsm_wakeup_ssid_info));
if (ret)
{
atbm_printk_err("%s: wsm_set_wakeup_ssid err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_clear_wk_ssid(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_wakeup_ssid_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_wakeup_ssid_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_clear_wakeup_ssid(hw_priv, &req, sizeof(struct wsm_wakeup_ssid_info));
if (ret)
{
atbm_printk_err("%s: wsm_clear_wakeup_ssid err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_conn_lose_map(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_conn_lose_info req;
ret = wsm_conn_lose(hw_priv, &req, sizeof(struct wsm_conn_lose_info));
if (!ret)
{
if (0 != copy_to_user((struct wsm_conn_lose_info *)buff, &req, sizeof(struct wsm_conn_lose_info)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
else
{
atbm_printk_err("%s: wsm_conn_lose err\n", __func__);
}
return ret;
}
int atbm_wsm_conn_switch(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_conn_switch_info req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_conn_switch_info *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_conn_switch(hw_priv, &req, sizeof(struct wsm_conn_switch_info));
if (ret)
{
atbm_printk_err("%s: wsm_conn_switch err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_auto_reconnect(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_auto_reconnect_req req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_auto_reconnect_req *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_auto_reconnect(hw_priv, &req, sizeof(struct wsm_auto_reconnect_req));
if (ret)
{
atbm_printk_err("%s: wsm_auto_reconnect err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_send_customer_cmd(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_customer_cmd_req req;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_customer_cmd_req *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_send_customer_cmd(hw_priv, &req, sizeof(struct wsm_customer_cmd_req));
if (ret)
{
atbm_printk_err("%s: wsm_send_customer_cmd err\n", __func__);
}
err:
return ret;
}
int atbm_wsm_customer_cert_save(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
memset(&hw_priv->cert_save_req, 0, sizeof(struct wsm_customer_cert_save_req));
if (0 != copy_from_user(&hw_priv->cert_save_req, (struct wsm_customer_cert_save_req *)buff, sizeof(struct wsm_customer_cert_save_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_customer_cert_save(hw_priv, &hw_priv->cert_save_req, sizeof(struct wsm_customer_cert_save_req));
if (ret)
{
atbm_printk_err("%s: wsm_customer_cert_save err\n", __func__);
}
err:
return ret;
}
void check_alive_work(struct work_struct *work)
{
int ret = 0;
struct wsm_check_alive_req req;
check_alive_info.in_check = 1;
memset(&req, 0, sizeof(req));
req.alive_notify = 1212;
req.period = check_alive_info.period / 1000;
req.tmo_cnt = check_alive_info.tmo_cnt;
ret = wsm_check_alive(g_hw_priv, &req, sizeof(struct wsm_check_alive_req));
if (!ret)
{
check_alive_info.cur_cnt = 0;
}
check_alive_info.in_check = 0;
}
void sdio_alive_check_cb(unsigned long data)
{
check_alive_info.cur_cnt++;
if (check_alive_info.cur_cnt >= check_alive_info.tmo_cnt)
{
printk("check alive fail over\n");
}
else
{
if (!check_alive_info.in_check)
{
queue_work(check_alive_info.workqueue, &check_alive_info.work);
}
atbm_mod_timer(&check_alive_info.timer, jiffies+msecs_to_jiffies(check_alive_info.period));
}
}
int atbm_wsm_start_check_alive(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
struct wsm_check_alive_req req;
static int is_first = 1;
memset(&req, 0, sizeof(req));
if (0 != copy_from_user(&req, (struct wsm_check_alive_req *)buff, sizeof(req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
if (req.period < 1 || req.tmo_cnt < 2)
{
atbm_printk_err("%s: invalid params.\n", __func__);
ret = -1;
goto err;
}
req.alive_notify = 1212;
if (!is_first && check_alive_info.is_start)
{
atbm_del_timer(&check_alive_info.timer);
}
ret = wsm_check_alive(hw_priv, &req, sizeof(struct wsm_check_alive_req));
if (ret)
{
atbm_printk_err("%s: wsm_customer_cert_save err\n", __func__);
if (!is_first && check_alive_info.is_start)
{
atbm_mod_timer(&check_alive_info.timer,jiffies+msecs_to_jiffies(check_alive_info.period));
}
}
else
{
if (is_first)
{
check_alive_info.workqueue = alloc_workqueue("check_alive_", 0, 0);
INIT_WORK(&check_alive_info.work, check_alive_work);
atbm_init_timer(&check_alive_info.timer);
check_alive_info.timer.function = sdio_alive_check_cb;
check_alive_info.timer.data = 0;
check_alive_info.in_check = 0;
is_first = 0;
}
check_alive_info.period = req.period * 1000;
check_alive_info.tmo_cnt = req.tmo_cnt;
check_alive_info.cur_cnt = 0;
check_alive_info.is_start = 1;
atbm_mod_timer(&check_alive_info.timer,jiffies+msecs_to_jiffies(check_alive_info.period));
}
err:
return ret;
}
int atbm_wsm_direct_trans_buffer(struct atbm_common *hw_priv, unsigned long buff)
{
int ret = 0;
memset(&hw_priv->direct_buffer_req, 0, sizeof(struct wsm_direct_trans_buffer_req));
if (0 != copy_from_user(&hw_priv->direct_buffer_req, (struct wsm_direct_trans_buffer_req *)buff, sizeof(struct wsm_direct_trans_buffer_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_direct_trans_buffer(hw_priv, &hw_priv->direct_buffer_req, sizeof(struct wsm_direct_trans_buffer_req));
if (ret)
{
atbm_printk_err("%s: wsm_direct_trans_buffer err\n", __func__);
}
else
{
if (0 != copy_to_user((struct wsm_direct_trans_buffer_req *)buff, &hw_priv->direct_buffer_req, sizeof(struct wsm_direct_trans_buffer_req)))
{
atbm_printk_err("%s: copy_to_user err.\n", __func__);
ret = -1;
}
}
err:
return ret;
}
u32 atbm_control_debug_mask = 0;
int atbm_wsm_set_control_debug_mask(struct atbm_common *hw_priv, u32 debug_mask)
{
atbm_control_debug_mask = debug_mask;
atbm_printk_always("%s: update debug mask %x.\n", __func__, atbm_control_debug_mask);
return 0;
}
//force 6441 reboot
int atbm_wsm_force_reboot(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req reboot_req;
memset(&reboot_req, 0, sizeof(reboot_req));
ret = wsm_force_reboot(hw_priv, &reboot_req, sizeof(reboot_req));
if (ret)
{
atbm_printk_err("%s: wsm_force_reboot err.\n", __func__);
}
else
{
atbm_wsm_fw_sleep(hw_priv);
}
return ret;
}
//host reboot
int atbm_wsm_host_reboot_notify(struct atbm_common *hw_priv)
{
int ret = 0;
struct wsm_generic_req reboot_req;
memset(&reboot_req, 0, sizeof(reboot_req));
ret = wsm_host_reboot_notify(hw_priv, &reboot_req, sizeof(reboot_req));
if (ret)
{
atbm_printk_err("%s: wsm_host_reboot_notify err.\n", __func__);
}
return ret;
}
int atbm_wsm_fast_cfg_recv(struct atbm_common *hw_priv, unsigned long data)
{
int ret = 0;
struct wsm_fast_cfg_recv_req fast_cfg;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&fast_cfg, 0, sizeof(fast_cfg));
if (0 != copy_from_user(&fast_cfg, (struct wsm_fast_cfg_recv_req *)data, sizeof(struct wsm_fast_cfg_recv_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_ext_fast_cfg_recv(hw_priv,&fast_cfg,sizeof(fast_cfg));
if (ret)
{
atbm_printk_err("%s: wsm_set_psmode err.\n", __func__);
}
err:
return ret;
}
int atbm_wsm_fast_cfg_send(struct atbm_common *hw_priv, unsigned long data)
{
int ret = 0;
struct wsm_fast_cfg_send_req fast_cfg;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&fast_cfg, 0, sizeof(fast_cfg));
if (0 != copy_from_user(&fast_cfg, (struct wsm_fast_cfg_send_req *)data, sizeof(struct wsm_fast_cfg_send_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
ret = wsm_ext_fast_cfg_send(hw_priv,&fast_cfg,sizeof(fast_cfg));
if (ret)
{
atbm_printk_err("%s: wsm_set_psmode err.\n", __func__);
}
err:
return ret;
}
#ifdef CONFIG_ATBM_SDIO_ATCMD
struct at_cmd_direct cmd_req;
int atbm_at_cmd_direct_send(struct atbm_common *hw_priv, unsigned int data)
{
int ret = 0;
u32 put;
struct wsm_hdr_tx *wsm_h;
if (0 == data)
{
atbm_printk_err("%s: info data is null.\n", __func__);
ret = -1;
goto err;
}
memset(&cmd_req, 0, sizeof(cmd_req));
if (0 != copy_from_user(&cmd_req, (struct at_cmd_direct *)data, sizeof(cmd_req)))
{
atbm_printk_err("%s: copy_from_user err.\n", __func__);
ret = -1;
goto err;
}
if((hw_priv->at_cmd_put - hw_priv->at_cmd_get) >= ATBM_AT_CMD_MAX_SW_CACHE){
atbm_printk_err("%s: atcmd software cache full.\n", __func__);
ret = -1;
goto err;
}
spin_lock_bh(&hw_priv->wsm_cmd.lock);
put = hw_priv->at_cmd_put & (ATBM_AT_CMD_MAX_SW_CACHE - 1);
BUG_ON(hw_priv->at_cmd_buf[put] == NULL);
memset(hw_priv->at_cmd_buf[put], 0, MAX_WSM_BUF_LEN);
wsm_h = (struct wsm_hdr_tx *)hw_priv->at_cmd_buf[put];
wsm_h->len =__cpu_to_le16(cmd_req.len + sizeof(struct wsm_hdr_tx));
wsm_h->id = __cpu_to_le16(WSM_SDIO_ATCMD_DIRECT_ID);
memcpy(hw_priv->at_cmd_buf[put]+sizeof(struct wsm_hdr_tx), cmd_req.cmd, cmd_req.len);
hw_priv->at_cmd_put ++;
spin_unlock_bh(&hw_priv->wsm_cmd.lock);
atbm_bh_wakeup(hw_priv);
err:
return ret;
}
#endif
#ifdef LINUX_OS
static long atbm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
long ret = 0;
switch (cmd)
{
case ATBM_PS_SET:
ret = atbm_wsm_ps(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CONNECT:
ret = atbm_wsm_connect(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_STATUS:
ret = atbm_wsm_get_status(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_SET_FILTER:
ret = atbm_wsm_tcp_filter(((struct atbm_info *)(filp->private_data))->hw_priv, arg, 1);
break;
case ATBM_GET_FILTER:
ret = atbm_wsm_tcp_filter(((struct atbm_info *)(filp->private_data))->hw_priv, arg, 0);
break;
case ATBM_SCAN:
ret = atbm_wsm_set_scan(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_SCAN_INFO:
ret = atbm_wsm_get_scan_info(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_WIFI_MODE:
ret = atbm_wsm_set_wifi_mode(((struct atbm_info *)(filp->private_data))->hw_priv, (char)arg);
break;
case ATBM_AP_CFG:
ret = atbm_wsm_set_ap_cfg(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_WIFI_CHANNEL:
ret = atbm_wsm_set_wifi_channel(((struct atbm_info *)(filp->private_data))->hw_priv, (char)arg);
break;
case ATBM_SET_COUNTRY:
ret = atbm_wsm_set_country(((struct atbm_info *)(filp->private_data))->hw_priv, (char)arg);
break;
case ATBM_GET_COUNTRY:
ret = atbm_wsm_get_country(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_GET_STALIST:
ret = atbm_wsm_get_sta_list(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_SMART_START:
ret = atbm_wsm_smartcfg_start(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_SMART_STOP:
ret = atbm_wsm_smartcfg_stop(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_APTOUCH_START:
ret = atbm_wsm_ap_touch_start(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_APTOUCH_STOP:
ret = atbm_wsm_ap_touch_stop(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_ETF_START_TX:
ret = atbm_wsm_etf_start_tx(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_ETF_SINGLETONE:
ret = atbm_wsm_etf_single_tone(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_ETF_STOP_TX:
ret = atbm_wsm_etf_stop_tx(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_ETF_START_RX:
ret = atbm_wsm_etf_start_rx(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_ETF_STOP_RX:
ret = atbm_wsm_etf_stop_rx(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_ETF_RESET_RX:
ret = atbm_wsm_etf_reset_rx(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_ADAPTIVE:
ret = atbm_wsm_set_adaptive(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_VERSION:
ret = atbm_wsm_get_version(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_SDK_VERSION:
ret = atbm_wsm_get_sdk_version(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_UPDATE_FW:
ret = atbm_wsm_update_fw(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_LISTEN_ITVL:
ret = atbm_wsm_set_listen_itvl(((struct atbm_info *)(filp->private_data))->hw_priv, (char)arg);
break;
case ATBM_FW_AT_CMD:
ret = atbm_wsm_send_at_cmd(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_FW_DBG_PRINT:
ret = atbm_wsm_set_dbg_print(((struct atbm_info *)(filp->private_data))->hw_priv, (char)arg);
break;
case ATBM_ETF_START_RX_NO_DROP:
ret = atbm_wsm_etf_start_rx_no_drop(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_FW_SLEEP:
ret = atbm_wsm_fw_sleep(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_TX_RATE:
ret = atbm_wsm_get_rate(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_IPC_DATA:
ret = atbm_wsm_send_ipc_data(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_RSSI:
ret = atbm_wsm_get_rssi(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_TIME:
ret = atbm_wsm_get_time(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CLEAR_WIFI_CFG:
ret = atbm_wsm_clear_wifi_config(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_ETF_RX_INFO:
ret = atbm_wsm_get_etf_rx_info(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_PRE_RMMOD:
ret = atbm_wsm_pre_rmmod(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
case ATBM_TX_EMPTY:
ret = atbm_wsm_is_tx_buffer_empty(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_WKUP_EVENT:
ret = atbm_wsm_set_wakeup_event(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_NETPATTERN_ADD:
ret = atbm_wsm_add_netpattern_info(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_NETPATTERN_DEL:
ret = atbm_wsm_del_netpattern_info(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CONN_PARAM_ADD:
ret = atbm_wsm_add_conn_param_info(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CONN_PARAM_DEL:
ret = atbm_wsm_del_conn_param_info(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CONN_LOSE_MAP:
ret = atbm_wsm_conn_lose_map(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CONN_SWITCH:
ret = atbm_wsm_conn_switch(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_SET_WK_SSID:
ret = atbm_wsm_set_wk_ssid(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CLR_WK_SSID:
ret = atbm_wsm_clear_wk_ssid(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_AUTO_RECONN:
ret = atbm_wsm_auto_reconnect(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CUSTOMER_CMD:
ret = atbm_wsm_send_customer_cmd(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CUSTOMER_CERT:
ret = atbm_wsm_customer_cert_save(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CHECK_ALIVE:
ret = atbm_wsm_start_check_alive(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_DIRECT_BUFFER:
ret = atbm_wsm_direct_trans_buffer(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_CONTROL_DEBUG:
ret = atbm_wsm_set_control_debug_mask(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_FORCE_REBOOT:
ret = atbm_wsm_force_reboot(((struct atbm_info *)(filp->private_data))->hw_priv);
break;
#ifdef CONFIG_ATBM_SDIO_ATCMD
case ATBM_AT_CMD_DIRECT:
ret = atbm_at_cmd_direct_send(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
#endif
case ATBM_FAST_CFG_RECV:
ret = atbm_wsm_fast_cfg_recv(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
case ATBM_FAST_CFG_SEND:
ret = atbm_wsm_fast_cfg_send(((struct atbm_info *)(filp->private_data))->hw_priv, arg);
break;
default:
atbm_printk_err("%s cmd %d invalid.\n", __func__, cmd);
ret = -1;
}
return ret;
}
static int atbm_ioctl_fasync(int fd, struct file *filp, int on)
{
return fasync_helper(fd, filp, on, &connect_async);
}
static int atbm_ioctl_open(struct inode *inode, struct file *filp)
{
int time_cnt = 100;
struct atbm_common *hw_priv = NULL;
while (NULL == (hw_priv=atbm_hw_priv_dereference()))
{
msleep(10);
time_cnt--;
if (time_cnt <= 0)
{
return -1;
}
}
while (!hw_priv->init_done || !hw_net_cfg_ok)
{
msleep(10);
time_cnt--;
if (time_cnt <= 0)
{
return -1;
}
}
atbm_info.hw_priv = hw_priv;
filp->private_data = &atbm_info;
printk("atbm_ioctl_open cost time: %d ms\n", 10*(100-time_cnt));
return 0;
}
static int atbm_ioctl_release(struct inode *inode, struct file *filp)
{
atbm_ioctl_fasync(-1, filp, 0);
filp->private_data = NULL;
return 0;
}
static ssize_t atbm_ioctl_read(struct file *filp, char __user *buff, size_t len, loff_t *off)
{
int ret = 0;
struct atbm_status_event *event = NULL;
if (sizeof(struct status_async) > len)
{
atbm_printk_err("%s: buff len is not enough.\n", __func__);
return -1;
}
if (list_empty(&s_status_head))
{
atbm_printk_err("%s: status list is empty.\n", __func__);
return -1;
}
spin_lock_bh(&s_status_queue_lock);
event = list_first_entry(&s_status_head, struct atbm_status_event, link);
if (event)
{
if (s_cur_status_list_cnt >= 2)
{
event->status.list_empty = 0;
}
else
{
event->status.list_empty = 1;
}
spin_unlock_bh(&s_status_queue_lock);
ret = copy_to_user(buff, &event->status, sizeof(struct status_async));
spin_lock_bh(&s_status_queue_lock);
if (ret)
{
atbm_printk_err("%s: copy_to_user err %d.\n", __func__, ret);
}
else
{
list_del(&event->link);
atbm_kfree(event);
s_cur_status_list_cnt--;
}
}
else
{
ret = -1;
}
spin_unlock_bh(&s_status_queue_lock);
if (ret)
{
return -1;
}
return sizeof(struct status_async);
}
static struct file_operations atbm_ioctl_fops = {
.owner = THIS_MODULE,
.open = atbm_ioctl_open,
.release = atbm_ioctl_release,
.read = atbm_ioctl_read,
.unlocked_ioctl = atbm_unlocked_ioctl,
.fasync = atbm_ioctl_fasync,
};
int atbm_ioctl_add(void)
{
memset(&atbm_info, 0, sizeof(struct atbm_info));
alloc_chrdev_region(&atbm_info.devid, 0, 1, "atbm_ioctl");
atbm_info.my_cdev = cdev_alloc();
cdev_init(atbm_info.my_cdev, &atbm_ioctl_fops);
atbm_info.my_cdev->owner = THIS_MODULE;
cdev_add(atbm_info.my_cdev, atbm_info.devid, 1);
atbm_info.my_class = class_create(THIS_MODULE, "atbm_ioctl_class");
atbm_info.my_device = device_create(atbm_info.my_class, NULL, atbm_info.devid, NULL, "atbm_ioctl");
spin_lock_init(&s_status_queue_lock);
INIT_LIST_HEAD(&s_status_head);
return 0;
}
void atbm_ioctl_free(void)
{
device_destroy(atbm_info.my_class, atbm_info.devid);
class_destroy(atbm_info.my_class);
cdev_del(atbm_info.my_cdev);
unregister_chrdev_region(atbm_info.devid, 1);
memset(&atbm_info, 0, sizeof(struct atbm_info));
spin_lock_bh(&s_status_queue_lock);
while (!list_empty(&s_status_head)) {
struct atbm_status_event *event =
list_first_entry(&s_status_head, struct atbm_status_event,
link);
list_del(&event->link);
atbm_kfree(event);
s_cur_status_list_cnt--;
}
spin_unlock_bh(&s_status_queue_lock);
}
#endif