/************************************************************************ * buildNullTemplate * ************************************************************************ DESCRIPTION: This function build a NULL data template to set to the HAL when joining an infrastructure network performs the following: - Build a template & set the template len, the template type is set in the site mgr INPUT: pSiteMgr - Handle to site manager pTemplate - Pointer to the template structure OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildNullTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate) { paramInfo_t param; nullDataTemplate_t *pBuffer = (nullDataTemplate_t *) pTemplate->ptr; siteEntry_t *pPrimarySite = pSiteMgr->pSitesMgmtParams->pPrimarySite; TI_UINT16 fc; os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(nullDataTemplate_t)); /* * Header First */ /* Set destination address */ MAC_COPY(pBuffer->hdr.DA, pPrimarySite->bssid); /* Set BSSID address */ MAC_COPY(pBuffer->hdr.BSSID, pPrimarySite->bssid); /* Build Source address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.SA, param.content.ctrlDataDeviceMacAddress); fc = DOT11_FC_DATA_NULL_FUNCTION; fc |= (TI_TRUE << DOT11_FC_TO_DS_SHIFT); COPY_WLAN_WORD(&pBuffer->hdr.fc, &fc); /* copy with endianess handling. */ pTemplate->len = sizeof(dot11_mgmtHeader_t); return TI_OK; }
/************************************************************************ * insertMeasurementIEToQueue * ************************************************************************ DESCRIPTION: The function inserts measurement request of one received measurement request information element. INPUT: hRequestHandler - A Handler to the Request Handler Object. frameToken - Frame token of the received frame in which This current measurement request IE is included. measurementObjMode - XCC or SPECTRUM_MNGMNT dataLen - pointer to the data length that is left. pData - pointer to the data. OUTPUT: singelRequestLen - The Length of the request that was inserted to the queue. RETURN: TI_OK on success, TI_NOK otherwise ************************************************************************/ static TI_STATUS insertMeasurementIEToQueue(TI_HANDLE hRequestHandler, TI_UINT16 frameToken, EMeasurementMode measurementObjMode, TI_UINT8 *pData, TI_UINT8 *singelRequestLen) { requestHandler_t *pRequestHandler = (requestHandler_t *)hRequestHandler; TI_UINT16 HeaderLen; TI_UINT8 measurementMode; TI_UINT8 parallelBit; TI_UINT8 enableBit; TI_UINT16 measurementToken; MeasurementRequest_t *pCurrRequest = &(pRequestHandler->reqArr[pRequestHandler->numOfWaitingRequests]); if (pRequestHandler->parserRequestIEHdr(pData, &HeaderLen, &measurementToken) != TI_OK) { return TI_NOK; } pCurrRequest->frameToken = frameToken; pCurrRequest->measurementToken = measurementToken; pData += HeaderLen; /*** Getting the Measurement Mode ***/ measurementMode = *pData++; /* getting parallel bit */ parallelBit = measurementMode & 0x1; /* getting Enable bit */ enableBit = (measurementMode & 0x2)>>1; /* checking enable bit, the current implementation does not support enable bit which set to one, so there is no need to check request/report bits */ if (enableBit == 1) return TI_OK; pCurrRequest->isParallel = parallelBit; /* Getting the Measurement Mode */ pCurrRequest->Type = (EMeasurementType)(*pData++); /* Inserting the request that is included in the current measurement request IE. */ pCurrRequest->channelNumber = *pData++; pCurrRequest->ScanMode = (EMeasurementScanMode)(*pData++); /* IN dot11h - Spare = 0 */ COPY_WLAN_WORD(&pCurrRequest->DurationTime, pData); *singelRequestLen = HeaderLen + 6; pRequestHandler->numOfWaitingRequests ++; return TI_OK; }
/************************************************************************ * buildQosNullDataTemplate * ************************************************************************ DESCRIPTION: This function build a qos null data template performs the following: - Build a template & set the template len, the template type is set in the site mgr INPUT: pSiteMgr - Handle to site manager pTemplate - Pointer to the template structure pSsid - Desired SSID OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildQosNullDataTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate, TI_UINT8 userPriority) { paramInfo_t param; TI_UINT32 size; QosNullDataTemplate_t *pBuffer = (QosNullDataTemplate_t *) pTemplate->ptr; siteEntry_t *pPrimarySite = pSiteMgr->pSitesMgmtParams->pPrimarySite; TI_UINT16 fc; TI_UINT16 qosControl; os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(QosNullDataTemplate_t)); /* * Header First */ /* Set destination address */ if (pPrimarySite) { MAC_COPY(pBuffer->hdr.address1, pPrimarySite->bssid); /* Set BSSID address */ MAC_COPY(pBuffer->hdr.address3, pPrimarySite->bssid); } else { TRACE0(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "No Primary site so cannot fill QosNullData template\n"); } /* Build Source address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.address2, param.content.ctrlDataDeviceMacAddress); fc = DOT11_FC_DATA_NULL_QOS | (1 << DOT11_FC_TO_DS_SHIFT); COPY_WLAN_WORD(&pBuffer->hdr.fc, &fc); /* copy with endianess handling. */ qosControl = (TI_UINT16) userPriority; qosControl <<= QOS_CONTROL_UP_SHIFT; COPY_WLAN_WORD(&pBuffer->hdr.qosControl, &qosControl); /* copy with endianess handling. */ size = WLAN_QOS_HDR_LEN; pTemplate->len = size; return TI_OK; }
/************************************************************************ * buildPsPollTemplate * ************************************************************************ DESCRIPTION: This function build a ps poll template performs the following: - Build a template & set the template len, the template type is set in the site mgr INPUT: pSiteMgr - Handle to site manager pTemplate - Pointer to the template structure pSsid - Desired SSID OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildPsPollTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate) { paramInfo_t param; TTwdParamInfo tTwdParam; TI_UINT32 size; psPollTemplate_t *pBuffer = (psPollTemplate_t *) pTemplate->ptr; siteEntry_t *pPrimarySite = pSiteMgr->pSitesMgmtParams->pPrimarySite; TI_UINT16 fc; os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(psPollTemplate_t)); /* * Header First */ /* Set BSSID address */ MAC_COPY(pBuffer->hdr.BSSID, pPrimarySite->bssid); /* Build Source address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.TA, param.content.ctrlDataDeviceMacAddress); /* ** Building the Frame Control word (16 bits) ** --------------------------------------------- ** Type = Control ** SubType = Power Save (PS) POLL, */ fc = DOT11_FC_PS_POLL; /* ** setting the Power Management bit in the Frame control field ** to be "Power Save mode" */ fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT); COPY_WLAN_WORD(&pBuffer->hdr.fc, &fc); /* copy with endianess handling. */ /* ** Association ID ** ----------------- */ tTwdParam.paramType = TWD_AID_PARAM_ID; TWD_GetParam(pSiteMgr->hTWD, &tTwdParam); /* AID should have its two MSB bit Set to "1" */ pBuffer->hdr.AID = tTwdParam.content.halCtrlAid | 0xC000; size = sizeof(dot11_PsPollFrameHeader_t); pTemplate->len = size; return TI_OK; }
/*********************************************************************** * txCtrlServ_buildNullFrame *********************************************************************** DESCRIPTION: Build Null frame Function. The function does the following: - Builds Null Data Frame, considering current QoS mode. INPUT: hTxCtrl - Tx Ctrl module handle (the txServ uses the txCtrl object!!). pFrame - A pointer to a buffer where the frame should be stored pLength - A pointer to a placeholder for the frame length ************************************************************************/ TI_STATUS txCtrlServ_buildNullFrame(TI_HANDLE hTxCtrl, TI_UINT8* pFrame, TI_UINT32* pLength) { txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl; EHeaderConvertMode qosMode = pTxCtrl->headerConverMode; dot11_header_t *pHeader; /* Note : there is no body for null frame */ TI_STATUS status; TI_UINT16 fc; pHeader = (dot11_header_t*)(pFrame); if (qosMode == HDR_CONVERT_QOS) { *pLength = WLAN_QOS_HDR_LEN; SET_WLAN_WORD(&pHeader->qosControl, 0); /* We are using user priority 0 (BE) so no need for shift and endianess */ } else { *pLength = WLAN_HDR_LEN; } /* Set the Frame Control with Null Data type, QoS or non-QoS */ if (qosMode == HDR_CONVERT_QOS) fc = DOT11_FC_DATA_NULL_QOS | DOT11_FC_TO_DS; else fc = DOT11_FC_DATA_NULL_FUNCTION | DOT11_FC_TO_DS; COPY_WLAN_WORD(&pHeader->fc, &fc); /* copy with endianess handling. */ /* copy destination mac address */ status = ctrlData_getParamBssid(pTxCtrl->hCtrlData, CTRL_DATA_CURRENT_BSSID_PARAM, pHeader->address3); if (status != TI_OK) { return TI_NOK; } /* copy source mac address */ status = ctrlData_getParamBssid(pTxCtrl->hCtrlData, CTRL_DATA_MAC_ADDRESS, pHeader->address2); if (status != TI_OK) { return TI_NOK; } /* copy BSSID (destination mac address) */ MAC_COPY (pHeader->address1, pHeader->address3); return status; }
TI_STATUS mlmeBuilder_buildFrameCtrl(mlme_t* pMlme, dot11MgmtSubType_e type, TI_UINT16* pFctrl, TI_UINT8 setWepOpt) { TI_UINT16 fc = 0; switch (type) { case ASSOC_REQUEST: fc |= DOT11_FC_ASSOC_REQ; break; case ASSOC_RESPONSE: fc |= DOT11_FC_ASSOC_RESP; break; case RE_ASSOC_REQUEST: fc |= DOT11_FC_REASSOC_REQ; break; case RE_ASSOC_RESPONSE: fc |= DOT11_FC_REASSOC_RESP; break; case DIS_ASSOC: fc |= DOT11_FC_DISASSOC; break; case AUTH: fc |= DOT11_FC_AUTH; break; case DE_AUTH: fc |= DOT11_FC_DEAUTH; break; case ACTION: fc |= DOT11_FC_ACTION; break; default: *pFctrl = 0; return TI_NOK; } if (setWepOpt) { fc |= DOT11_FC_WEP; } COPY_WLAN_WORD(pFctrl, &fc); /* copy with endianess handling. */ return TI_OK; }
/************************************************************************ * buildDisconnTemplate * ************************************************************************ DESCRIPTION: This function build a Death/Disassoc template to set to the HAL when joining an infrastructure network performs the following: - Build a template & set the template len, the template type is set in the site mgr INPUT: pSiteMgr - Handle to site manager pTemplate - Pointer to the template structure OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildDisconnTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate) { paramInfo_t param; TI_UINT32 size; disconnTemplate_t *pBuffer = (disconnTemplate_t *) pTemplate->ptr; siteEntry_t *pPrimarySite = pSiteMgr->pSitesMgmtParams->pPrimarySite; TI_UINT16 fc; os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(disconnTemplate_t)); /* * Header First */ /* Set destination address */ MAC_COPY(pBuffer->hdr.DA, pPrimarySite->bssid); /* Set BSSID address */ MAC_COPY(pBuffer->hdr.BSSID, pPrimarySite->bssid); /* Build Source address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.SA, param.content.ctrlDataDeviceMacAddress); fc = DOT11_FC_DISASSOC; /* will be change by firmware to DOT11_FC_DEAUTH if needed */ COPY_WLAN_WORD(&pBuffer->hdr.fc, &fc); /* copy with endianess handling. */ pBuffer->disconnReason = 0; /* filled by firmware */ size = sizeof(disconnTemplate_t); pTemplate->len = size; return TI_OK; }
/************************************************************************ * buildArpRspTemplate * ************************************************************************ DESCRIPTION: This function builds an ARP Response template to set to the HAL when joining an infrastructure network. The function's steps: - It builds the template & set the template len. - If QoS is inactive, it discards the QoS Control Field. ** The template type is set in the site mgr. INPUT: pSiteMgr - Handle to site manager. pTemplate - Pointer to the template structure. OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildArpRspTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate, TIpAddr staIp) { siteEntry_t *pPrimarySite = pSiteMgr->pSitesMgmtParams->pPrimarySite; ArpRspTemplate_t *pBuffer = (ArpRspTemplate_t *) pTemplate->ptr; TI_UINT8 *ptr = (TI_UINT8 *) pBuffer; paramInfo_t param; /* To get Site and QoS params */ TI_UINT16 fc; /* Frame Control field in MAC header */ TI_UINT16 macAddrItr; TI_BOOL privacyInvoked; TI_UINT8 encryptionFieldSize, copyPayloadOffset, lenToCopy; /* Reset the buffer */ os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(ArpRspTemplate_t)); /* Turn on the To_DS bit in the Frame Control field */ fc = (1 << DOT11_FC_TO_DS_SHIFT); /* Set MAC header address fields: ----------------------------- Since To_DS is on and From_DS is off the address meaning is as follows: Address1 - BSSID Address2 - Source Address Address3 - Destination Address Address4 - Not present */ /* - Set BSSID */ if (pPrimarySite) { MAC_COPY(pBuffer->hdr.address1, pPrimarySite->bssid); } else { TRACE0(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "No Primary site so cannot fill QosNullData template.\n"); } /* - Set Source Address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.address2, param.content.ctrlDataDeviceMacAddress); /* - Set Destination Address: ARP response should be sent with broadcast DA - Set accordingly */ for (macAddrItr = 0; macAddrItr < MAC_ADDR_LEN; macAddrItr++) { pBuffer->hdr.address3[macAddrItr] = 0xFF; } pBuffer->LLC.DSAP = 0xaa; pBuffer->LLC.SSAP = 0xaa; pBuffer->LLC.Control = 0x03; /* pBuffer->LLC.Control.OUI these 3 bytes are zeroed already */ pBuffer->LLC.Type = WLANTOHS((TI_UINT16) 0x806); pBuffer->hardType = WLANTOHS((TI_UINT16) 1); pBuffer->protType = WLANTOHS((TI_UINT16) 0x800); pBuffer->hardSize = 6; pBuffer->protSize = 4; pBuffer->op = WLANTOHS((TI_UINT16) 2); /*filled as for ARP-RSP, not for RARP_RSP */ MAC_COPY(pBuffer->StaMac, pBuffer->hdr.address2); IP_COPY(pBuffer->StaIp, staIp); pTemplate->len = sizeof(ArpRspTemplate_t); /* Get encryption status */ txCtrlParams_getCurrentEncryptionInfo(pSiteMgr->hTxCtrl, &privacyInvoked, &encryptionFieldSize); /* If no encryption is used, encryptionFieldSize has garbage value */ encryptionFieldSize = privacyInvoked ? encryptionFieldSize : 0; /* Set the subtype field of fc with WEP_BIT */ fc |= (privacyInvoked << DOT11_FC_WEP_SHIFT); /* Get QoS type to check if QoS is active */ param.paramType = QOS_MNGR_ACTIVE_PROTOCOL; qosMngr_getParams(pSiteMgr->hQosMngr, ¶m); if (param.content.qosSiteProtocol == QOS_NONE) { /* QoS is not active */ copyPayloadOffset = sizeof(pBuffer->hdr.qosControl) + AES_AFTER_HEADER_FIELD_SIZE - encryptionFieldSize; /* Set the subtype field of fc with DATA value (non Qos) */ fc |= DOT11_FC_DATA; } else { /* QoS is active */ copyPayloadOffset = AES_AFTER_HEADER_FIELD_SIZE - encryptionFieldSize; /* Set the subtype field of fc with DATA_QOS */ fc |= DOT11_FC_DATA_QOS; } /* Need to copy backward to overwrite security or QoS offset */ if (copyPayloadOffset > 0) { ptr = (TI_UINT8 *) & pBuffer->LLC.DSAP; /* Copy back the actual payload without header & security */ lenToCopy = sizeof(ArpRspTemplate_t) - sizeof(dot11_header_t) - AES_AFTER_HEADER_FIELD_SIZE; os_memoryCopy(pSiteMgr->hOs, ptr - copyPayloadOffset, ptr, lenToCopy); pTemplate->len -= copyPayloadOffset; } COPY_WLAN_WORD(&pBuffer->hdr.fc, &fc); /* copy with endianess handling. */ return TI_OK; }
/************************************************************************ * buildProbeRspTemplate * ************************************************************************ DESCRIPTION: This function build a probe response template to set to the HAL when joining an IBSS network. performs the following: - Build a template & set the template len, the template type is set in the site mgr - The template is built based on the chosen site attributes NOTE: This function is used to build beacon template too. The site manager set the template type (after thos function returns) to beacon or probe response accordingly. INPUT: pSiteMgr - Handle to site manager pTemplate - Pointer to the template structure OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildProbeRspTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate) { paramInfo_t param; TI_UINT8 *pBuf; probeRspTemplate_t *pBuffer = (probeRspTemplate_t *) pTemplate->ptr; siteEntry_t *pPrimarySite = pSiteMgr->pSitesMgmtParams->pPrimarySite; TI_INT32 i, j; TI_UINT32 size; dot11_RATES_t *pDot11Rates; dot11_ERP_t *pdot11Erp; TI_UINT32 len = 0, ofdmIndex = 0; TI_BOOL extRates = TI_FALSE; TI_BOOL useProtection, NonErpPresent, barkerPreambleType; TCountry *pCountry = NULL; TI_UINT8 ratesBuf[DOT11_MAX_SUPPORTED_RATES]; TI_UINT32 supportedRateMask, basicRateMask; TI_UINT16 headerFC = DOT11_FC_PROBE_RESP; os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(probeRspTemplate_t)); /* * Build WLAN Header: * ================== */ /* Set destination address */ for (i = 0; i < MAC_ADDR_LEN; i++) pBuffer->hdr.DA[i] = 0xFF; /* Set BSSID address */ MAC_COPY(pBuffer->hdr.BSSID, pPrimarySite->bssid); /* Build Source address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.SA, param.content.ctrlDataDeviceMacAddress); COPY_WLAN_WORD(&pBuffer->hdr.fc, &headerFC); size = sizeof(dot11_mgmtHeader_t); pBuf = (TI_UINT8 *) pBuffer->timeStamp; /* * Fixed Fields */ /* we skip the timestamp field */ size += TIME_STAMP_LEN; pBuf += TIME_STAMP_LEN; /* Beacon interval */ COPY_WLAN_WORD(pBuf, &pPrimarySite->beaconInterval); size += FIX_FIELD_LEN; pBuf += FIX_FIELD_LEN; /* capabilities */ COPY_WLAN_WORD(pBuf, &pPrimarySite->capabilities); size += FIX_FIELD_LEN; pBuf += FIX_FIELD_LEN; /* * Build Informataion Elements: * ============================ */ /* SSID IE */ /* It looks like it never happens. Anyway decided to check */ if (pPrimarySite->ssid.len > MAX_SSID_LEN) { TRACE2(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "buildProbeRspTemplate. pPrimarySite->ssid.len=%d exceeds the limit %d\n", pPrimarySite->ssid.len, MAX_SSID_LEN); handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION); return TI_NOK; } ((dot11_SSID_t *) (pBuf))->hdr[0] = DOT11_SSID_ELE_ID; ((dot11_SSID_t *) (pBuf))->hdr[1] = pPrimarySite->ssid.len; os_memoryCopy(pSiteMgr->hOs, pBuf + sizeof(dot11_eleHdr_t), (void *)pPrimarySite->ssid.str, pPrimarySite->ssid.len); size += sizeof(dot11_eleHdr_t) + pPrimarySite->ssid.len; pBuf += sizeof(dot11_eleHdr_t) + pPrimarySite->ssid.len; /* Rates IE */ pDot11Rates = (dot11_RATES_t *) pBuf; if (pPrimarySite->channel == SPECIAL_BG_CHANNEL) { supportedRateMask = rate_GetDrvBitmapForDefaultSupporteSet(); basicRateMask = rate_GetDrvBitmapForDefaultBasicSet(); } else { supportedRateMask = pSiteMgr->pDesiredParams->siteMgrMatchedSuppRateMask; basicRateMask = pSiteMgr->pDesiredParams->siteMgrMatchedBasicRateMask; } rate_DrvBitmapToNetStr(supportedRateMask, basicRateMask, ratesBuf, &len, &ofdmIndex); if (pSiteMgr->siteMgrOperationalMode != DOT11_G_MODE || pSiteMgr->pDesiredParams->siteMgrUseDraftNum == DRAFT_5_AND_EARLIER || ofdmIndex == len) { pDot11Rates->hdr[0] = DOT11_SUPPORTED_RATES_ELE_ID; pDot11Rates->hdr[1] = len; os_memoryCopy(pSiteMgr->hOs, (void *)pDot11Rates->rates, ratesBuf, pDot11Rates->hdr[1]); size += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); pBuf += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); } else { pDot11Rates->hdr[0] = DOT11_SUPPORTED_RATES_ELE_ID; pDot11Rates->hdr[1] = ofdmIndex; os_memoryCopy(pSiteMgr->hOs, (void *)pDot11Rates->rates, ratesBuf, pDot11Rates->hdr[1]); size += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); pBuf += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); extRates = TI_TRUE; } /* DS IE */ ((dot11_DS_PARAMS_t *) (pBuf))->hdr[0] = DOT11_DS_PARAMS_ELE_ID; ((dot11_DS_PARAMS_t *) (pBuf))->hdr[1] = DOT11_DS_PARAMS_ELE_LEN; ((dot11_DS_PARAMS_t *) (pBuf))->currChannel = pPrimarySite->channel; size += sizeof(dot11_eleHdr_t) + DOT11_DS_PARAMS_ELE_LEN; pBuf += sizeof(dot11_eleHdr_t) + DOT11_DS_PARAMS_ELE_LEN; /* IBSS IE */ ((dot11_IBSS_PARAMS_t *) (pBuf))->hdr[0] = DOT11_IBSS_PARAMS_ELE_ID; ((dot11_IBSS_PARAMS_t *) (pBuf))->hdr[1] = DOT11_IBSS_PARAMS_ELE_LEN; COPY_WLAN_WORD(&((dot11_IBSS_PARAMS_t *) (pBuf))->atimWindow, &pPrimarySite->atimWindow); size += sizeof(dot11_eleHdr_t) + DOT11_IBSS_PARAMS_ELE_LEN; pBuf += sizeof(dot11_eleHdr_t) + DOT11_IBSS_PARAMS_ELE_LEN; /* Country IE */ param.paramType = REGULATORY_DOMAIN_ENABLED_PARAM; regulatoryDomain_getParam(pSiteMgr->hRegulatoryDomain, ¶m); if (param.content.regulatoryDomainEnabled == TI_TRUE) { /* get country IE */ param.paramType = REGULATORY_DOMAIN_COUNTRY_PARAM; regulatoryDomain_getParam(pSiteMgr->hRegulatoryDomain, ¶m); pCountry = param.content.pCountry; /* Check if a country IE was found */ if (pCountry != NULL) { *pBuf = DOT11_COUNTRY_ELE_ID; pBuf++; size++; *pBuf = (TI_UINT8) (pCountry->len); pBuf++; size++; /* Note: The country structure is not byte-aligned so it is copied as follows to ensure that there are no gaps in the output structure (pBuf). */ os_memoryCopy(pSiteMgr->hOs, pBuf, &pCountry->countryIE.CountryString, DOT11_COUNTRY_STRING_LEN); pBuf += DOT11_COUNTRY_STRING_LEN; size += DOT11_COUNTRY_STRING_LEN; /* Loop on all tripletChannels. Each item has three fields ('i' counts rows and 'j' counts bytes). */ for (i = 0, j = 0; j < (pCountry->len - DOT11_COUNTRY_STRING_LEN); i++, j += 3) { *(pBuf + j) = pCountry->countryIE.tripletChannels[i]. firstChannelNumber; *(pBuf + j + 1) = pCountry->countryIE.tripletChannels[i]. maxTxPowerLevel; *(pBuf + j + 2) = pCountry->countryIE.tripletChannels[i]. numberOfChannels; } pBuf += (pCountry->len - DOT11_COUNTRY_STRING_LEN); size += (pCountry->len - DOT11_COUNTRY_STRING_LEN); } } /*ERP IE */ siteMgr_IsERP_Needed(pSiteMgr, &useProtection, &NonErpPresent, &barkerPreambleType); if (useProtection || NonErpPresent || barkerPreambleType) { pdot11Erp = (dot11_ERP_t *) pBuf; pdot11Erp->hdr[0] = DOT11_ERP_IE_ID; pdot11Erp->hdr[1] = 1; pdot11Erp->ctrl = 0; if (NonErpPresent) pdot11Erp->ctrl |= ERP_IE_NON_ERP_PRESENT_MASK; if (useProtection) pdot11Erp->ctrl |= ERP_IE_USE_PROTECTION_MASK; if (barkerPreambleType) pdot11Erp->ctrl |= ERP_IE_BARKER_PREAMBLE_MODE_MASK; size += pdot11Erp->hdr[1] + sizeof(dot11_eleHdr_t); pBuf += pdot11Erp->hdr[1] + sizeof(dot11_eleHdr_t); } /* Extended supported rates IE */ if (extRates) { pDot11Rates = (dot11_RATES_t *) pBuf; pDot11Rates->hdr[0] = DOT11_EXT_SUPPORTED_RATES_ELE_ID; pDot11Rates->hdr[1] = len - ofdmIndex; os_memoryCopy(pSiteMgr->hOs, (void *)pDot11Rates->rates, &ratesBuf[ofdmIndex], pDot11Rates->hdr[1]); size += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); pBuf += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); } /* no need to insert RSN information elements */ pTemplate->len = size; TRACE1(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "Probe response template len = %d\n", size); return TI_OK; }
/************************************************************************ * buildProbeReqTemplate * ************************************************************************ DESCRIPTION: This function build a probe request template to set to the HAL in the scan process. performs the following: - Build a template & set the template len, the template type is set in the site mgr INPUT: pSiteMgr - Handle to site manager pTemplate - Pointer to the template structure pSsid - Desired SSID OUTPUT: RETURN: TI_OK ************************************************************************/ TI_STATUS buildProbeReqTemplate(siteMgr_t * pSiteMgr, TSetTemplate * pTemplate, TSsid * pSsid, ERadioBand radioBand) { paramInfo_t param; char *pBuf; int i; probeReqTemplate_t *pBuffer = (probeReqTemplate_t *) pTemplate->ptr; TI_UINT32 size; dot11_RATES_t *pDot11Rates; TI_UINT32 len = 0, ofdmIndex = 0; TI_UINT32 suppRatesLen, extSuppRatesLen; TI_UINT8 ratesBuf[DOT11_MAX_SUPPORTED_RATES]; TI_UINT8 WSCOuiIe[DOT11_OUI_LEN] = { 0x00, 0x50, 0xf2, 0x04 }; TI_UINT32 supportedRateMask, basicRateMask; TI_UINT16 fc = DOT11_FC_PROBE_REQ; os_memoryZero(pSiteMgr->hOs, pBuffer, sizeof(probeReqTemplate_t)); /* * Header First */ /* Set destination address */ for (i = 0; i < MAC_ADDR_LEN; i++) pBuffer->hdr.DA[i] = 0xFF; /* Set BSSID address */ for (i = 0; i < MAC_ADDR_LEN; i++) pBuffer->hdr.BSSID[i] = 0xFF; /* Build Source address */ param.paramType = CTRL_DATA_MAC_ADDRESS; ctrlData_getParam(pSiteMgr->hCtrlData, ¶m); MAC_COPY(pBuffer->hdr.SA, param.content.ctrlDataDeviceMacAddress); COPY_WLAN_WORD(&pBuffer->hdr.fc, &fc); /* copy with endianess handling. */ size = sizeof(dot11_mgmtHeader_t); pBuf = (char *)&(pBuffer->infoElements); /* * Informataion elements */ /* SSID */ /* It looks like it never happens. Anyway decided to check */ if (pSsid->len > MAX_SSID_LEN) { TRACE2(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "buildProbeReqTemplate. pSsid->len=%d exceeds the limit %d\n", pSsid->len, MAX_SSID_LEN); handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION); return TI_NOK; } ((dot11_SSID_t *) (pBuf))->hdr[0] = DOT11_SSID_ELE_ID; ((dot11_SSID_t *) (pBuf))->hdr[1] = pSsid->len; os_memoryCopy(pSiteMgr->hOs, pBuf + sizeof(dot11_eleHdr_t), (void *)pSsid->str, pSsid->len); size += sizeof(dot11_eleHdr_t) + pSsid->len; pBuf += sizeof(dot11_eleHdr_t) + pSsid->len; /* Rates */ pDot11Rates = (dot11_RATES_t *) pBuf; /* * Supported rates in probe request will always use the default rates for BG or A bands, * regardless of the STA desired rates. */ if (radioBand == RADIO_BAND_2_4_GHZ) { /* Basic rates: 1,2,5.5,11 */ basicRateMask = rate_BasicToDrvBitmap((EBasicRateSet) (pSiteMgr->pDesiredParams-> siteMgrRegstryBasicRate [DOT11_G_MODE]), TI_FALSE); /* Extended: 6,9,12,18,24,36,48,54 */ supportedRateMask = rate_SupportedToDrvBitmap((ESupportedRateSet) (pSiteMgr->pDesiredParams-> siteMgrRegstrySuppRate [DOT11_G_MODE]), TI_FALSE); } else if (radioBand == RADIO_BAND_5_0_GHZ) { /* Basic rates: 6,12,24 */ basicRateMask = rate_BasicToDrvBitmap((EBasicRateSet) (pSiteMgr->pDesiredParams-> siteMgrRegstryBasicRate [DOT11_A_MODE]), TI_TRUE); /* Extended: 9,18,24,36,48,54 */ supportedRateMask = rate_SupportedToDrvBitmap((ESupportedRateSet) (pSiteMgr->pDesiredParams-> siteMgrRegstrySuppRate [DOT11_A_MODE]), TI_TRUE); } else { TRACE1(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "buildProbeReqTemplate, radioBand =%d ???\n", radioBand); /* Use default and pray for the best */ /* Basic rates: 1,2,5.5,11 */ basicRateMask = rate_BasicToDrvBitmap(BASIC_RATE_SET_1_2_5_5_11, TI_FALSE); /* Extended: 6,9,12,18,24,36,48,54 */ supportedRateMask = rate_SupportedToDrvBitmap(SUPPORTED_RATE_SET_UP_TO_54, TI_FALSE); } rate_DrvBitmapToNetStr(supportedRateMask, basicRateMask, ratesBuf, &len, &ofdmIndex); TRACE5(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "buildProbeReqTemplate, supportedRateMask=0x%x, basicRateMask=0x%x, len=%d, ofdmIndex=%d, radioBand =%d\n", supportedRateMask, basicRateMask, len, ofdmIndex, radioBand); /* It looks like it never happens. Anyway decided to check */ if (len > DOT11_MAX_SUPPORTED_RATES) { TRACE2(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "buildProbeReqTemplate. len=%d exceeds the limit %d\n", len, DOT11_MAX_SUPPORTED_RATES); handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION); return TI_NOK; } if (radioBand == RADIO_BAND_5_0_GHZ || pSiteMgr->pDesiredParams->siteMgrUseDraftNum == DRAFT_5_AND_EARLIER || ofdmIndex == len) { pDot11Rates->hdr[0] = DOT11_SUPPORTED_RATES_ELE_ID; pDot11Rates->hdr[1] = len; os_memoryCopy(pSiteMgr->hOs, (void *)pDot11Rates->rates, ratesBuf, pDot11Rates->hdr[1]); size += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); pBuf += pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); } else { pDot11Rates->hdr[0] = DOT11_SUPPORTED_RATES_ELE_ID; pDot11Rates->hdr[1] = ofdmIndex; os_memoryCopy(pSiteMgr->hOs, (void *)pDot11Rates->rates, ratesBuf, pDot11Rates->hdr[1]); suppRatesLen = pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); pDot11Rates = (dot11_RATES_t *) (pBuf + suppRatesLen); pDot11Rates->hdr[0] = DOT11_EXT_SUPPORTED_RATES_ELE_ID; pDot11Rates->hdr[1] = len - ofdmIndex; os_memoryCopy(pSiteMgr->hOs, (void *)pDot11Rates->rates, &ratesBuf[ofdmIndex], pDot11Rates->hdr[1]); extSuppRatesLen = pDot11Rates->hdr[1] + sizeof(dot11_eleHdr_t); size += suppRatesLen + extSuppRatesLen; pBuf += suppRatesLen + extSuppRatesLen; } /* add HT capabilities IE */ StaCap_GetHtCapabilitiesIe(pSiteMgr->hStaCap, (TI_UINT8 *) pBuf, &len); size += len; pBuf += len; /* WiFi Simple Config */ if (pSiteMgr->includeWSCinProbeReq && (pSiteMgr->siteMgrWSCCurrMode != TIWLN_SIMPLE_CONFIG_OFF)) { ((dot11_WSC_t *) pBuf)->hdr[0] = DOT11_WSC_PARAM_ELE_ID; ((dot11_WSC_t *) pBuf)->hdr[1] = pSiteMgr->uWscIeSize + DOT11_OUI_LEN; pBuf += sizeof(dot11_eleHdr_t); os_memoryCopy(pSiteMgr->hOs, pBuf, &WSCOuiIe, DOT11_OUI_LEN); os_memoryCopy(pSiteMgr->hOs, pBuf + DOT11_OUI_LEN, &pSiteMgr->siteMgrWSCProbeReqParams, pSiteMgr->uWscIeSize); size += sizeof(dot11_eleHdr_t) + pSiteMgr->uWscIeSize + DOT11_OUI_LEN; pBuf += sizeof(dot11_eleHdr_t) + pSiteMgr->uWscIeSize + DOT11_OUI_LEN; } pTemplate->len = size; return TI_OK; }
/** * \fn RxQueue_ReceivePacket() * \brief Main function of the RxQueue module. * Responsible on reorder of the packets from the RxXfer to the RX module. * Call from RxXfer in order to pass packet to uppers layers. * In order to save disordered packets the module use array of structures per TID * that each entry describe a packet. The array elements is sorted in the way that * the winStart array index represent always the winStart packet and the lowest SN. * Each increment index represent index at the BA window. Array index winEnd always * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner. * * SN range : 0 - 4095 * winStart range: 0 - 7 [0 - (RX_QUEUE_ARRAY_SIZE - 1)] * winSize : Determined by the BA session. We limit it to maximum 8 [RX_QUEUE_ARRAY_SIZE] * winEnd : = winStart + winSize - 1 * * The function functionality devided to parts: * Part 1: * In case the module received a packet with SN equal to the expected SN: * " pass it to upper layers * " increases winStart and array index winStart * " validate that all sequential queue packet are pass to the upper layers. * Part 2: * In case the module received a packet with SN between winStart to winEnd: * " Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize. * Part 3: * In case the module received a packet with SN higher than winEnd: * " Update winStart and WinEnd. * " Save it sorted at the array in index winEnd index. * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. * Part 4 + 5: * In case the module received a BA event packet: [Remember: This is an Rx module - We expect BAR and not BA (as well as ADDBE / DELBA] * " Update winStart and WinEnd * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. * " Free BA event packet via pass it to upper layers with error status. * * \note * \param hRxQueue - RxQueue handle. * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. * \param pBuffer - paket address of the packet [contains the RxIfDescriptor_t added by the FW]. * \return None * \sa */ void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer) { TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; TI_UINT8 *pFrame = RX_BUF_DATA((TI_UINT8 *)pBuffer); TI_STATUS tStatus = TI_OK; dot11_header_t *pHdr = (dot11_header_t *)pFrame; TI_UINT16 uQosControl; COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */ /* * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct. * If the packet is a QoS packet but the tag is not TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU - force TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU. * * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA */ if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) { /* Get AMSDU bit from frame */ if ( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS) { pRxParams->packet_class_tag = TAG_CLASS_AMSDU; } else { pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA; } } /* * packet doesn't need reorder ? */ if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) { RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer); return; } /* * pRxParams->type == TAG_CLASS_QOS_DATA ? */ if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU)) { TI_UINT8 uFrameTid; TI_UINT16 uFrameSn; TI_UINT16 uSequenceControl; TRxQueueTidDataBase *pTidDataBase; /* Get TID from frame */ uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS; /* TID illegal value ? */ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) { RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } /* Set the SA Tid pointer */ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); /* TID legal value */ /* Packet TID BA session not established ? */ if (pTidDataBase->aTidBaEstablished != TI_TRUE) { RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer); return; } /* If we got here - Packet TID BA established */ /* Get Sequence Number from frame */ COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */ uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4; /* * Note: * The FW never sends packet, in establish TID BA, with SN less than ESN !!! */ /* Part 1 - Received Frame Sequence Number is the expected one ? */ if (uFrameSn == pTidDataBase->aTidExpectedSn) { /* If the expected SN received and timer was running - Stop the timer. If we wait for more than one packet we should not stop the timer - This is why we are checking after the while loop, if we have more packets stored, and if we have, we start the timer again. */ if (pTidDataBase->uMissingPktTimeStamp != 0xffffffff) { StopMissingPktTimer(pRxQueue, uFrameTid); } /* Pass the packet */ RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer); /* Increase expected SN to the next */ pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */ /* Increase the ArrayInex to the next */ pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Pass all saved queue consecutive packets with SN higher than the expected one */ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */ /* Decrease the packets in queue */ pTidDataBase->uStoredPackets--; } /* aTidExpectedSn % 0xfff in order to tack care of wrap around */ pTidDataBase->aTidExpectedSn &= 0xfff; /* If there are still packets stored in the queue - start timer */ if (pTidDataBase->uStoredPackets) { StartMissingPktTimer(pRxQueue, uFrameTid); } return; } /* Frame Sequence Number is lower than Expected sequence number (ISN) ? */ if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) { /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); return; } /* Part 2 - Frame Sequence Number between winStart and winEnd ? */ if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) && /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */ ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)))) { TI_UINT16 uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */ uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Before storing packet in queue, make sure the place in the queue is vacant */ if (pTidDataBase->aPaketsQueue[uSaveIndex].pPacket == NULL) { /* Store the packet in the queue */ pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus; pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; pTidDataBase->aPaketsQueue[uSaveIndex].uFrameSn = uFrameSn; pTidDataBase->uStoredPackets++; /* Start Timer */ StartMissingPktTimer(pRxQueue, uFrameTid); } else { RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } return; } /* Part 3 - Frame Sequence Number higher than winEnd ? */ if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) ) { TI_UINT32 i; TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK; TI_UINT16 uSaveIndex; /* stop timer */ if (pTidDataBase->uMissingPktTimeStamp != 0xffffffff) { StopMissingPktTimer(pRxQueue, uFrameTid); } /* Increase the ArrayInex to the next */ pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Update the Expected SN since the current one is lost */ pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; /* Pass all saved queue packets with SN lower than the new win start */ for (i = 0; BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) && (i < RX_QUEUE_ARRAY_SIZE) && (i < pTidDataBase->aTidWinSize); i++) { if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->uStoredPackets--; } pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; } /* Calculate the new Expected SN */ if (i == pTidDataBase->aTidWinSize) { pTidDataBase->aTidExpectedSn = uNewWinStartSn; } else { /* In case the uWinStartDelta lower than aTidWinSize - check if there are packets stored in Array */ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { RxQueue_PassPacket ( pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket ); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; pTidDataBase->uStoredPackets--; } } if (pTidDataBase->aTidExpectedSn == uFrameSn) { /* pass the packet */ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; } else { uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */ uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Save the packet in the last entry of the queue */ pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus; pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; pTidDataBase->uStoredPackets++; } /* aTidExpectedSn % 0xfff in order to take care of wrap around */ pTidDataBase->aTidExpectedSn &= 0xfff; /* If there are still packets stored in the queue - start timer */ if (pTidDataBase->uStoredPackets) { StartMissingPktTimer(pRxQueue, uFrameTid); } return; } }
/** * \fn StaCap_GetHtCapabilitiesIe * \brief Get the desired STA HT capabilities IE. get the physical HT capabilities from TWD * and build HT capabilities IE. * * \note * \param hStaCap - The module object * \param pRequest - pointer to request buffer\n * \param len - size of returned IE\n * \return TI_OK on success or TI_NOK on failure * \sa */ TI_STATUS StaCap_GetHtCapabilitiesIe (TI_HANDLE hStaCap, TI_UINT8 *pRequest, TI_UINT32 *pLen) { TStaCap *pStaCap = (TStaCap *)hStaCap; TTwdHtCapabilities *pTwdHtCapabilities; TI_UINT8 *pDataBuf = pRequest; TStaCapHtCapabilities tHtCapabilities; TI_BOOL bWmeEnable; /* verify that WME flag enable */ qosMngr_GetWmeEnableFlag (pStaCap->hQosMngr, &bWmeEnable); if (bWmeEnable == TI_FALSE) { *pLen = 0; return TI_OK; } TWD_GetTwdHtCapabilities (pStaCap->hTWD, &pTwdHtCapabilities); /* verify that 802.11n flag enable */ if (pTwdHtCapabilities->b11nEnable == TI_FALSE) { *pLen = 0; return TI_OK; } /* * set TWD values to HT capabilities structure * * Note: all numbers after "<<" represent the position of the values in the filed according * to 11n SPEC. */ tHtCapabilities.uHtCapabilitiesInfo = ((pTwdHtCapabilities->uChannelWidth << 1) | (pTwdHtCapabilities->uRxSTBC << 8) | (pTwdHtCapabilities->uMaxAMSDU << 11)| (DSSS_CCK_MODE << 12)); tHtCapabilities.uHtCapabilitiesInfo |= ((((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_LDPC_CODING) ? 1 : 0) << 0) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_GREENFIELD_FRAME_FORMAT) ? 1 : 0) << 4) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_SHORT_GI_FOR_20MHZ_PACKETS) ? 1 : 0) << 5) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_SHORT_GI_FOR_40MHZ_PACKETS) ? 1 : 0) << 6) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_SUPPORT_FOR_STBC_IN_TRANSMISSION) ? 1 : 0) << 7) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_DELAYED_BLOCK_ACK) ? 1 : 0) << 10) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_DSSS_CCK_IN_40_MHZ) ? 1 : 0) << 12) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_LSIG_TXOP_PROTECTION) ? 1 : 0) << 15)); tHtCapabilities.uAMpduParam = ((pTwdHtCapabilities->uMaxAMPDU << 0) | (pTwdHtCapabilities->uAMPDUSpacing << 2)); /* copy RX supported MCS rates */ os_memoryCopy (pStaCap->hOs, tHtCapabilities.tSuppMcsSet.aRxMscBitmask, pTwdHtCapabilities->aRxMCS, RX_TX_MCS_BITMASK_SIZE); tHtCapabilities.tSuppMcsSet.uHighestSupportedDataRate = pTwdHtCapabilities->uRxMaxDataRate; /* check if supported MCS rates identical to TX and RX */ if( 0 == os_memoryCompare(pStaCap->hOs, pTwdHtCapabilities->aRxMCS, pTwdHtCapabilities->aTxMCS, RX_TX_MCS_BITMASK_SIZE)) { tHtCapabilities.tSuppMcsSet.uTxRxSetting = ((TX_MCS_SET_YES << 0) | /* set supported TX MCS rate */ (TX_RX_NOT_EQUAL_NO << 1)); /* set TX&RX MCS rate are equal */ } /* in case supported MCS rates TX different from the RX */ else { TI_UINT32 i; /* check if there are TX MCS rates supported */ for (i = 0; i <= (RX_TX_MCS_BITMASK_SIZE - 1); ++i) { if (pTwdHtCapabilities->aTxMCS[i] != 0) { break; } } /* TX MCS supported */ if(i <= (RX_TX_MCS_BITMASK_SIZE -1)) { tHtCapabilities.tSuppMcsSet.uTxRxSetting = ((TX_MCS_SET_YES << 0) | /* set supported TX MCS rates */ (TX_RX_NOT_EQUAL_YES << 1)); /* set TX&RX MCS rates different */ } /* TX MCS not supported */ else { tHtCapabilities.tSuppMcsSet.uTxRxSetting = (TX_MCS_SET_NO << 0); /* set no supported TX MCS rates */ } } tHtCapabilities.uExteCapabilities = (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_PCO) ? 1 : 0) << 0); if (tHtCapabilities.uExteCapabilities != 0) { tHtCapabilities.uExteCapabilities |= (pTwdHtCapabilities->uPCOTransTime << 1); } tHtCapabilities.uExteCapabilities |= ((pTwdHtCapabilities->uMCSFeedback << 8) | (HTC_SUPPORT_NO << 10)); tHtCapabilities.uTxBfCapabilities = ((IMPLICIT_TXBF_REC_CAPABLE << 0) | (TRANSMIT_STAGGERED_SOUNDING_CAPABLE << 2)); tHtCapabilities.uAselCapabilities = 0x0; /* build IE */ *pDataBuf = HT_CAPABILITIES_IE_ID; *(pDataBuf + 1) = DOT11_HT_CAPABILITIES_ELE_LEN; COPY_WLAN_WORD(pDataBuf + 2, &(tHtCapabilities.uHtCapabilitiesInfo)); *(pDataBuf + 4) = tHtCapabilities.uAMpduParam; os_memoryCopy (pStaCap->hOs, pDataBuf + 5, tHtCapabilities.tSuppMcsSet.aRxMscBitmask, RX_TX_MCS_BITMASK_SIZE); COPY_WLAN_WORD(pDataBuf + 15, &(tHtCapabilities.tSuppMcsSet.uHighestSupportedDataRate)); *(pDataBuf + 17) = tHtCapabilities.tSuppMcsSet.uTxRxSetting; /* clear the reserved bytes */ os_memoryZero (pStaCap->hOs, (pDataBuf + 18), 3); COPY_WLAN_WORD(pDataBuf + 21, &(tHtCapabilities.uExteCapabilities)); COPY_WLAN_LONG(pDataBuf + 23, &(tHtCapabilities.uTxBfCapabilities)); *(pDataBuf + 27) = tHtCapabilities.uAselCapabilities; *pLen = DOT11_HT_CAPABILITIES_ELE_LEN + sizeof(dot11_eleHdr_t); return TI_OK; }
/*********************************************************************** * txCtrlServ_buildWlanHeader *********************************************************************** DESCRIPTION: Build WLAN header from Ethernet header. INPUT: hTxCtrl - Tx Ctrl module handle (the txServ uses the txCtrl object!!). pFrame - A pointer to a buffer where the frame should be stored pLength - A pointer to a placeholder for the frame length ************************************************************************/ TI_STATUS txCtrlServ_buildWlanHeader(TI_HANDLE hTxCtrl, TI_UINT8* pFrame, TI_UINT32* pLength) { txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl; TI_STATUS status; TMacAddr daBssid; TMacAddr saBssid; EQosProtocol qosProt; ScanBssType_e currBssType; TMacAddr currBssId; TI_UINT32 headerLength; TI_UINT16 headerFlags; TI_BOOL currentPrivacyInvokedMode; TI_UINT8 encryptionFieldSize; TTxCtrlBlk tPktCtrlBlk; dot11_header_t *pDot11Header = (dot11_header_t*)(tPktCtrlBlk.aPktHdr); Wlan_LlcHeader_T *pWlanSnapHeader; /* * If QoS is used, add two bytes padding before the header for 4-bytes alignment. * Note that the header length doesn't include it, so the txCtrl detects the pad existence * by checking if the header-length is a multiple of 4. */ qosMngr_getParamsActiveProtocol(pTxCtrl->hQosMngr, &qosProt); if (qosProt == QOS_WME) { headerLength = WLAN_QOS_HDR_LEN; headerFlags = DOT11_FC_DATA_QOS | DOT11_FC_TO_DS; pDot11Header->qosControl = 0; } else { headerLength = WLAN_HDR_LEN; headerFlags = DOT11_FC_DATA | DOT11_FC_TO_DS; } /* * Handle encryption if needed (decision was done at RSN and is provided by TxCtrl): * - Set WEP bit in header. * - Add padding for FW security overhead: 4 bytes for TKIP, 8 for AES. */ txCtrlParams_getCurrentEncryptionInfo (hTxCtrl, ¤tPrivacyInvokedMode, &encryptionFieldSize); if (currentPrivacyInvokedMode) { headerFlags |= DOT11_FC_WEP; headerLength += encryptionFieldSize; } COPY_WLAN_WORD (&pDot11Header->fc, &headerFlags); /* copy with endianess handling. */ /* Get the Destination MAC address */ status = ctrlData_getParamBssid (pTxCtrl->hCtrlData, CTRL_DATA_CURRENT_BSSID_PARAM, daBssid); if (status != TI_OK) { return TI_NOK; } /* Get the Source MAC address */ status = ctrlData_getParamBssid (pTxCtrl->hCtrlData, CTRL_DATA_MAC_ADDRESS, saBssid); if (status != TI_OK) { return TI_NOK; } /* receive BssId and Bss Type from control module */ ctrlData_getCurrBssTypeAndCurrBssId (pTxCtrl->hCtrlData, &currBssId, &currBssType); if (currBssType != BSS_INFRASTRUCTURE) { return TI_NOK; } /* copy BSSID */ MAC_COPY (pDot11Header->address1, currBssId); /* copy source mac address */ MAC_COPY (pDot11Header->address2, saBssid); /* copy destination mac address*/ MAC_COPY (pDot11Header->address3, daBssid); /* Set the SNAP header pointer right after the other header parts handled above. */ pWlanSnapHeader = (Wlan_LlcHeader_T *)&(tPktCtrlBlk.aPktHdr[headerLength]); pWlanSnapHeader->DSAP = SNAP_CHANNEL_ID; pWlanSnapHeader->SSAP = SNAP_CHANNEL_ID; pWlanSnapHeader->Control = LLC_CONTROL_UNNUMBERED_INFORMATION; /* add RFC1042. */ pWlanSnapHeader->OUI[0] = SNAP_OUI_RFC1042_BYTE0; pWlanSnapHeader->OUI[1] = SNAP_OUI_RFC1042_BYTE1; pWlanSnapHeader->OUI[2] = SNAP_OUI_RFC1042_BYTE2; /* set ETH type to IP */ pWlanSnapHeader->Type = HTOWLANS(ETHERTYPE_IP); /* Add the SNAP length to the total header length. */ headerLength += sizeof(Wlan_LlcHeader_T); /* copy WLAN header */ os_memoryCopy (pTxCtrl->hOs, pFrame, tPktCtrlBlk.aPktHdr, headerLength); *pLength = headerLength; return TI_OK; }
/** * \fn RxQueue_ReceivePacket() * \brief Main function of the RxQueue module. * Responsible on reorder of the packets from the RxXfer to the RX module. * Call from RxXfer in order to pass packet to uppers layers. * In order to save disordered packets the module use array of structures per TID * that each entry describe a packet. The array elements is sorted in the way that * the winStart array index represent always the winStar packet and the lowest SN. * Each increment index represent index at the BA window. Array index winEnd always * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner. * The function functionality devided to parts: * Part 1: * in case the modulo receive packet with SN equal to winStart: * " pass it to upper layers * " increases winStart and array index winStart * " validate that all sequential queue packet are pass to the upper layers. * Part 2: * in case the modulo receive packet that SN between winStart to winEnd: * " Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize. * Part 3: * in case the modulo receive packet that SN higher then winEnd: * " Update winStart and WinEnd. * " Save it sorted at the array in index winEnd index. * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. * Part 4 + 5: * in case the modulo receive BA event packet: * " Update winStart and WinEnd * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. * " Free BA event packet via pass it to upper layers with error status. * * \note * \param hRxQueue - RxQueue handle. * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. * \param pBuffer - paket address of the packet * \return None * \sa */ void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer) { TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; TI_UINT8 *pFrame = RX_BUF_DATA((TI_UINT8 *)pBuffer); TI_STATUS tStatus = TI_OK; dot11_header_t *pHdr = (dot11_header_t *)pFrame; TI_UINT16 uQosControl; COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */ /* * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA */ if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) { TRACE1(pRxQueue->hReport, REPORT_SEVERITY_WARNING, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag); /* Get AMSDU bit from frame */ if( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS) { pRxParams->packet_class_tag = TAG_CLASS_AMSDU; } else { pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA; } } /* * packet doesn't need reorder ? */ if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: pass packet without reorder.\n"); RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); return; } /* * pRxParams->type == TAG_CLASS_QOS_DATA ? */ if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU)) { TI_UINT8 uFrameTid; TI_UINT16 uFrameSn; TI_UINT16 uSequenceControl; TRxQueueTidDataBase *pTidDataBase; /* Get TID from frame */ uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS; /* TID illegal value ? */ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) { TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid); RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } /*set the SA Tid pointer */ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); /* TID legal value */ /* packet TID BA not established ? */ if (pTidDataBase->aTidBaEstablished != TI_TRUE) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n"); RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); return; } /* packet TID BA established */ /* Get Sequence Number from frame */ COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */ uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4; /* * note: * the FW never send paket, in establish TID BA, that the SN less then ESN !!! */ /* frame Sequence Number is the expected one ? */ if (uFrameSn == pTidDataBase->aTidExpectedSn) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n"); /* pass the packet */ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; /* increase the ArrayInex to the next */ pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* pass all saved queue packets with SN higher then the expected one */ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; } return; } /* frame Sequence Number is lower then Expected sequence number (ISN) ? */ if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) { /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */ TRACE2(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame SN=%u is less than ESN=%u\n",uFrameSn,pTidDataBase->aTidExpectedSn); RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } /* frame Sequence Number between winStart and winEnd ? */ if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) && /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */ ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)))) { TI_UINT16 uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); /* uSaveInex % RX_QUEUE_ARRAY_SIZE */ uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; if (pTidDataBase->aPaketsQueue[uSaveInex].pPacket == NULL) { /* save the packet in the queue */ pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus; pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer; pTidDataBase->aPaketsQueue[uSaveInex].uFrameSn = uFrameSn; } else { TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has allready saved. uFrameSn = %d\n",uFrameSn); RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } return; } /* frame Sequence Number higher then winEnd ? */ if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) ) { TI_UINT32 i; TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK; TI_UINT16 uSaveInex; TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher then winEnd.\n"); /* increase the ArrayInex to the next */ pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* update the Expected SN since the current one is lost */ pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; /* pass all saved queue packets with SN lower then the new win start */ for (i = 0; BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) && (i < RX_QUEUE_ARRAY_SIZE) && (i < pTidDataBase->aTidWinSize); i++) { if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; } pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; } /* Calculate the new Expected SN */ if (i == pTidDataBase->aTidWinSize) { pTidDataBase->aTidExpectedSn = uNewWinStartSn; } else { /* Incase the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; } } if(pTidDataBase->aTidExpectedSn == uFrameSn) { /* pass the packet */ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; } else { uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); /* uSaveInex % RX_QUEUE_ARRAY_SIZE */ uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* save the packet in the last entry of the queue */ pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus; pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer; pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer; } return; } }
TI_STATUS admCtrlWpa_getInfoElement(admCtrl_t *pAdmCtrl, TI_UINT8 *pIe, TI_UINT32 *pLength) { wpaIePacket_t localWpaPkt; wpaIePacket_t *pWpaIePacket; TI_UINT8 length; TI_UINT16 tempInt; TI_STATUS status; TIWLN_SIMPLE_CONFIG_MODE wscMode; /* Get Simple-Config state */ status = siteMgr_getParamWSC(pAdmCtrl->pRsn->hSiteMgr, &wscMode); /* SITE_MGR_SIMPLE_CONFIG_MODE */ if (pIe==NULL) { *pLength = 0; return TI_NOK; } if ((wscMode != TIWLN_SIMPLE_CONFIG_OFF) && (pAdmCtrl->broadcastSuite == TWD_CIPHER_NONE) && (pAdmCtrl->unicastSuite == TWD_CIPHER_NONE)) { *pLength = 0; return TI_NOK; } /* Check validity of WPA IE */ if (!broadcastCipherSuiteValidity[pAdmCtrl->networkMode][pAdmCtrl->broadcastSuite]) { /* check Group suite validity */ *pLength = 0; return TI_NOK; } if (pAdmCtrl->unicastSuite == TWD_CIPHER_WEP) { /* check pairwise suite validity */ *pLength = 0; return TI_NOK; } /* Build Wpa IE */ pWpaIePacket = &localWpaPkt; os_memoryZero(pAdmCtrl->hOs, pWpaIePacket, sizeof(wpaIePacket_t)); pWpaIePacket->elementid= WPA_IE_ID; os_memoryCopy(pAdmCtrl->hOs, (void *)pWpaIePacket->oui, wpaIeOuiIe, 3); pWpaIePacket->ouiType = WPA_OUI_DEF_TYPE; tempInt = WPA_OUI_MAX_VERSION; COPY_WLAN_WORD(&pWpaIePacket->version, &tempInt); length = sizeof(wpaIePacket_t)-2; /* check defaults */ if (pAdmCtrl->replayCnt==1) { length -= 2; /* 2: capabilities + 4: keyMng suite, 2: keyMng count*/ #if 0 /* The following was removed since there are APs which do no accept the default WPA IE */ if (pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA) { length -= 6; /* 2: capabilities + 4: keyMng suite, 2: keyMng count*/ if (pAdmCtrl->unicastSuite == TWD_CIPHER_TKIP) { length -= 6; /* 4: unicast suite, 2: unicast count */ if (pAdmCtrl->broadcastSuite == TWD_CIPHER_TKIP) { length -= 4; /* broadcast suite */ } } } #endif }
/** * \fn RxQueue_ReceivePacket() * \brief Main function of the RxQueue module. * Responsible on reorder of the packets from the RxXfer to the RX module. * Call from RxXfer in order to pass packet to uppers layers. * In order to save disordered packets the module use array of structures per TID * that each entry describe a packet. The array elements is sorted in the way that * the winStart array index represent always the winStart packet and the lowest SN. * Each increment index represent index at the BA window. Array index winEnd always * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner. * * SN range : 0 - 4095 * winStart range: 0 - 7 [0 - (RX_QUEUE_ARRAY_SIZE - 1)] * winSize : Determined by the BA session. We limit it to maximum 8 [RX_QUEUE_ARRAY_SIZE] * winEnd : = winStart + winSize - 1 * * The function functionality devided to parts: * Part 1: * In case the module received a packet with SN equal to the expected SN: * " pass it to upper layers * " increases winStart and array index winStart * " validate that all sequential queue packet are pass to the upper layers. * Part 2: * In case the module received a packet with SN between winStart to winEnd: * " Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize. * Part 3: * In case the module received a packet with SN higher than winEnd: * " Update winStart and WinEnd. * " Save it sorted at the array in index winEnd index. * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. * Part 4 + 5: * In case the module received a BA event packet: [Remember: This is an Rx module - We expect BAR and not BA (as well as ADDBE / DELBA] * " Update winStart and WinEnd * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. * " Free BA event packet via pass it to upper layers with error status. * * \note * \param hRxQueue - RxQueue handle. * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. * \param pBuffer - paket address of the packet [contains the RxIfDescriptor_t added by the FW]. * \return None * \sa */ void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer) { TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; TI_UINT8 *pFrame = RX_BUF_DATA((TI_UINT8 *)pBuffer); TI_STATUS tStatus = TI_OK; dot11_header_t *pHdr = (dot11_header_t *)pFrame; TI_UINT16 uQosControl; COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */ TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: packet_class_tag = 0x%x(%d)",pRxParams->packet_class_tag,pRxParams->packet_class_tag); /* * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct. * If the packet is a QoS packet but the tag is not TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU - force TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU. * * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA */ if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) { TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag); /* Get AMSDU bit from frame */ if ( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS) { pRxParams->packet_class_tag = TAG_CLASS_AMSDU; } else { pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA; } } /* * packet doesn't need reorder ? */ if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: pass packet without reorder.\n"); RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer); return; } /* * pRxParams->type == TAG_CLASS_QOS_DATA ? */ if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU)) { TI_UINT8 uFrameTid; TI_UINT16 uFrameSn; TI_UINT16 uSequenceControl; TRxQueueTidDataBase *pTidDataBase; /* Get TID from frame */ uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS; TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: QoS Packet received"); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uFrameTid = 0x%x(%d)",uFrameTid,uFrameTid); /* TID illegal value ? */ if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) { TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid); RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } /* Set the SA Tid pointer */ pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); /* TID legal value */ /* Packet TID BA session not established ? */ if (pTidDataBase->aTidBaEstablished != TI_TRUE) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n"); RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer); return; } /* If we got here - Packet TID BA established */ /* Get Sequence Number from frame */ COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */ uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4; TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uFrameSn = 0x%x(%d)", uFrameSn, uFrameSn); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn, pTidDataBase->aTidExpectedSn); /* * Note: * The FW never sends packet, in establish TID BA, with SN less than ESN !!! */ /* Part 1 - Received Frame Sequence Number is the expected one ? */ if (uFrameSn == pTidDataBase->aTidExpectedSn) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n"); /* If the expected SN received and timer was running - Stop the timer. If we wait for more than one packet we should not stop the timer - This is why we are checking after the while loop, if we have more packets stored, and if we have, we start the timer again. */ if (pRxQueue->tPacketTimeout.bPacketMiss) { tmr_StopTimer (pRxQueue->hTimer); pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; } /* Pass the packet */ RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer); /* Increase expected SN to the next */ pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */ /* Increase the ArrayInex to the next */ pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Pass all saved queue consecutive packets with SN higher than the expected one */ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Pass all saved queue packets with SN higher than the expected one that was just received."); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)", pTidDataBase->aTidExpectedSn, pTidDataBase->aTidExpectedSn); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aWinStartArrayInex = 0x%x(%d)", pTidDataBase->aWinStartArrayInex, pTidDataBase->aWinStartArrayInex); RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */ /* Decrease the packets in queue */ pRxQueue->tPacketTimeout.aPacketsStored--; } /* aTidExpectedSn % 0xfff in order to tack care of wrap around */ pTidDataBase->aTidExpectedSn &= 0xfff; /* If there are still packets stored in the queue - start timer */ if (pRxQueue->tPacketTimeout.aPacketsStored) { tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; } return; } /* Frame Sequence Number is lower than Expected sequence number (ISN) ? */ if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) { /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */ TRACE2(pRxQueue->hReport, REPORT_SEVERITY_WARNING, "RxQueue_ReceivePacket: frame Sequence Number (%d) is lower than expected sequence number (%d).\n", uFrameSn, pTidDataBase->aTidExpectedSn); RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); return; } /* Part 2 - Frame Sequence Number between winStart and winEnd ? */ if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) && /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */ ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)))) { TI_UINT16 uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */ uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number between winStart and winEnd.\n"); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uSaveIndex = 0x%x(%d)",uSaveIndex,uSaveIndex); /* Before storing packet in queue, make sure the place in the queue is vacant */ if (pTidDataBase->aPaketsQueue[uSaveIndex].pPacket == NULL) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Enter packet to Reorder Queue"); /* Store the packet in the queue */ pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus; pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; pTidDataBase->aPaketsQueue[uSaveIndex].uFrameSn = uFrameSn; pRxQueue->tPacketTimeout.aPacketsStored++; /* Start Timer [only if timer is not already started - according to bPacketMiss] */ if (pRxQueue->tPacketTimeout.bPacketMiss == TI_FALSE) { tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; } } else { TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has already saved. uFrameSn = %d\n", uFrameSn); RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); return; } return; } /* Part 3 - Frame Sequence Number higher than winEnd ? */ if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) ) { TI_UINT32 i; TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK; TI_UINT16 uSaveIndex; TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher than winEnd.\n"); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uNewWinStartSn = 0x%x(%d) STOP TIMER",uNewWinStartSn,uNewWinStartSn); /* If timer is on - stop it */ if (pRxQueue->tPacketTimeout.bPacketMiss) { tmr_StopTimer (pRxQueue->hTimer); pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; } /* Increase the ArrayInex to the next */ pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Update the Expected SN since the current one is lost */ pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; /* Pass all saved queue packets with SN lower than the new win start */ for (i = 0; BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) && (i < RX_QUEUE_ARRAY_SIZE) && (i < pTidDataBase->aTidWinSize); i++) { TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aWinStartArrayInex = 0x%x(%d)",pTidDataBase->aWinStartArrayInex,pTidDataBase->aWinStartArrayInex); if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send Packet to Upper layer"); RxQueue_PassPacket (pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pRxQueue->tPacketTimeout.aPacketsStored--; } pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; } TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: i = %d",i); /* Calculate the new Expected SN */ if (i == pTidDataBase->aTidWinSize) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Set aTidExpectedSn to uNewWinStartSn"); pTidDataBase->aTidExpectedSn = uNewWinStartSn; } else { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send all saved packets"); /* In case the uWinStartDelta lower than aTidWinSize - check if there are packets stored in Array */ while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send packet with SN = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); RxQueue_PassPacket ( pRxQueue, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket ); pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; pTidDataBase->aWinStartArrayInex++; /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xFFF; pRxQueue->tPacketTimeout.aPacketsStored--; } } TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); if (pTidDataBase->aTidExpectedSn == uFrameSn) { TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send current packet to uper layer"); /* pass the packet */ RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); pTidDataBase->aTidExpectedSn++; pTidDataBase->aTidExpectedSn &= 0xfff; } else { uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Enter current packet to Reorder Queue"); TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uSaveIndex = 0x%x(%d)", uSaveIndex, uSaveIndex); /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */ uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; /* Save the packet in the last entry of the queue */ pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus; pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; pRxQueue->tPacketTimeout.aPacketsStored++; } /* aTidExpectedSn % 0xfff in order to take care of wrap around */ pTidDataBase->aTidExpectedSn &= 0xfff; /* If there are still packets stored in the queue - start timer */ if (pRxQueue->tPacketTimeout.aPacketsStored) { tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; } return; } }