2019-11-09 10:12:08 +00:00
/******************************************************************************
*
* Copyright ( c ) 2016 - 2017 Realtek Corporation .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*************************************************************
* Description :
*
* This file is for TXBF interface mechanism
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "mp_precomp.h"
# include "../phydm_precomp.h"
# ifdef PHYDM_BEAMFORMING_SUPPORT
# if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
void beamforming_gid_paid (
void * adapter ,
PRT_TCB tcb )
{
u8 RA [ 6 ] = { 0 } ;
u8 * p_header = GET_FRAME_OF_FIRST_FRAG ( adapter , tcb ) ;
HAL_DATA_TYPE * hal_data = GET_HAL_DATA ( ( ( PADAPTER ) adapter ) ) ;
struct dm_struct * dm = & hal_data - > DM_OutSrc ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
if ( ( ( PADAPTER ) adapter ) - > HardwareType < HARDWARE_TYPE_RTL8192EE )
return ;
else if ( IS_WIRELESS_MODE_N ( ( PADAPTER ) adapter ) = = false )
return ;
# if (SUPPORT_MU_BF == 1)
if ( tcb - > tx_bf_pkt_type = = RT_BF_PKT_TYPE_BROADCAST_NDPA ) { /* @MU NDPA */
# else
if ( 0 ) {
# endif
/* @Fill G_ID and P_AID */
tcb - > G_ID = 63 ;
if ( beam_info - > first_mu_bfee_index < BEAMFORMEE_ENTRY_NUM ) {
tcb - > P_AID = beam_info - > beamformee_entry [ beam_info - > first_mu_bfee_index ] . p_aid ;
RT_DISP ( FBEAM , FBEAM_FUN , ( " [David]@%s End, G_ID=0x%X, P_AID=0x%X \n " , __func__ , tcb - > G_ID , tcb - > P_AID ) ) ;
}
} else {
GET_80211_HDR_ADDRESS1 ( p_header , & RA ) ;
/* VHT SU PPDU carrying one or more group addressed MPDUs or */
/* Transmitting a VHT NDP intended for multiple recipients */
if ( MacAddr_isBcst ( RA ) | | MacAddr_isMulticast ( RA ) | | tcb - > macId = = MAC_ID_STATIC_FOR_BROADCAST_MULTICAST ) {
tcb - > G_ID = 63 ;
tcb - > P_AID = 0 ;
} else if ( ACTING_AS_AP ( adapter ) ) {
u16 AID = ( u16 ) ( MacIdGetOwnerAssociatedClientAID ( adapter , tcb - > macId ) & 0x1ff ) ; /*@AID[0:8]*/
/*RT_DISP(FBEAM, FBEAM_FUN, ("@%s tcb->mac_id=0x%X, AID=0x%X\n", __func__, tcb->mac_id, AID));*/
tcb - > G_ID = 63 ;
if ( AID = = 0 ) /*@A PPDU sent by an AP to a non associated STA*/
tcb - > P_AID = 0 ;
else { /*Sent by an AP and addressed to a STA associated with that AP*/
u16 BSSID = 0 ;
GET_80211_HDR_ADDRESS2 ( p_header , & RA ) ;
BSSID = ( ( RA [ 5 ] & 0xf0 ) > > 4 ) ^ ( RA [ 5 ] & 0xf ) ; /*@BSSID[44:47] xor BSSID[40:43]*/
tcb - > P_AID = ( AID + BSSID * 32 ) & 0x1ff ; /*@(dec(A) + dec(B)*32) mod 512*/
}
} else if ( ACTING_AS_IBSS ( ( ( PADAPTER ) adapter ) ) ) {
tcb - > G_ID = 63 ;
/*P_AID for infrasturcture mode; MACID for ad-hoc mode. */
tcb - > P_AID = tcb - > macId ;
} else if ( MgntLinkStatusQuery ( adapter ) ) { /*@Addressed to AP*/
tcb - > G_ID = 0 ;
GET_80211_HDR_ADDRESS1 ( p_header , & RA ) ;
tcb - > P_AID = RA [ 5 ] ; /*RA[39:47]*/
tcb - > P_AID = ( tcb - > P_AID < < 1 ) | ( RA [ 4 ] > > 7 ) ;
} else {
tcb - > G_ID = 63 ;
tcb - > P_AID = 0 ;
}
/*RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X\n", __func__, tcb->G_ID, tcb->P_AID));*/
}
}
enum rt_status
beamforming_get_report_frame (
void * adapter ,
PRT_RFD rfd ,
POCTET_STRING p_pdu_os )
{
HAL_DATA_TYPE * hal_data = GET_HAL_DATA ( ( PADAPTER ) adapter ) ;
struct dm_struct * dm = & hal_data - > DM_OutSrc ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = NULL ;
u8 * p_mimo_ctrl_field , p_csi_matrix ;
u8 idx , nc , nr , CH_W ;
u16 csi_matrix_len = 0 ;
ACT_PKT_TYPE pkt_type = ACT_PKT_TYPE_UNKNOWN ;
/* @Memory comparison to see if CSI report is the same with previous one */
beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , Frame_Addr2 ( * p_pdu_os ) , & idx ) ;
if ( beamform_entry = = NULL ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s: Cannot find entry by addr \n " ,
__func__ ) ;
return RT_STATUS_FAILURE ;
}
pkt_type = PacketGetActionFrameType ( p_pdu_os ) ;
/* @-@ Modified by David */
if ( pkt_type = = ACT_PKT_VHT_COMPRESSED_BEAMFORMING ) {
p_mimo_ctrl_field = p_pdu_os - > Octet + 26 ;
nc = ( ( * p_mimo_ctrl_field ) & 0x7 ) + 1 ;
nr = ( ( ( * p_mimo_ctrl_field ) & 0x38 ) > > 3 ) + 1 ;
CH_W = ( ( ( * p_mimo_ctrl_field ) & 0xC0 ) > > 6 ) ;
/*p_csi_matrix = p_mimo_ctrl_field + 3 + nc;*/ /* 24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField) +SNR(nc=2) */
csi_matrix_len = p_pdu_os - > Length - 26 - 3 - nc ;
} else if ( pkt_type = = ACT_PKT_HT_COMPRESSED_BEAMFORMING ) {
p_mimo_ctrl_field = p_pdu_os - > Octet + 26 ;
nc = ( ( * p_mimo_ctrl_field ) & 0x3 ) + 1 ;
nr = ( ( ( * p_mimo_ctrl_field ) & 0xC ) > > 2 ) + 1 ;
CH_W = ( ( ( * p_mimo_ctrl_field ) & 0x10 ) > > 4 ) ;
/*p_csi_matrix = p_mimo_ctrl_field + 6 + nr;*/ /* 24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField) +SNR(nc=2) */
csi_matrix_len = p_pdu_os - > Length - 26 - 6 - nr ;
} else
return RT_STATUS_SUCCESS ;
PHYDM_DBG ( dm , DBG_TXBF ,
" [%s] idx=%d, pkt type=%d, nc=%d, nr=%d, CH_W=%d \n " , __func__ ,
idx , pkt_type , nc , nr , CH_W ) ;
return RT_STATUS_SUCCESS ;
}
void construct_ht_ndpa_packet (
// 2017/11 MH PHYDM compile. But why need to use windows maco?
// For all linux code, it should be useless?
//void *adapter = dm->adapter;
ADAPTER * adapter ,
//void *adapter,
u8 * RA ,
u8 * buffer ,
u32 * p_length ,
enum channel_width BW )
{
u16 duration = 0 ;
PMGNT_INFO mgnt_info = & ( ( ( PADAPTER ) adapter ) - > MgntInfo ) ;
//PMGNT_INFO mgnt_info = &((MGNT_INFO)(((PADAPTER)adapter)->MgntInfo));
OCTET_STRING p_ndpa_frame , action_content ;
u8 action_hdr [ 4 ] = { ACT_CAT_VENDOR , 0x00 , 0xe0 , 0x4c } ;
PlatformZeroMemory ( buffer , 32 ) ;
SET_80211_HDR_FRAME_CONTROL ( buffer , 0 ) ;
SET_80211_HDR_ORDER ( buffer , 1 ) ;
SET_80211_HDR_TYPE_AND_SUBTYPE ( buffer , Type_Action_No_Ack ) ;
SET_80211_HDR_ADDRESS1 ( buffer , RA ) ;
SET_80211_HDR_ADDRESS2 ( buffer , ( ( PADAPTER ) adapter ) - > CurrentAddress ) ;
SET_80211_HDR_ADDRESS3 ( buffer , ( ( PMGNT_INFO ) mgnt_info ) - > Bssid ) ;
duration = 2 * a_SifsTime + 40 ;
if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
SET_80211_HDR_DURATION ( buffer , duration ) ;
/* @HT control field */
SET_HT_CTRL_CSI_STEERING ( buffer + sMacHdrLng , 3 ) ;
SET_HT_CTRL_NDP_ANNOUNCEMENT ( buffer + sMacHdrLng , 1 ) ;
FillOctetString ( p_ndpa_frame , buffer , sMacHdrLng + sHTCLng ) ;
FillOctetString ( action_content , action_hdr , 4 ) ;
PacketAppendData ( & p_ndpa_frame , action_content ) ;
* p_length = 32 ;
}
boolean
send_fw_ht_ndpa_packet (
void * dm_void ,
u8 * RA ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
void * adapter = dm - > adapter ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u32 buf_len ;
u8 * buf_addr ;
u8 desc_len = 0 , idx = 0 , ndp_tx_rate ;
void * p_def_adapter = GetDefaultAdapter ( ( ( PADAPTER ) adapter ) ) ;
HAL_DATA_TYPE * hal_data = GET_HAL_DATA ( ( ( PADAPTER ) adapter ) ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] Start! \n " , __func__ ) ;
if ( beamform_entry = = NULL )
return false ;
ndp_tx_rate = beamforming_get_htndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetFWBuffer ( p_def_adapter , & tcb , & p_buf ) ) {
# if (DEV_BUS_TYPE != RT_PCI_INTERFACE)
desc_len = ( ( PADAPTER ) adapter ) - > HWDescHeadLength - hal_data - > USBALLDummyLength ;
# endif
buf_addr = p_buf - > Buffer . VirtualAddress + desc_len ;
construct_ht_ndpa_packet (
adapter ,
RA ,
buf_addr ,
& buf_len ,
BW ) ;
tcb - > PacketLength = buf_len + desc_len ;
tcb - > bTxEnableSwCalcDur = true ;
tcb - > BWOfPacket = BW ;
if ( ACTING_AS_IBSS ( ( ( PADAPTER ) adapter ) ) | | ACTING_AS_AP ( ( ( PADAPTER ) adapter ) ) )
tcb - > G_ID = 63 ;
tcb - > P_AID = beamform_entry - > p_aid ;
tcb - > DataRate = ndp_tx_rate ; /*rate of NDP decide by nr*/
( ( PADAPTER ) adapter ) - > HalFunc . CmdSendPacketHandler ( ( ( PADAPTER ) adapter ) , tcb , p_buf , tcb - > PacketLength , DESC_PACKET_TYPE_NORMAL , false ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
boolean
send_sw_ht_ndpa_packet (
void * dm_void ,
u8 * RA ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
void * adapter = dm - > adapter ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u8 idx = 0 , ndp_tx_rate = 0 ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
PHYDM_DBG ( dm , D BG_TXBF , " [%s] Start! \n " , __func__ ) ;
ndp_tx_rate = beamforming_get_htndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetBuffer ( adapter , & tcb , & p_buf ) ) {
construct_ht_ndpa_packet (
adapter ,
RA ,
p_buf - > Buffer . VirtualAddress ,
& tcb - > PacketLength ,
BW ) ;
tcb - > bTxEnableSwCalcDur = true ;
tcb - > BWOfPacket = BW ;
MgntSendPacket ( adapter , tcb , p_buf , tcb - > PacketLength , NORMAL_QUEUE , ndp_tx_rate ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
void construct_vht_ndpa_packet (
struct dm_struct * dm ,
u8 * RA ,
u16 AID ,
u8 * buffer ,
u32 * p_length ,
enum channel_width BW )
{
u16 duration = 0 ;
u8 sequence = 0 ;
u8 * p_ndpa_frame = buffer ;
struct _RT_NDPA_STA_INFO sta_info ;
// 2017/11 MH PHYDM compile. But why need to use windows maco?
// For all linux code, it should be useless?
//void *adapter = dm->adapter;
ADAPTER * adapter = ( PADAPTER ) ( dm - > adapter ) ;
u8 idx = 0 ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
/* @Frame control. */
SET_80211_HDR_FRAME_CONTROL ( p_ndpa_frame , 0 ) ;
SET_80211_HDR_TYPE_AND_SUBTYPE ( p_ndpa_frame , Type_NDPA ) ;
SET_80211_HDR_ADDRESS1 ( p_ndpa_frame , RA ) ;
SET_80211_HDR_ADDRESS2 ( p_ndpa_frame , beamform_entry - > my_mac_addr ) ;
// 2017/11 MH PHYDM compile. But why need to use windows maco?
// For all linux code, it should be useless?
duration = 2 * a_SifsTime + 44 ;
if ( BW = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
SET_80211_HDR_DURATION ( p_ndpa_frame , duration ) ;
sequence = * ( dm - > sounding_seq ) < < 2 ;
odm_move_memory ( dm , p_ndpa_frame + 16 , & sequence , 1 ) ;
if ( phydm_acting_determine ( dm , phydm_acting_as_ibss ) | | phydm_acting_determine ( dm , phydm_acting_as_ap ) = = false )
AID = 0 ;
sta_info . aid = AID ;
sta_info . feedback_type = 0 ;
sta_info . nc_index = 0 ;
odm_move_memory ( dm , p_ndpa_frame + 17 , ( u8 * ) & sta_info , 2 ) ;
* p_length = 19 ;
}
boolean
send_fw_vht_ndpa_packet (
void * dm_void ,
u8 * RA ,
u16 AID ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
void * adapter = dm - > adapter ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u32 buf_len ;
u8 * buf_addr ;
u8 desc_len = 0 , idx = 0 , ndp_tx_rate = 0 ;
void * p_def_adapter = GetDefaultAdapter ( ( ( PADAPTER ) adapter ) ) ;
HAL_DATA_TYPE * hal_data = GET_HAL_DATA ( ( ( PADAPTER ) adapter ) ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] Start! \n " , __func__ ) ;
if ( beamform_entry = = NULL )
return false ;
ndp_tx_rate = beamforming_get_vht_ndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetFWBuffer ( p_def_adapter , & tcb , & p_buf ) ) {
# if (DEV_BUS_TYPE != RT_PCI_INTERFACE)
desc_len = ( ( PADAPTER ) adapter ) - > HWDescHeadLength - hal_data - > USBALLDummyLength ;
# endif
buf_addr = p_buf - > Buffer . VirtualAddress + desc_len ;
construct_vht_ndpa_packet (
dm ,
RA ,
AID ,
buf_addr ,
& buf_len ,
BW ) ;
tcb - > PacketLength = buf_len + desc_len ;
tcb - > bTxEnableSwCalcDur = true ;
tcb - > BWOfPacket = BW ;
if ( phydm_acting_determine ( dm , phydm_acting_as_ibss ) | | phydm_acting_determine ( dm , phydm_acting_as_ap ) )
tcb - > G_ID = 63 ;
tcb - > P_AID = beamform_entry - > p_aid ;
tcb - > DataRate = ndp_tx_rate ; /*@decide by nr*/
( ( PADAPTER ) adapter ) - > HalFunc . CmdSendPacketHandler ( adapter , tcb , p_buf , tcb - > PacketLength , DESC_PACKET_TYPE_NORMAL , false ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] End, ret=%d \n " , __func__ , ret ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
boolean
send_sw_vht_ndpa_packet (
void * dm_void ,
u8 * RA ,
u16 AID ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
void * adapter = dm - > adapter ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u8 idx = 0 , ndp_tx_rate = 0 ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
ndp_tx_rate = beamforming_get_vht_ndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetBuffer ( adapter , & tcb , & p_buf ) ) {
construct_vht_ndpa_packet (
dm ,
RA ,
AID ,
p_buf - > Buffer . VirtualAddress ,
& tcb - > PacketLength ,
BW ) ;
tcb - > bTxEnableSwCalcDur = true ;
tcb - > BWOfPacket = BW ;
/*rate of NDP decide by nr*/
MgntSendPacket ( adapter , tcb , p_buf , tcb - > PacketLength , NORMAL_QUEUE , ndp_tx_rate ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
# ifdef SUPPORT_MU_BF
# if (SUPPORT_MU_BF == 1)
/*@
* Description : On VHT GID management frame by an MU beamformee .
*
* 2015.05 .20 . Created by tynli .
*/
enum rt_status
beamforming_get_vht_gid_mgnt_frame (
void * adapter ,
PRT_RFD rfd ,
POCTET_STRING p_pdu_os )
{
HAL_DATA_TYPE * hal_data = GET_HAL_DATA ( ( ( PADAPTER ) adapter ) ) ;
struct dm_struct * dm = & hal_data - > DM_OutSrc ;
enum rt_status rt_status = RT_STATUS_SUCCESS ;
u8 * p_buffer = NULL ;
u8 * p_raddr = NULL ;
u8 mem_status [ 8 ] = { 0 } , user_pos [ 16 ] = { 0 } ;
u8 idx ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMER_ENTRY * beamform_entry = & beam_info - > beamformer_entry [ beam_info - > mu_ap_index ] ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] On VHT GID mgnt frame! \n " , __func__ ) ;
/* @Check length*/
if ( p_pdu_os - > length < ( FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY + 16 ) ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s: Invalid length (%d) \n " , __func__ ,
p_pdu_os - > length ) ;
return RT_STATUS_INVALID_LENGTH ;
}
/* @Check RA*/
p_raddr = ( u8 * ) ( p_pdu_os - > Octet ) + 4 ;
if ( ! eq_mac_addr ( p_raddr , adapter - > CurrentAddress ) ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s: Drop because of RA error. \n " ,
__func__ ) ;
return RT_STATUS_PKT_DROP ;
}
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " On VHT GID Mgnt Frame ==>: \n " , p_pdu_os - > Octet , p_pdu_os - > length ) ;
/*Parsing Membership status array*/
p_buffer = p_pdu_os - > Octet + FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY ;
for ( idx = 0 ; idx < 8 ; idx + + ) {
mem_status [ idx ] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS ( p_buffer + idx ) ;
beamform_entry - > gid_valid [ idx ] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS ( p_buffer + idx ) ;
}
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " mem_status: " , mem_status , 8 ) ;
/* Parsing User Position array*/
p_buffer = p_pdu_os - > Octet + FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY ;
for ( idx = 0 ; idx < 16 ; idx + + ) {
user_pos [ idx ] = GET_VHT_GID_MGNT_INFO_USER_POSITION ( p_buffer + idx ) ;
beamform_entry - > user_position [ idx ] = GET_VHT_GID_MGNT_INFO_USER_POSITION ( p_buffer + idx ) ;
}
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " user_pos: " , user_pos , 16 ) ;
/* @Group ID detail printed*/
{
u8 i , j ;
u8 tmp_val ;
u16 tmp_val2 ;
for ( i = 0 ; i < 8 ; i + + ) {
tmp_val = mem_status [ i ] ;
tmp_val2 = ( ( user_pos [ i * 2 + 1 ] < < 8 ) & 0xFF00 ) + ( user_pos [ i * 2 ] & 0xFF ) ;
for ( j = 0 ; j < 8 ; j + + ) {
if ( ( tmp_val > > j ) & BIT ( 0 ) ) {
PHYDM_DBG ( dm , DBG_TXBF , " Use Group ID (%d), User Position (%d) \n " ,
( i * 8 + j ) , ( tmp_val2 > > 2 * j ) & 0x3 ) ;
}
}
}
}
/* @Indicate GID frame to IHV service. */
{
u8 indibuffer [ 24 ] = { 0 } ;
u8 indioffset = 0 ;
PlatformMoveMemory ( indibuffer + indioffset , beamform_entry - > gid_valid , 8 ) ;
indioffset + = 8 ;
PlatformMoveMemory ( indibuffer + indioffset , beamform_entry - > user_position , 16 ) ;
indioffset + = 16 ;
PlatformIndicateCustomStatus (
adapter ,
RT_CUSTOM_EVENT_VHT_RECV_GID_MGNT_FRAME ,
RT_CUSTOM_INDI_TARGET_IHV ,
indibuffer ,
indioffset ) ;
}
/* @Config HW GID table */
hal_com_txbf_config_gtab ( dm ) ;
return rt_status ;
}
/*@
* Description : Construct VHT Group ID ( GID ) management frame .
*
* 2015.05 .20 . Created by tynli .
*/
void construct_vht_gid_mgnt_frame (
struct dm_struct * dm ,
u8 * RA ,
struct _RT_BEAMFORMEE_ENTRY * beamform_entry ,
u8 * buffer ,
u32 * p_length
)
{
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
void * adapter = beam_info - > source_adapter ;
OCTET_STRING os_ftm_frame , tmp ;
FillOctetString ( os_ftm_frame , buffer , 0 ) ;
* p_length = 0 ;
ConstructMaFrameHdr (
adapter ,
RA ,
ACT_CAT_VHT ,
ACT_VHT_GROUPID_MANAGEMENT ,
& os_ftm_frame ) ;
/* @Membership status array*/
FillOctetString ( tmp , beamform_entry - > gid_valid , 8 ) ;
PacketAppendData ( & os_ftm_frame , tmp ) ;
/* User Position array*/
FillOctetString ( tmp , beamform_entry - > user_position , 16 ) ;
PacketAppendData ( & os_ftm_frame , tmp ) ;
* p_length = os_ftm_frame . length ;
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " construct_vht_gid_mgnt_frame(): \n " , buffer , * p_length ) ;
}
boolean
send_sw_vht_gid_mgnt_frame (
void * dm_void ,
u8 * RA ,
u8 idx )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u8 data_rate = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = & beam_info - > beamformee_entry [ idx ] ;
void * adapter = beam_info - > source_adapter ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] Start! \n " , __func__ ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetBuffer ( adapter , & tcb , & p_buf ) ) {
construct_vht_gid_mgnt_frame (
dm ,
RA ,
beamform_entry ,
p_buf - > Buffer . VirtualAddress ,
& tcb - > PacketLength ) ;
tcb - > bw_of_packet = CHANNEL_WIDTH_20 ;
data_rate = MGN_6M ;
MgntSendPacket ( adapter , tcb , p_buf , tcb - > PacketLength , NORMAL_QUEUE , data_rate ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
/*@
* Description : Construct VHT beamforming report poll .
*
* 2015.05 .20 . Created by tynli .
*/
void construct_vht_bf_report_poll (
struct dm_struct * dm ,
u8 * RA ,
u8 * buffer ,
u32 * p_length )
{
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
void * adapter = beam_info - > source_adapter ;
u8 * p_bf_rpt_poll = buffer ;
/* @Frame control*/
SET_80211_HDR_FRAME_CONTROL ( p_bf_rpt_poll , 0 ) ;
SET_80211_HDR_TYPE_AND_SUBTYPE ( p_bf_rpt_poll , Type_Beamforming_Report_Poll ) ;
/* @duration*/
SET_80211_HDR_DURATION ( p_bf_rpt_poll , 100 ) ;
/* RA*/
SET_VHT_BF_REPORT_POLL_RA ( p_bf_rpt_poll , RA ) ;
/* TA*/
SET_VHT_BF_REPORT_POLL_TA ( p_bf_rpt_poll , adapter - > CurrentAddress ) ;
/* @Feedback Segment Retransmission Bitmap*/
SET_VHT_BF_REPORT_POLL_FEEDBACK_SEG_RETRAN_BITMAP ( p_bf_rpt_poll , 0xFF ) ;
* p_length = 17 ;
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " construct_vht_bf_report_poll(): \n " , buffer , * p_length ) ;
}
boolean
send_sw_vht_bf_report_poll (
void * dm_void ,
u8 * RA ,
boolean is_final_poll )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u8 idx = 0 , data_rate = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
void * adapter = beam_info - > source_adapter ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] Start! \n " , __func__ ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetBuffer ( adapter , & tcb , & p_buf ) ) {
construct_vht_bf_report_poll (
dm ,
RA ,
p_buf - > Buffer . VirtualAddress ,
& tcb - > PacketLength ) ;
tcb - > bTxEnableSwCalcDur = true ; /* @<tynli_note> need?*/
tcb - > BWOfPacket = CHANNEL_WIDTH_20 ;
if ( is_final_poll )
tcb - > TxBFPktType = RT_BF_PKT_TYPE_FINAL_BF_REPORT_POLL ;
else
tcb - > TxBFPktType = RT_BF_PKT_TYPE_BF_REPORT_POLL ;
data_rate = MGN_6M ; /* @Legacy OFDM rate*/
MgntSendPacket ( adapter , tcb , p_buf , tcb - > PacketLength , NORMAL_QUEUE , data_rate ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " send_sw_vht_bf_report_poll: \n " ,
p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
/*@
* Description : Construct VHT MU NDPA packet .
* < Note > We should combine this function with construct_vht_ndpa_packet ( ) in the future .
*
* 2015.05 .21 . Created by tynli .
*/
void construct_vht_mu_ndpa_packet (
struct dm_struct * dm ,
enum channel_width BW ,
u8 * buffer ,
u32 * p_length )
{
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
void * adapter = beam_info - > source_adapter ;
u16 duration = 0 ;
u8 sequence = 0 ;
u8 * p_ndpa_frame = buffer ;
struct _RT_NDPA_STA_INFO sta_info ;
u8 idx ;
u8 dest_addr [ 6 ] = { 0 } ;
struct _RT_BEAMFORMEE_ENTRY * entry = NULL ;
/* @Fill the first MU BFee entry (STA1) MAC addr to destination address then
HW will change A1 to broadcast addr . 2015.05 .28 . Suggested by SD1 Chunchu . */
for ( idx = 0 ; idx < BEAMFORMEE_ENTRY_NUM ; idx + + ) {
entry = & ( beam_info - > beamformee_entry [ idx ] ) ;
if ( entry - > is_mu_sta ) {
cp_mac_addr ( dest_addr , entry - > mac_addr ) ;
break ;
}
}
if ( entry = = NULL )
return ;
/* @Frame control.*/
SET_80211_HDR_FRAME_CONTROL ( p_ndpa_frame , 0 ) ;
SET_80211_HDR_TYPE_AND_SUBTYPE ( p_ndpa_frame , Type_NDPA ) ;
SET_80211_HDR_ADDRESS1 ( p_ndpa_frame , dest_addr ) ;
SET_80211_HDR_ADDRESS2 ( p_ndpa_frame , entry - > my_mac_addr ) ;
/*@--------------------------------------------*/
/* @<Note> Need to modify "duration" to MU consideration. */
duration = 2 * a_SifsTime + 44 ;
if ( BW = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
/*@--------------------------------------------*/
SET_80211_HDR_DURATION ( p_ndpa_frame , duration ) ;
sequence = * ( dm - > sounding_seq ) < < 2 ;
odm_move_memory ( dm , p_ndpa_frame + 16 , & sequence , 1 ) ;
* p_length = 17 ;
/* @Construct STA info. for multiple STAs*/
for ( idx = 0 ; idx < BEAMFORMEE_ENTRY_NUM ; idx + + ) {
entry = & ( beam_info - > beamformee_entry [ idx ] ) ;
if ( entry - > is_mu_sta ) {
sta_info . aid = entry - > AID ;
sta_info . feedback_type = 1 ; /* @1'b1: MU*/
sta_info . nc_index = 0 ;
PHYDM_DBG ( dm , DBG_TXBF ,
" [%s] Get beamformee_entry idx(%d), AID =%d \n " ,
__func__ , idx , entry - > AID ) ;
odm_move_memory ( dm , p_ndpa_frame + ( * p_length ) , ( u8 * ) & sta_info , 2 ) ;
* p_length + = 2 ;
}
}
}
boolean
send_sw_vht_mu_ndpa_packet (
void * dm_void ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u8 ndp_tx_rate = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
void * adapter = beam_info - > source_adapter ;
ndp_tx_rate = MGN_VHT2SS_MCS0 ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetBuffer ( adapter , & tcb , & p_buf ) ) {
construct_vht_mu_ndpa_packet (
dm ,
BW ,
p_buf - > Buffer . VirtualAddress ,
& tcb - > PacketLength ) ;
tcb - > bTxEnableSwCalcDur = true ;
tcb - > BWOfPacket = BW ;
tcb - > TxBFPktType = RT_BF_PKT_TYPE_BROADCAST_NDPA ;
/*rate of NDP decide by nr*/
MgntSendPacket ( adapter , tcb , p_buf , tcb - > PacketLength , NORMAL_QUEUE , ndp_tx_rate ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
void dbg_construct_vht_mundpa_packet (
struct dm_struct * dm ,
enum channel_width BW ,
u8 * buffer ,
u32 * p_length )
{
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
void * adapter = beam_info - > source_adapter ;
u16 duration = 0 ;
u8 sequence = 0 ;
u8 * p_ndpa_frame = buffer ;
struct _RT_NDPA_STA_INFO sta_info ;
u8 idx ;
u8 dest_addr [ 6 ] = { 0 } ;
struct _RT_BEAMFORMEE_ENTRY * entry = NULL ;
boolean is_STA1 = false ;
/* @Fill the first MU BFee entry (STA1) MAC addr to destination address then
HW will change A1 to broadcast addr . 2015.05 .28 . Suggested by SD1 Chunchu . */
for ( idx = 0 ; idx < BEAMFORMEE_ENTRY_NUM ; idx + + ) {
entry = & ( beam_info - > beamformee_entry [ idx ] ) ;
if ( entry - > is_mu_sta ) {
if ( is_STA1 = = false ) {
is_STA1 = true ;
continue ;
} else {
cp_mac_addr ( dest_addr , entry - > mac_addr ) ;
break ;
}
}
}
/* @Frame control.*/
SET_80211_HDR_FRAME_CONTROL ( p_ndpa_frame , 0 ) ;
SET_80211_HDR_TYPE_AND_SUBTYPE ( p_ndpa_frame , Type_NDPA ) ;
SET_80211_HDR_ADDRESS1 ( p_ndpa_frame , dest_addr ) ;
SET_80211_HDR_ADDRESS2 ( p_ndpa_frame , dm - > CurrentAddress ) ;
/*@--------------------------------------------*/
/* @<Note> Need to modify "duration" to MU consideration. */
duration = 2 * a_SifsTime + 44 ;
if ( BW = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
/*@--------------------------------------------*/
SET_80211_HDR_DURATION ( p_ndpa_frame , duration ) ;
sequence = * ( dm - > sounding_seq ) < < 2 ;
odm_move_memory ( dm , p_ndpa_frame + 16 , & sequence , 1 ) ;
* p_length = 17 ;
/*STA2's STA Info*/
sta_info . aid = entry - > aid ;
sta_info . feedback_type = 1 ; /* @1'b1: MU */
sta_info . nc_index = 0 ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] Get beamformee_entry idx(%d), AID =%d \n " ,
__func__ , idx , entry - > aid ) ;
odm_move_memory ( dm , p_ndpa_frame + ( * p_length ) , ( u8 * ) & sta_info , 2 ) ;
* p_length + = 2 ;
}
boolean
dbg_send_sw_vht_mundpa_packet (
void * dm_void ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
PRT_TCB tcb ;
PRT_TX_LOCAL_BUFFER p_buf ;
boolean ret = true ;
u8 ndp_tx_rate = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
void * adapter = beam_info - > source_adapter ;
ndp_tx_rate = MGN_VHT2SS_MCS0 ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
PlatformAcquireSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( MgntGetBuffer ( adapter , & tcb , & p_buf ) ) {
dbg_construct_vht_mundpa_packet (
dm ,
BW ,
p_buf - > Buffer . VirtualAddress ,
& tcb - > PacketLength ) ;
tcb - > bTxEnableSwCalcDur = true ;
tcb - > BWOfPacket = BW ;
tcb - > TxBFPktType = RT_BF_PKT_TYPE_UNICAST_NDPA ;
/*rate of NDP decide by nr*/
MgntSendPacket ( adapter , tcb , p_buf , tcb - > PacketLength , NORMAL_QUEUE , ndp_tx_rate ) ;
} else
ret = false ;
PlatformReleaseSpinLock ( adapter , RT_TX_SPINLOCK ) ;
if ( ret )
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " " , p_buf - > Buffer . VirtualAddress , tcb - > PacketLength ) ;
return ret ;
}
# endif /*@#if (SUPPORT_MU_BF == 1)*/
# endif /*@#ifdef SUPPORT_MU_BF*/
# elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
u32 beamforming_get_report_frame (
void * dm_void ,
union recv_frame * precv_frame )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
u32 ret = _SUCCESS ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = NULL ;
u8 * pframe = precv_frame - > u . hdr . rx_data ;
u32 frame_len = precv_frame - > u . hdr . len ;
u8 * TA ;
u8 idx , offset ;
/*@Memory comparison to see if CSI report is the same with previous one*/
TA = get_addr2_ptr ( pframe ) ;
beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , TA , & idx ) ;
if ( beamform_entry - > beamform_entry_cap & BEAMFORMER_CAP_VHT_SU )
offset = 31 ; /*@24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(nc=2)*/
else if ( beamform_entry - > beamform_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT )
offset = 34 ; /*@24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(nc=2)*/
else
return ret ;
return ret ;
}
boolean
send_fw_ht_ndpa_packet (
void * dm_void ,
u8 * RA ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
struct _ADAPTER * adapter = dm - > adapter ;
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
u8 action_hdr [ 4 ] = { ACT_CAT_VENDOR , 0x00 , 0xe0 , 0x4c } ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 a_sifs_time = 0 , ndp_tx_rate = 0 , idx = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s, alloc mgnt frame fail \n " ,
__func__ ) ;
return false ;
}
/* update attribute */
pattrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( adapter , pattrib ) ;
pattrib - > qsel = QSLT_BEACON ;
ndp_tx_rate = beamforming_get_htndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
pattrib - > rate = ndp_tx_rate ;
pattrib - > bwmode = BW ;
pattrib - > order = 1 ;
pattrib - > subtype = WIFI_ACTION_NOACK ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
set_order_bit ( pframe ) ;
set_frame_sub_type ( pframe , WIFI_ACTION_NOACK ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , RA , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , beamform_entry - > my_mac_addr , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr3 , get_my_bssid ( & ( pmlmeinfo - > network ) ) , ETH_ALEN ) ;
if ( pmlmeext - > cur_wireless_mode = = WIRELESS_11B )
a_sifs_time = 10 ;
else
a_sifs_time = 16 ;
duration = 2 * a_sifs_time + 40 ;
if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
set_duration ( pframe , duration ) ;
/* @HT control field */
SET_HT_CTRL_CSI_STEERING ( pframe + 24 , 3 ) ;
SET_HT_CTRL_NDP_ANNOUNCEMENT ( pframe + 24 , 1 ) ;
_rtw_memcpy ( pframe + 28 , action_hdr , 4 ) ;
pattrib - > pktlen = 32 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( adapter , pmgntframe ) ;
return true ;
}
boolean
send_sw_ht_ndpa_packet (
void * dm_void ,
u8 * RA ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
struct _ADAPTER * adapter = dm - > adapter ;
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
u8 action_hdr [ 4 ] = { ACT_CAT_VENDOR , 0x00 , 0xe0 , 0x4c } ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 a_sifs_time = 0 , ndp_tx_rate = 0 , idx = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
ndp_tx_rate = beamforming_get_htndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s, alloc mgnt frame fail \n " ,
__func__ ) ;
return false ;
}
/*update attribute*/
pattrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( adapter , pattrib ) ;
pattrib - > qsel = QSLT_MGNT ;
pattrib - > rate = ndp_tx_rate ;
pattrib - > bwmode = BW ;
pattrib - > order = 1 ;
pattrib - > subtype = WIFI_ACTION_NOACK ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
set_order_bit ( pframe ) ;
set_frame_sub_type ( pframe , WIFI_ACTION_NOACK ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , RA , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , beamform_entry - > my_mac_addr , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr3 , get_my_bssid ( & ( pmlmeinfo - > network ) ) , ETH_ALEN ) ;
if ( pmlmeext - > cur_wireless_mode = = WIRELESS_11B )
a_sifs_time = 10 ;
else
a_sifs_time = 16 ;
duration = 2 * a_sifs_time + 40 ;
if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
set_duration ( pframe , duration ) ;
/*@HT control field*/
SET_HT_CTRL_CSI_STEERING ( pframe + 24 , 3 ) ;
SET_HT_CTRL_NDP_ANNOUNCEMENT ( pframe + 24 , 1 ) ;
_rtw_memcpy ( pframe + 28 , action_hdr , 4 ) ;
pattrib - > pktlen = 32 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( adapter , pmgntframe ) ;
return true ;
}
boolean
send_fw_vht_ndpa_packet (
void * dm_void ,
u8 * RA ,
u16 AID ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
struct _ADAPTER * adapter = dm - > adapter ;
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 sequence = 0 , a_sifs_time = 0 , ndp_tx_rate = 0 , idx = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
struct _RT_NDPA_STA_INFO sta_info ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s, alloc mgnt frame fail \n " ,
__func__ ) ;
return false ;
}
/* update attribute */
pattrib = & pmgntframe - > attrib ;
_rtw_memcpy ( pattrib - > ra , RA , ETH_ALEN ) ;
update_mgntframe_attrib ( adapter , pattrib ) ;
pattrib - > qsel = QSLT_BEACON ;
ndp_tx_rate = beamforming_get_vht_ndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
pattrib - > rate = ndp_tx_rate ;
pattrib - > bwmode = BW ;
pattrib - > subtype = WIFI_NDPA ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
set_frame_sub_type ( pframe , WIFI_NDPA ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , RA , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , beamform_entry - > my_mac_addr , ETH_ALEN ) ;
if ( is_supported_5g ( pmlmeext - > cur_wireless_mode ) | | is_supported_ht ( pmlmeext - > cur_wireless_mode ) )
a_sifs_time = 16 ;
else
a_sifs_time = 10 ;
duration = 2 * a_sifs_time + 44 ;
if ( BW = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
set_duration ( pframe , duration ) ;
sequence = beam_info - > sounding_sequence < < 2 ;
if ( beam_info - > sounding_sequence > = 0x3f )
beam_info - > sounding_sequence = 0 ;
else
beam_info - > sounding_sequence + + ;
_rtw_memcpy ( pframe + 16 , & sequence , 1 ) ;
if ( ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_ADHOC_STATE ) | | ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_AP_STATE ) )
AID = 0 ;
sta_info . aid = AID ;
sta_info . feedback_type = 0 ;
sta_info . nc_index = 0 ;
_rtw_memcpy ( pframe + 17 , ( u8 * ) & sta_info , 2 ) ;
pattrib - > pktlen = 19 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( adapter , pmgntframe ) ;
return true ;
}
boolean
send_sw_vht_ndpa_packet (
void * dm_void ,
u8 * RA ,
u16 AID ,
enum channel_width BW )
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
struct _ADAPTER * adapter = dm - > adapter ;
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct _RT_NDPA_STA_INFO ndpa_sta_info ;
u8 ndp_tx_rate = 0 , sequence = 0 , a_sifs_time = 0 , idx = 0 ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
struct _RT_BEAMFORMING_INFO * beam_info = & ( dm - > beamforming_info ) ;
struct _RT_BEAMFORMEE_ENTRY * beamform_entry = phydm_beamforming_get_bfee_entry_by_addr ( dm , RA , & idx ) ;
ndp_tx_rate = beamforming_get_vht_ndp_tx_rate ( dm , beamform_entry - > comp_steering_num_of_bfer ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] ndp_tx_rate =%d \n " , __func__ ,
ndp_tx_rate ) ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL ) {
PHYDM_DBG ( dm , DBG_TXBF , " %s, alloc mgnt frame fail \n " ,
__func__ ) ;
return false ;
}
/*update attribute*/
pattrib = & pmgntframe - > attrib ;
_rtw_memcpy ( pattrib - > ra , RA , ETH_ALEN ) ;
update_mgntframe_attrib ( adapter , pattrib ) ;
pattrib - > qsel = QSLT_MGNT ;
pattrib - > rate = ndp_tx_rate ;
pattrib - > bwmode = BW ;
pattrib - > subtype = WIFI_NDPA ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
set_frame_sub_type ( pframe , WIFI_NDPA ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , RA , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , beamform_entry - > my_mac_addr , ETH_ALEN ) ;
if ( is_supported_5g ( pmlmeext - > cur_wireless_mode ) | | is_supported_ht ( pmlmeext - > cur_wireless_mode ) )
a_sifs_time = 16 ;
else
a_sifs_time = 10 ;
duration = 2 * a_sifs_time + 44 ;
if ( BW = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( BW = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
set_duration ( pframe , duration ) ;
sequence = beam_info - > sounding_sequence < < 2 ;
if ( beam_info - > sounding_sequence > = 0x3f )
beam_info - > sounding_sequence = 0 ;
else
beam_info - > sounding_sequence + + ;
_rtw_memcpy ( pframe + 16 , & sequence , 1 ) ;
if ( ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_ADHOC_STATE ) | | ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_AP_STATE ) )
AID = 0 ;
ndpa_sta_info . aid = AID ;
ndpa_sta_info . feedback_type = 0 ;
ndpa_sta_info . nc_index = 0 ;
_rtw_memcpy ( pframe + 17 , ( u8 * ) & ndpa_sta_info , 2 ) ;
pattrib - > pktlen = 19 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( adapter , pmgntframe ) ;
PHYDM_DBG ( dm , DBG_TXBF , " [%s] [%d] \n " , __func__ , __LINE__ ) ;
return true ;
}
# endif
void beamforming_get_ndpa_frame (
void * dm_void ,
# if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
OCTET_STRING pdu_os
# elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
union recv_frame * precv_frame
# endif
)
{
struct dm_struct * dm = ( struct dm_struct * ) dm_void ;
u8 * TA ;
u8 idx , sequence ;
# if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
u8 * p_ndpa_frame = pdu_os . Octet ;
# elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
u8 * p_ndpa_frame = precv_frame - > u . hdr . rx_data ;
# endif
struct _RT_BEAMFORMER_ENTRY * beamformer_entry = NULL ; /*@Modified By Jeffery @2014-10-29*/
# if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
RT_DISP_DATA ( FBEAM , FBEAM_DATA , " beamforming_get_ndpa_frame \n " ,
pdu_os . Octet , pdu_os . Length ) ;
if ( IsCtrlNDPA ( p_ndpa_frame ) = = false )
# elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
if ( get_frame_sub_type ( p_ndpa_frame ) ! = WIFI_NDPA )
# endif
return ;
else if ( ! ( dm - > support_ic_type & ( ODM_RTL8812 | ODM_RTL8821 ) ) ) {
PHYDM_DBG ( dm , DBG_TXBF , " [%s] not 8812 or 8821A, return \n " ,
__func__ ) ;
return ;
}
# if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
TA = Frame_Addr2 ( pdu_os ) ;
# elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
TA = get_addr2_ptr ( p_ndpa_frame ) ;
# endif
/*Remove signaling TA. */
TA [ 0 ] = TA [ 0 ] & 0xFE ;
beamformer_entry = phydm_beamforming_get_bfer_entry_by_addr ( dm , TA , & idx ) ; /* @Modified By Jeffery @2014-10-29 */
/*@Break options for Clock Reset*/
if ( beamformer_entry = = NULL )
return ;
else if ( ! ( beamformer_entry - > beamform_entry_cap & BEAMFORMEE_CAP_VHT_SU ) )
return ;
/*@log_success: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/
/*@clock_reset_times: While BFer entry always doesn't receive our CSI, clock will reset again and again.So clock_reset_times is limited to 5 times.2015-04-13, Jeffery*/
else if ( ( beamformer_entry - > log_success = = 1 ) | | ( beamformer_entry - > clock_reset_times = = 5 ) ) {
PHYDM_DBG ( dm , DBG_TXBF ,
" [%s] log_seq=%d, pre_log_seq=%d, log_retry_cnt=%d, log_success=%d, clock_reset_times=%d, clock reset is no longer needed. \n " ,
__func__ , beamformer_entry - > log_seq ,
beamformer_entry - > pre_log_seq ,
beamformer_entry - > log_retry_cnt ,
beamformer_entry - > log_success ,
beamformer_entry - > clock_reset_times ) ;
return ;
}
sequence = ( p_ndpa_frame [ 16 ] ) > > 2 ;
PHYDM_DBG ( dm , DBG_TXBF ,
" [%s] Start, sequence=%d, log_seq=%d, pre_log_seq=%d, log_retry_cnt=%d, clock_reset_times=%d, log_success=%d \n " ,
__func__ , sequence , beamformer_entry - > log_seq ,
beamformer_entry - > pre_log_seq ,
beamformer_entry - > log_retry_cnt ,
beamformer_entry - > clock_reset_times ,
beamformer_entry - > log_success ) ;
if ( beamformer_entry - > log_seq ! = 0 & & beamformer_entry - > pre_log_seq ! = 0 ) {
/*Success condition*/
if ( beamformer_entry - > log_seq ! = sequence & & beamformer_entry - > pre_log_seq ! = beamformer_entry - > log_seq ) {
/* @break option for clcok reset, 2015-03-30, Jeffery */
beamformer_entry - > log_retry_cnt = 0 ;
/*@As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/
/*That is, log_success is NOT needed to be reset to zero, 2015-04-13, Jeffery*/
beamformer_entry - > log_success = 1 ;
} else { /*@Fail condition*/
if ( beamformer_entry - > log_retry_cnt = = 5 ) {
beamformer_entry - > clock_reset_times + + ;
beamformer_entry - > log_retry_cnt = 0 ;
PHYDM_DBG ( dm , DBG_TXBF ,
" [%s] Clock Reset!!! clock_reset_times=%d \n " ,
__func__ ,
beamformer_entry - > clock_reset_times ) ;
hal_com_txbf_set ( dm , TXBF_SET_SOUNDING_CLK , NULL ) ;
} else
beamformer_entry - > log_retry_cnt + + ;
}
}
/*Update log_seq & pre_log_seq*/
beamformer_entry - > pre_log_seq = beamformer_entry - > log_seq ;
beamformer_entry - > log_seq = sequence ;
}
# endif