software/drivers/sd8887/src/wlan/mlinux/moal_ioctl.c
/**
 *  @brief Check current uap/go connection status
 *         Need handle channel switch if current channel is DFS channel
 *
 *  @param priv          A pointer to moal_private structure
 *  @param wait_option          Wait option
 *  @param new channel 		new channel
 *  @return              N/A
 */
@brief Check current uap/go connection status
Need handle channel switch if current channel is DFS channel

@param priv          A pointer to moal_private structure
@param wait_option          Wait option
@param new channel          new channel
@return              N/A
@brief Check current uap / go connection status Need handle channel switch if current channel is DFS channel @param priv A pointer to moal_private structure @param wait_option Wait option @param new channel new channel @return N / A
void
woal_check_uap_dfs_status(moal_private *priv, t_u8 wait_option,
			  t_u8 new_channel)
{
	chan_band_info channel;
	mlan_bss_info bss_info;
#if defined(UAP_SUPPORT)
	IEEEtypes_ChanSwitchAnn_t *chan_switch = NULL;
	IEEEtypes_ExtChanSwitchAnn_t *ext_chan_switch = NULL;
	custom_ie *pcust_chansw_ie = NULL;
	mlan_ioctl_req *ioctl_req = NULL;
	mlan_ds_misc_cfg *misc = NULL;
	mlan_status status = MLAN_STATUS_SUCCESS;
	t_u8 bw = 0, oper_class = 0;
#endif
	if (MLAN_STATUS_SUCCESS !=
	    woal_get_bss_info(priv, wait_option, &bss_info))
		goto done;
	if (MLAN_STATUS_SUCCESS !=
	    woal_set_get_ap_channel(priv, MLAN_ACT_GET, wait_option, &channel))
		goto done;
	PRINTM(MCMND, "is_11h_active=%d dfs_check_channel=%d\n",
	       bss_info.is_11h_active, bss_info.dfs_check_channel);
	PRINTM(MCMND, "uap current channel=%d new_channel=%d\n",
	       channel.channel, new_channel);
#if defined(UAP_SUPPORT)
	if (new_channel == channel.channel)
		goto done;
	if (bss_info.is_11h_active &&
	    (bss_info.dfs_check_channel == channel.channel)) {
		if (new_channel < MAX_BG_CHANNEL) {
			bw = 20;
		} else {
			switch (channel.bandcfg.chanWidth) {
			case CHAN_BW_20MHZ:
				bw = 20;
				break;
			case CHAN_BW_40MHZ:
				bw = 40;
				break;
			case CHAN_BW_80MHZ:
				bw = 80;
				break;
			default:
				break;
			}
		}
		woal_priv_get_nonglobal_operclass_by_bw_channel(priv, bw,
								new_channel,
								&oper_class);
		PRINTM(MCMND,
		       "Switch the uap channel from %d to %d, oper_class=%d bw=%d\n",
		       channel.channel, new_channel, oper_class, bw);
		ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
		if (ioctl_req) {
			misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
			misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
			ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
			ioctl_req->action = MLAN_ACT_SET;
			misc->param.cust_ie.type = TLV_TYPE_MGMT_IE;
			misc->param.cust_ie.len =
				sizeof(custom_ie) - MAX_IE_SIZE;
			pcust_chansw_ie =
				(custom_ie *)&misc->param.cust_ie.
				ie_data_list[0];
			pcust_chansw_ie->ie_index = 0xffff;	
			if (!oper_class) {
				pcust_chansw_ie->ie_length =
					sizeof(IEEEtypes_ChanSwitchAnn_t);
				pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	
				chan_switch =
					(IEEEtypes_ChanSwitchAnn_t *)
					pcust_chansw_ie->ie_buffer;
				chan_switch->element_id = CHANNEL_SWITCH_ANN;
				chan_switch->len =
					sizeof(IEEEtypes_ChanSwitchAnn_t) -
					sizeof(IEEEtypes_Header_t);
				chan_switch->chan_switch_mode = 1;	
				chan_switch->new_channel_num = new_channel;
				chan_switch->chan_switch_count =
					DEF_CHAN_SWITCH_COUNT;
				DBG_HEXDUMP(MCMD_D, "CSA IE",
					    (t_u8 *)pcust_chansw_ie->ie_buffer,
					    pcust_chansw_ie->ie_length);
			} else {
				pcust_chansw_ie->ie_length =
					sizeof(IEEEtypes_ExtChanSwitchAnn_t);
				pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	
				ext_chan_switch =
					(IEEEtypes_ExtChanSwitchAnn_t *)
					pcust_chansw_ie->ie_buffer;
				ext_chan_switch->element_id =
					EXTEND_CHANNEL_SWITCH_ANN;
				ext_chan_switch->len =
					sizeof(IEEEtypes_ExtChanSwitchAnn_t) -
					sizeof(IEEEtypes_Header_t);
				ext_chan_switch->chan_switch_mode = 1;	
				ext_chan_switch->new_channel_num = new_channel;
				ext_chan_switch->chan_switch_count =
					DEF_CHAN_SWITCH_COUNT;
				ext_chan_switch->new_oper_class = oper_class;
				DBG_HEXDUMP(MCMD_D, "ECSA IE",
					    (t_u8 *)pcust_chansw_ie->ie_buffer,
					    pcust_chansw_ie->ie_length);
			}
			status = woal_request_ioctl(priv, ioctl_req,
						    wait_option);
			if (status != MLAN_STATUS_SUCCESS) {
				PRINTM(MERROR, "Failed to set CSA IE\n");
				goto done;
			}
			PRINTM(MCMND, "CSA/ECSA ie index=%d\n",
			       pcust_chansw_ie->ie_index);
			priv->phandle->chsw_wait_q_woken = MFALSE;
			wait_event_interruptible_timeout(priv->phandle->
							 chsw_wait_q,
							 priv->phandle->
							 chsw_wait_q_woken,
							 (u32)HZ *
							 (DEF_CHAN_SWITCH_COUNT
							  + 2) * 110 / 1000);
			pcust_chansw_ie->ie_index = 0xffff;
			pcust_chansw_ie->mgmt_subtype_mask =
				MLAN_CUSTOM_IE_DELETE_MASK;
			status = woal_request_ioctl(priv, ioctl_req,
						    MOAL_IOCTL_WAIT);
			if (status != MLAN_STATUS_SUCCESS) {
				PRINTM(MERROR, "Failed to clear CSA/ECSA IE\n");
			}
		}
	}
#endif
done:
#if defined(UAP_SUPPORT)
	if (status != MLAN_STATUS_PENDING)
		kfree(ioctl_req);
#endif
	return;
}
void woal_check_uap_dfs_status ( moal_private * priv , t_u8 wait_option , t_u8 new_channel ) { chan_band_info channel ; mlan_bss_info bss_info ; #if defined ( UAP_SUPPORT ) IEEEtypes_ChanSwitchAnn_t * chan_switch = NULL ; IEEEtypes_ExtChanSwitchAnn_t * ext_chan_switch = NULL ; custom_ie * pcust_chansw_ie = NULL ; mlan_ioctl_req * ioctl_req = NULL ; mlan_ds_misc_cfg * misc = NULL ; mlan_status status = MLAN_STATUS_SUCCESS ; t_u8 bw = 0 , oper_class = 0 ; #endif if ( MLAN_STATUS_SUCCESS != woal_get_bss_info ( priv , wait_option , & bss_info ) ) goto done ; if ( MLAN_STATUS_SUCCESS != woal_set_get_ap_channel ( priv , MLAN_ACT_GET , wait_option , & channel ) ) goto done ; PRINTM ( MCMND , " \n " , bss_info . is_11h_active , bss_info . dfs_check_channel ) ; PRINTM ( MCMND , " \n " , channel . channel , new_channel ) ; #if defined ( UAP_SUPPORT ) if ( new_channel == channel . channel ) goto done ; if ( bss_info . is_11h_active && ( bss_info . dfs_check_channel == channel . channel ) ) { if ( new_channel < MAX_BG_CHANNEL ) { bw = 20 ; } else { switch ( channel . bandcfg . chanWidth ) { case CHAN_BW_20MHZ : bw = 20 ; break ; case CHAN_BW_40MHZ : bw = 40 ; break ; case CHAN_BW_80MHZ : bw = 80 ; break ; default : break ; } } woal_priv_get_nonglobal_operclass_by_bw_channel ( priv , bw , new_channel , & oper_class ) ; PRINTM ( MCMND , " \n " , channel . channel , new_channel , oper_class , bw ) ; ioctl_req = woal_alloc_mlan_ioctl_req ( sizeof ( mlan_ds_misc_cfg ) ) ; if ( ioctl_req ) { misc = ( mlan_ds_misc_cfg * ) ioctl_req -> pbuf ; misc -> sub_command = MLAN_OID_MISC_CUSTOM_IE ; ioctl_req -> req_id = MLAN_IOCTL_MISC_CFG ; ioctl_req -> action = MLAN_ACT_SET ; misc -> param . cust_ie . type = TLV_TYPE_MGMT_IE ; misc -> param . cust_ie . len = sizeof ( custom_ie ) - MAX_IE_SIZE ; pcust_chansw_ie = ( custom_ie * ) & misc -> param . cust_ie . ie_data_list [ 0 ] ; pcust_chansw_ie -> ie_index = 0xffff ; if ( ! oper_class ) { pcust_chansw_ie -> ie_length = sizeof ( IEEEtypes_ChanSwitchAnn_t ) ; pcust_chansw_ie -> mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP ; chan_switch = ( IEEEtypes_ChanSwitchAnn_t * ) pcust_chansw_ie -> ie_buffer ; chan_switch -> element_id = CHANNEL_SWITCH_ANN ; chan_switch -> len = sizeof ( IEEEtypes_ChanSwitchAnn_t ) - sizeof ( IEEEtypes_Header_t ) ; chan_switch -> chan_switch_mode = 1 ; chan_switch -> new_channel_num = new_channel ; chan_switch -> chan_switch_count = DEF_CHAN_SWITCH_COUNT ; DBG_HEXDUMP ( MCMD_D , " " , ( t_u8 * ) pcust_chansw_ie -> ie_buffer , pcust_chansw_ie -> ie_length ) ; } else { pcust_chansw_ie -> ie_length = sizeof ( IEEEtypes_ExtChanSwitchAnn_t ) ; pcust_chansw_ie -> mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP ; ext_chan_switch = ( IEEEtypes_ExtChanSwitchAnn_t * ) pcust_chansw_ie -> ie_buffer ; ext_chan_switch -> element_id = EXTEND_CHANNEL_SWITCH_ANN ; ext_chan_switch -> len = sizeof ( IEEEtypes_ExtChanSwitchAnn_t ) - sizeof ( IEEEtypes_Header_t ) ; ext_chan_switch -> chan_switch_mode = 1 ; ext_chan_switch -> new_channel_num = new_channel ; ext_chan_switch -> chan_switch_count = DEF_CHAN_SWITCH_COUNT ; ext_chan_switch -> new_oper_class = oper_class ; DBG_HEXDUMP ( MCMD_D , " " , ( t_u8 * ) pcust_chansw_ie -> ie_buffer , pcust_chansw_ie -> ie_length ) ; } status = woal_request_ioctl ( priv , ioctl_req , wait_option ) ; if ( status != MLAN_STATUS_SUCCESS ) { PRINTM ( MERROR , " \n " ) ; goto done ; } PRINTM ( MCMND , " \n " , pcust_chansw_ie -> ie_index ) ; priv -> phandle -> chsw_wait_q_woken = MFALSE ; wait_event_interruptible_timeout ( priv -> phandle -> chsw_wait_q , priv -> phandle -> chsw_wait_q_woken , ( u32 ) HZ * ( DEF_CHAN_SWITCH_COUNT + 2 ) * 110 / 1000 ) ; pcust_chansw_ie -> ie_index = 0xffff ; pcust_chansw_ie -> mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK ; status = woal_request_ioctl ( priv , ioctl_req , MOAL_IOCTL_WAIT ) ; if ( status != MLAN_STATUS_SUCCESS ) { PRINTM ( MERROR , " \n " ) ; } } } #endif done : #if defined ( UAP_SUPPORT ) if ( status != MLAN_STATUS_PENDING ) kfree ( ioctl_req ) ; #endif return ; }
@brief Check current uap/go connection status
         Need handle channel switch if current channel is DFS channel
@brief Check current uap / go connection status Need handle channel switch if current channel is DFS channel
/* Get BSS information */ /*Auto index */ /*Add IE for BEACON/probe resp */ /* STA should not transmit */ /*Add IE for BEACON/probe resp */ /* STA should not transmit */ /* wait for channel switch to complete  */