int ath6kl_wmi_set_customer_scan_cmd(struct ath6kl_vif *vif)
{
	//athcfg_wcmd_sta_t *cmd;
	int ret;
    int left;

    set_bit(SONY_WMI_SCAN, &vif->flag);
    //printk("%s[%d]Start sony scan,vif=0x%x\n\r",__func__,__LINE__,(int*)vif);        
    ret = ath6kl_wmi_bssfilter_cmd(
        vif,
         ALL_BSS_FILTER, 0);
    if (ret) {
        return ret;
    }
	
    total_bss_info = 0;
    memset(&scaninfor_db[0],0x00,sizeof(scaninfor_db));
	ret = ath6kl_wmi_startscan_cmd(vif, WMI_LONG_SCAN, 0,
				       false, 0, 0, 0, NULL);

    left = wait_event_interruptible_timeout(vif->event_wq,
            !test_bit(SONY_WMI_SCAN, &vif->flag), WMI_TIMEOUT*10);      
    
    ath6kl_wmi_bssfilter_cmd(vif, NONE_BSS_FILTER, 0);

	return ret;
}
int ath6kl_wmi_get_customer_stainfo_cmd(struct ath6kl_vif *vif, athcfg_wcmd_sta_t *val)
{
	struct sk_buff *skb;
	athcfg_wcmd_sta_t *cmd;
	int ret;
    int left;

	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
	if (!skb)
		return -ENOMEM;

	cmd = (athcfg_wcmd_sta_t *) skb->data;
    set_bit(SONY_WMI_UPDATE, &vif->flag);
	ret = ath6kl_wmi_cmd_send(vif, skb, WMI_GET_CUSTOM_STAINFO,
				  NO_SYNC_WMIFLAG);
       
	left = wait_event_interruptible_timeout(vif->event_wq,
			!test_bit(SONY_WMI_UPDATE, &vif->flag), WMI_TIMEOUT);      
                      
	if (left == 0)
		return -ETIMEDOUT;

    //get beacon RSSI
    if(test_bit(CONNECTED, &vif->flag))
    {
        if(vif->nw_type != AP_NETWORK) {
            set_bit(SONY_WMI_UPDATE, &vif->flag);
            //printk("%s[%d]Start get beacon rssi,vif=0x%x\n\r",__func__,__LINE__,(int*)vif);        
            ret = ath6kl_wmi_bssfilter_cmd(
                 vif,
                 CURRENT_BSS_FILTER, 0);
            if (ret) {
                return ret;
            }
            left = wait_event_interruptible_timeout(vif->event_wq,
                    !test_bit(SONY_WMI_UPDATE, &vif->flag), WMI_TIMEOUT*10);      
            
            ath6kl_wmi_bssfilter_cmd(vif, NONE_BSS_FILTER, 0);                
        }
    }
   
    //printk("%s[%d]vif->nw_type=%d\n\r",__func__,__LINE__,vif->nw_type);        
    memcpy(val ,&stainfo_private,sizeof(athcfg_wcmd_sta_t));
	return ret;
}
int ath6kl_wmi_get_customer_scan_time_cmd(struct ath6kl_vif *vif,athcfg_wcmd_scantime_t *val)
{
	struct sk_buff *skb;
	athcfg_wcmd_sta_t *cmd;
	int ret;
    int left;
    unsigned long start_scan_timestamp;
    unsigned long end_scan_timestamp;
    unsigned long scan_time_msec;
    
	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
	if (!skb)
		return -ENOMEM;

	cmd = (athcfg_wcmd_sta_t *) skb->data;

    //set_bit(SONY_WMI_UPDATE, &vif->flag);
    set_bit(SONY_WMI_SCAN, &vif->flag);
   // printk("%s[%d]Start sony scan\n\r",__func__,__LINE__);        
    ret = ath6kl_wmi_bssfilter_cmd(
        vif,
         ALL_BSS_FILTER, 0);
    if (ret) {
        return ret;
    }
    start_scan_timestamp = jiffies;
	ret = ath6kl_wmi_startscan_cmd(vif, WMI_LONG_SCAN, 0,
				       false, 0, 0, 0, NULL);

    left = wait_event_interruptible_timeout(vif->event_wq,
            !test_bit(SONY_WMI_SCAN, &vif->flag), WMI_TIMEOUT*10);      
    
    end_scan_timestamp = jiffies;
    scan_time_msec = jiffies_to_msecs(end_scan_timestamp-start_scan_timestamp);
    if(val) 
        val->scan_time = scan_time_msec;
    //printk("%s[%d]scan_time_msec = %d msec \n\r",__func__,__LINE__,scan_time_msec);  
    ath6kl_wmi_bssfilter_cmd(vif, NONE_BSS_FILTER, 0);
        
        
    //printk("%s[%d]\n\r",__func__,__LINE__);        
    //memcpy(val ,&stainfo_private,sizeof(athcfg_wcmd_sta_t));
	return ret;
}
Example #4
0
void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
			  u16 listen_int, u16 beacon_int,
			  enum network_type net_type, u8 beacon_ie_len,
			  u8 assoc_req_len, u8 assoc_resp_len,
			  u8 *assoc_info)
{
	struct ath6kl *ar = vif->ar;

	ath6kl_cfg80211_connect_event(vif, channel, bssid,
				      listen_int, beacon_int,
				      net_type, beacon_ie_len,
				      assoc_req_len, assoc_resp_len,
				      assoc_info);

	memcpy(vif->bssid, bssid, sizeof(vif->bssid));
	vif->bss_ch = channel;

	if ((vif->nw_type == INFRA_NETWORK))
		ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
					      ar->listen_intvl_t,
					      ar->listen_intvl_b);

	netif_wake_queue(vif->ndev);

	/* Update connect & link status atomically */
	spin_lock_bh(&vif->if_lock);
	set_bit(CONNECTED, &vif->flags);
	clear_bit(CONNECT_PEND, &vif->flags);
	netif_carrier_on(vif->ndev);
	spin_unlock_bh(&vif->if_lock);

	aggr_reset_state(vif->aggr_cntxt);
	vif->reconnect_flag = 0;

	if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
		memset(ar->node_map, 0, sizeof(ar->node_map));
		ar->node_num = 0;
		ar->next_ep_id = ENDPOINT_2;
	}

	if (!ar->usr_bss_filter) {
		set_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
		ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
					 CURRENT_BSS_FILTER, 0);
	}
}
Example #5
0
void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
{
	struct ath6kl *ar = vif->ar;
	bool aborted = false;

	if (status != WMI_SCAN_STATUS_SUCCESS)
		aborted = true;

	ath6kl_cfg80211_scan_complete_event(vif, aborted);

	if (!ar->usr_bss_filter) {
		clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
		ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
					 NONE_BSS_FILTER, 0);
	}

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status);
}
Example #6
0
void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
{
	struct ath6kl *ar = vif->ar;
	struct ath6kl_req_key *ik;
	int res;
	u8 key_rsc[ATH6KL_KEY_SEQ_LEN];

	ik = &ar->ap_mode_bkey;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);

	switch (vif->auth_mode) {
	case NONE_AUTH:
		if (vif->prwise_crypto == WEP_CRYPT)
			ath6kl_install_static_wep_keys(vif);
		if (!ik->valid || ik->key_type != WAPI_CRYPT)
			break;
		/* for WAPI, we need to set the delayed group key, continue: */
	case WPA_PSK_AUTH:
	case WPA2_PSK_AUTH:
	case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
		if (!ik->valid)
			break;

		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
			   "the initial group key for AP mode\n");
		memset(key_rsc, 0, sizeof(key_rsc));
		res = ath6kl_wmi_addkey_cmd(
			ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type,
			GROUP_USAGE, ik->key_len, key_rsc, ATH6KL_KEY_SEQ_LEN,
			ik->key,
			KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
		if (res) {
			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
				   "addkey failed: %d\n", res);
		}
		break;
	}

	ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
	set_bit(CONNECTED, &vif->flags);
	netif_carrier_on(vif->ndev);
}
Example #7
0
static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
				struct cfg80211_scan_request *request)
{
	struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
	s8 n_channels = 0;
	u16 *channels = NULL;
	int ret = 0;

