//#include #ifdef LINUX_OS #include #include #include #include #include #include #include #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; ivif_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