	if (!ath6kl_cfg80211_ready(ar))
		return -EIO;

	if (!ar->usr_bss_filter) {
		clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
		ret = ath6kl_wmi_bssfilter_cmd(
			ar->wmi,
			(test_bit(CONNECTED, &ar->flag) ?
			 ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
		if (ret) {
			ath6kl_err("couldn't set bss filtering\n");
			return ret;
		}
	}

	if (request->n_ssids && request->ssids[0].ssid_len) {
		u8 i;

		if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
			request->n_ssids = MAX_PROBED_SSID_INDEX - 1;

		for (i = 0; i < request->n_ssids; i++)
			ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
						  SPECIFIC_SSID_FLAG,
						  request->ssids[i].ssid_len,
						  request->ssids[i].ssid);
	}

	if (request->ie) {
		ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_REQ,
					       request->ie, request->ie_len);
		if (ret) {
			ath6kl_err("failed to set Probe Request appie for "
				   "scan");
			return ret;
		}
	}

	/*
	 * Scan only the requested channels if the request specifies a set of
	 * channels. If the list is longer than the target supports, do not
	 * configure the list and instead, scan all available channels.
	 */
	if (request->n_channels > 0 &&
	    request->n_channels <= WMI_MAX_CHANNELS) {
		u8 i;

		n_channels = request->n_channels;

		channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
		if (channels == NULL) {
			ath6kl_warn("failed to set scan channels, "
				    "scan all channels");
			n_channels = 0;
		}

		for (i = 0; i < n_channels; i++)
			channels[i] = request->channels[i]->center_freq;
	}

	ret = ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0,
				       false, 0, 0, n_channels, channels);
	if (ret)
		ath6kl_err("wmi_startscan_cmd failed\n");
	else
		ar->scan_req = request;

	kfree(channels);

	return ret;
}
Example #8
0
static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
				   struct cfg80211_connect_params *sme)
{
	struct ath6kl *ar = ath6kl_priv(dev);
	int status;

	ar->sme_state = SME_CONNECTING;

	if (!ath6kl_cfg80211_ready(ar))
		return -EIO;

	if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
		ath6kl_err("destroy in progress\n");
		return -EBUSY;
	}

	if (test_bit(SKIP_SCAN, &ar->flag) &&
	    ((sme->channel && sme->channel->center_freq == 0) ||
	     (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
		ath6kl_err("SkipScan: channel or bssid invalid\n");
		return -EINVAL;
	}

	if (down_interruptible(&ar->sem)) {
		ath6kl_err("busy, couldn't get access\n");
		return -ERESTARTSYS;
	}

	if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
		ath6kl_err("busy, destroy in progress\n");
		up(&ar->sem);
		return -EBUSY;
	}

	if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
		/*
		 * sleep until the command queue drains
		 */
		wait_event_interruptible_timeout(ar->event_wq,
			ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
			WMI_TIMEOUT);
		if (signal_pending(current)) {
			ath6kl_err("cmd queue drain timeout\n");
			up(&ar->sem);
			return -EINTR;
		}
	}

	if (test_bit(CONNECTED, &ar->flag) &&
	    ar->ssid_len == sme->ssid_len &&
	    !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
		ar->reconnect_flag = true;
		status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid,
						  ar->ch_hint);

		up(&ar->sem);
		if (status) {
			ath6kl_err("wmi_reconnect_cmd failed\n");
			return -EIO;
		}
		return 0;
	} else if (ar->ssid_len == sme->ssid_len &&
		   !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
		ath6kl_disconnect(ar);
	}

	memset(ar->ssid, 0, sizeof(ar->ssid));
	ar->ssid_len = sme->ssid_len;
	memcpy(ar->ssid, sme->ssid, sme->ssid_len);

	if (sme->channel)
		ar->ch_hint = sme->channel->center_freq;

	memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
	if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
		memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid));

	ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions);

	status = ath6kl_set_auth_type(ar, sme->auth_type);
	if (status) {
		up(&ar->sem);
		return status;
	}

	if (sme->crypto.n_ciphers_pairwise)
		ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
	else
		ath6kl_set_cipher(ar, 0, true);

	ath6kl_set_cipher(ar, sme->crypto.cipher_group, false);

	if (sme->crypto.n_akm_suites)
		ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]);

	if ((sme->key_len) &&
	    (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) {
		struct ath6kl_key *key = NULL;

		if (sme->key_idx < WMI_MIN_KEY_INDEX ||
		    sme->key_idx > WMI_MAX_KEY_INDEX) {
			ath6kl_err("key index %d out of bounds\n",
				   sme->key_idx);
			up(&ar->sem);
			return -ENOENT;
		}

		key = &ar->keys[sme->key_idx];
		key->key_len = sme->key_len;
		memcpy(key->key, sme->key, key->key_len);
		key->cipher = ar->prwise_crypto;
		ar->def_txkey_index = sme->key_idx;

		ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx,
				      ar->prwise_crypto,
				      GROUP_USAGE | TX_USAGE,
				      key->key_len,
				      NULL,
				      key->key, KEY_OP_INIT_VAL, NULL,
				      NO_SYNC_WMIFLAG);
	}

	if (!ar->usr_bss_filter) {
		clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
		if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) {
			ath6kl_err("couldn't set bss filtering\n");
			up(&ar->sem);
			return -EIO;
		}
	}

	ar->nw_type = ar->next_mode;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
		   "%s: connect called with authmode %d dot11 auth %d"
		   " PW crypto %d PW crypto len %d GRP crypto %d"
		   " GRP crypto len %d channel hint %u\n",
		   __func__,
		   ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
		   ar->prwise_crypto_len, ar->grp_crypto,
		   ar->grp_crypto_len, ar->ch_hint);

	ar->reconnect_flag = 0;
	status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
					ar->dot11_auth_mode, ar->auth_mode,
					ar->prwise_crypto,
					ar->prwise_crypto_len,
					ar->grp_crypto, ar->grp_crypto_len,
					ar->ssid_len, ar->ssid,
					ar->req_bssid, ar->ch_hint,
					ar->connect_ctrl_flags);

	up(&ar->sem);

	if (status == -EINVAL) {
		memset(ar->ssid, 0, sizeof(ar->ssid));
		ar->ssid_len = 0;
		ath6kl_err("invalid request\n");
		return -ENOENT;
	} else if (status) {
		ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
		return -EIO;
	}

	if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
	    ((ar->auth_mode == WPA_PSK_AUTH)
	     || (ar->auth_mode == WPA2_PSK_AUTH))) {
		mod_timer(&ar->disconnect_timer,
			  jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
	}

	ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
	set_bit(CONNECT_PEND, &ar->flag);

	return 0;
}
int ath6kl_wmi_set_customer_testmode_cmd(struct ath6kl_vif *vif, athcfg_wcmd_testmode_t *val)
{
	struct sk_buff *skb;
	struct WMI_CUSTOMER_TESTMODE_STRUCT *cmd;
	int ret = 0;
    bool send_wmi_flag = false;
    
    switch(val->operation) 
    {
        case ATHCFG_WCMD_TESTMODE_BSSID:
            {
                if(memcmp(testmode_private.bssid,val->bssid,sizeof(testmode_private.bssid)) != 0) {
                    memcpy(testmode_private.bssid,val->bssid,sizeof(testmode_private.bssid));
                    send_wmi_flag = true;
                }
                //printk("%s[%d] testmode_private.bssid=\"%pM\"\n",__func__,__LINE__,testmode_private.bssid);
            }
        break;
        case ATHCFG_WCMD_TESTMODE_CHAN:
            {
                if(testmode_private.chan != val->chan) {
                    testmode_private.chan = val->chan;
                    send_wmi_flag = true;
                }
                //printk("%s[%d] testmode_private.chan=%d\n",__func__,__LINE__,testmode_private.chan);        
            }
            break;
        case ATHCFG_WCMD_TESTMODE_RX:
            {
                if(testmode_private.rx != val->rx) {
                    testmode_private.rx = val->rx;   
                    send_wmi_flag = true;
                }
            }        
            break;
        case ATHCFG_WCMD_TESTMODE_ANT:            
        default:
            printk("%s[%d]Not support\n",__func__,__LINE__);
            return -1;
    }
    
    //send WMI to target
    if(send_wmi_flag) {
        testmode_private.rx = val->rx;
        skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
        if (!skb)
            return -ENOMEM;

        cmd = (struct WMI_CUSTOMER_TESTMODE_STRUCT *) skb->data;
        //transfer to little endian
        memcpy(cmd->bssid, val->bssid,  sizeof(cmd->bssid));
        cmd->chan = cpu_to_le32(val->chan); 
        cmd->operation = cpu_to_le16(val->operation);
        cmd->antenna = val->antenna;
        cmd->rx = val->rx; 

        cmd->rssi_combined = cpu_to_le32(val->rssi_combined); 
        cmd->rssi0 = cpu_to_le32(val->rssi0); 
        cmd->rssi1 = cpu_to_le32(val->rssi1); 
        cmd->rssi2 = cpu_to_le32(val->rssi2); 
        
        ret = ath6kl_wmi_cmd_send(vif, skb, WMI_SET_CUSTOM_TESTMODE,
                      NO_SYNC_WMIFLAG);
    }  
    
    if(val->operation == ATHCFG_WCMD_TESTMODE_RX) {
        if(val->rx == 1) {
            s8 n_channels = 1;
            u16 *channels = NULL;
            int i;
            set_bit(SONY_WMI_TESTMODE_RX, &vif->flag);

            //set scan param
            ath6kl_wmi_scanparams_cmd(
                            vif, 
                            0, 
                            0xffff, 
                            0,     
                            vif->sc_params.minact_chdwell_time,
                            vif->sc_params.maxact_chdwell_time,//0xffff, 
                            1000,//vif->sc_params.pas_chdwell_time, msec
                            vif->sc_params.short_scan_ratio,
                            (vif->sc_params.scan_ctrl_flags & ~ACTIVE_SCAN_CTRL_FLAGS), 
                            //vif->sc_params.scan_ctrl_flags, 
                            vif->sc_params.max_dfsch_act_time, 
                            vif->sc_params.maxact_scan_per_ssid);                  

            //assign request channel
            channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
            if (channels == NULL) {
                n_channels = 0;
            }
            
            for (i = 0; i < n_channels; i++) {
                channels[i] = ieee80211_channel_to_frequency_ath6kl((testmode_private.chan == 0 ? 1:testmode_private.chan),IEEE80211_NUM_BANDS);                    
                //printk("%s[%d]channels[%d]=%d,testmode_private.chan=%d\n",__func__,__LINE__,i,channels[i],testmode_private.chan);
            }

            ret = ath6kl_wmi_bssfilter_cmd(
                 vif,
                 ALL_BSS_FILTER, 0);
            if (ret) {
                printk("%s[%d] Fail\n",__func__,__LINE__);
                goto rx_fail;
            }                 
            ret = ath6kl_wmi_startscan_cmd(vif, WMI_LONG_SCAN, 1,
                               false, 0, 0, n_channels, channels);                              
            if (ret) {
                printk("%s[%d] Fail\n",__func__,__LINE__);
                goto rx_fail;
            }
rx_fail:            
            kfree(channels);
        } else {
            //cancel test mode scan
            clear_bit(SONY_WMI_TESTMODE_RX, &vif->flag);                 
			ath6kl_wmi_scanparams_cmd(vif, 
									   vif->sc_params.fg_start_period, 
									   vif->sc_params.fg_end_period, 
									   vif->sc_params.bg_period, 
									   vif->sc_params.minact_chdwell_time, 
									   vif->sc_params.maxact_chdwell_time, 
									   vif->sc_params.pas_chdwell_time,
									   vif->sc_params.short_scan_ratio, 
									   vif->sc_params.scan_ctrl_flags, 
									   vif->sc_params.max_dfsch_act_time,
									   vif->sc_params.maxact_scan_per_ssid);	
        }
    }
	return ret;
}