NDIS_STATUS Sta11AllocateStation( __in NDIS_HANDLE MiniportAdapterHandle, __out PSTATION* ppStation ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PSTATION pStation = NULL; do { MP_ALLOCATE_MEMORY(MiniportAdapterHandle, ppStation, sizeof(STATION), STA11_MEMORY_TAG); if (*ppStation == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate memory for Station\n")); ndisStatus = NDIS_STATUS_RESOURCES; break; } pStation = *ppStation; NdisZeroMemory(pStation, sizeof(STATION)); pStation->MiniportAdapterHandle = MiniportAdapterHandle; } while (FALSE); return ndisStatus; }
/** * Initializes the DataRecorder for storing data * * \param MaxLength The maximum number of elements to store at a time. Adding * more than this number is possible, it only causes wraparound, overwriting * earlier data * \return NDIS_STATUS * \sa Terminate(), Insert() */ NDIS_STATUS InitializeDataRecorder( NDIS_HANDLE MiniportAdapterHandle, PMP_DATA_RECORDER_OBJ Recorder, ULONG MaxLength ) { ULONG count; Recorder->RecordList = NULL; Recorder->MaxLength = MaxLength; Recorder->CurrentIndex = 0; MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &Recorder->RecordList, sizeof(MP_DATA_RECORD_ELEMENT) * MaxLength, MP_MEMORY_TAG ); if (Recorder->RecordList == NULL) { MpTrace (COMP_INIT_PNP, DBG_SERIOUS, ("Unable to allocate memory for data recorder\n")); return NDIS_STATUS_RESOURCES; } for (count = 0; count < MaxLength; count++) { // Initialize as empty Recorder->RecordList[count].DataType = MP_NO_DATA; } return NDIS_STATUS_SUCCESS; }
NDIS_STATUS Sta11AllocatePort( _In_ NDIS_HANDLE MiniportAdapterHandle, _In_ PADAPTER Adapter, _In_ PMP_PORT Port ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PMP_EXTSTA_PORT newExtSTAPort = NULL; UNREFERENCED_PARAMETER(Adapter); do { // Allocate the helper port specific structure MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &newExtSTAPort, sizeof(MP_EXTSTA_PORT), EXTSTA_MEMORY_TAG); if (newExtSTAPort == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate %d bytes for extsta port\n", sizeof(MP_EXTSTA_PORT))); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Clear everything NdisZeroMemory(newExtSTAPort, sizeof(MP_EXTSTA_PORT)); // Save pointer to the parent port & vice versa Port->ChildPort = newExtSTAPort; newExtSTAPort->ParentPort = Port; // Set op mode and op state value Port->CurrentOpMode = DOT11_OPERATION_MODE_EXTENSIBLE_STATION; Port->CurrentOpState = INIT_STATE; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { if (newExtSTAPort != NULL) { Sta11FreePort(Port); } } return ndisStatus; }
NDIS_STATUS Sta11LoadRegistryInformation( _In_ NDIS_HANDLE MiniportAdapterHandle, _In_opt_ NDIS_HANDLE ConfigurationHandle, _Out_ PVOID* RegistryInformation ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PSTA_REG_INFO staRegInfo = NULL; *RegistryInformation = NULL; do { // // Allocate memory for the registry info // MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &staRegInfo, sizeof(STA_REG_INFO), EXTSTA_MEMORY_TAG); if (staRegInfo == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate %d bytes for STA_REG_INFO\n", sizeof(STA_REG_INFO))); ndisStatus = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(staRegInfo, sizeof(STA_REG_INFO)); // // read registry values // MpReadRegistry((PVOID)staRegInfo, ConfigurationHandle, STARegTable, STA_NUM_REG_PARAMS); *RegistryInformation = staRegInfo; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { // Free the buffer Sta11FreeRegistryInformation(staRegInfo); } return ndisStatus; }
NDIS_STATUS StaSendDisassociation( __in PSTATION pStation, __in PSTA_BSS_ENTRY pAPEntry, __in USHORT ReasonCode ) { PDOT11_MGMT_HEADER pMgmtMacHeader = NULL; PDOT11_DISASSOC_FRAME pDot11DisassocFrame = NULL; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pPacketBuffer = NULL; USHORT PacketSize; MpEntry; PacketSize = sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_DISASSOC_FRAME); MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, &pPacketBuffer, PacketSize, STA11_MEMORY_TAG); if (pPacketBuffer == NULL) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to allocate disassociation request packet\n")); return NDIS_STATUS_RESOURCES; } NdisZeroMemory(pPacketBuffer, PacketSize); pMgmtMacHeader = (PDOT11_MGMT_HEADER)pPacketBuffer; // // Fill the MAC header // pMgmtMacHeader->FrameControl.Version = 0x0; pMgmtMacHeader->FrameControl.Type = DOT11_FRAME_TYPE_MANAGEMENT; pMgmtMacHeader->FrameControl.Subtype = DOT11_MGMT_SUBTYPE_DISASSOCIATION; pMgmtMacHeader->FrameControl.ToDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.FromDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.MoreFrag = 0x0; pMgmtMacHeader->FrameControl.Retry = 0x0; pMgmtMacHeader->FrameControl.PwrMgt = 0x0; pMgmtMacHeader->FrameControl.MoreData = 0x0; pMgmtMacHeader->FrameControl.WEP = 0x0; // no WEP pMgmtMacHeader->FrameControl.Order = 0x0; // no order memcpy(pMgmtMacHeader->DA, pAPEntry->MacAddress, DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->SA, Hw11GetMACAddress(pStation->pNic), DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->BSSID, pAPEntry->Dot11BSSID, DOT11_ADDRESS_SIZE ); pDot11DisassocFrame = (PDOT11_DISASSOC_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER)); pDot11DisassocFrame->usReasonCode = ReasonCode; // // Send the disassociation request packet ndisStatus = Hw11SendMgmtPacket( pStation->pNic, pAPEntry, pPacketBuffer, PacketSize ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to send disassociation packet\n")); } // Send Mgmt Packet cannot pend MPVERIFY(ndisStatus != NDIS_STATUS_PENDING); if (pPacketBuffer) { MP_FREE_MEMORY(pPacketBuffer); } return ndisStatus; }
VOID StaReceiveAssociationResponse( __in PSTATION pStation, __in PNIC_RX_FRAGMENT pNicFragment, __in ULONG TotalLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pPacketBuffer; PDOT11_MGMT_HEADER pMgmtHeader; PDOT11_ASSOC_RESPONSE_FRAME pDot11AssocFrame; USHORT StatusCode; USHORT AID = 0; PSTA_BSS_ENTRY pAPEntry = pStation->ConnectContext.ActiveAP; BOOLEAN bTimerCancelled, bSetTxDataRate = FALSE; DOT11_RATE_SET rateSet; pPacketBuffer = Hw11GetFragmentDataStart(pNicFragment); // // Ref to make sure reset/halt does not leave while we are still working // STA_INCREMENT_REF(pStation->ConnectContext.AsyncFuncCount); NdisDprAcquireSpinLock(&(pStation->ConnectContext.Lock)); if (pStation->ConnectContext.AssociateState == ASSOC_STATE_WAITING_FOR_ASSOCIATE) { if (pStation->ConnectContext.ConnectState < CONN_STATE_READY_TO_CONNECT) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Reset/Disconnect before association completed\n")); // // Reset/disconnect, etc. We dont process this associate packet. Eventually, timeout // will happen and cleanup // NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); return; } do { if (TotalLength < (sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_ASSOC_RESPONSE_FRAME))) { ndisStatus = NDIS_STATUS_NOT_ACCEPTED; MpTrace(COMP_ASSOC, DBG_LOUD, ("Association response packet too short\n")); break; } pMgmtHeader = (PDOT11_MGMT_HEADER)pPacketBuffer; // // Check that is a packet from the AP we are interested in // if (!MP_COMPARE_MAC_ADDRESS(pMgmtHeader->SA, pAPEntry->MacAddress) || !MP_COMPARE_MAC_ADDRESS(pMgmtHeader->BSSID, pAPEntry->Dot11BSSID) || !MP_COMPARE_MAC_ADDRESS(pMgmtHeader->DA, Hw11GetMACAddress(pStation->pNic))) { ndisStatus = NDIS_STATUS_NOT_ACCEPTED; MpTrace(COMP_ASSOC, DBG_LOUD, ("Association response packet not for me\n")); break; } } while (FALSE); if (ndisStatus != NDIS_STATUS_NOT_ACCEPTED) { // // This was a valid response to our association request // Complete the association with appropriate status // pDot11AssocFrame = (PDOT11_ASSOC_RESPONSE_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER)); // // Get association status code from the packet // StatusCode = pDot11AssocFrame->usStatusCode; if (StatusCode == DOT11_FRAME_STATUS_SUCCESSFUL) { // // Association attempt succeeded // ndisStatus = NDIS_STATUS_SUCCESS; MpTrace(COMP_ASSOC, DBG_NORMAL, ("Association response status SUCCESS\n")); // // Validate AID // AID = pDot11AssocFrame->usAID; if ((AID & 0xc000) != 0xc000) { // Invalid AID. pStation->Config.ValidAID = FALSE; // Connecting to a non-conformant AP. Continue with association instead of bailing out. MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Association response contains invalid AID %d\n", AID)); } else { pStation->Config.ValidAID = TRUE; } AID &= ~(0xc000); if (AID > 2007) { // AID too big ndisStatus = NDIS_STATUS_FAILURE; MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Association response contains invalid AID %d\n", AID)); } if (ndisStatus == NDIS_STATUS_SUCCESS) { // // Get data rate // ndisStatus = StaGetRateSetFromInfoEle( Add2Ptr(pDot11AssocFrame, sizeof(DOT11_ASSOC_RESPONSE_FRAME)), TotalLength - sizeof(DOT11_MGMT_HEADER) - sizeof(DOT11_ASSOC_RESPONSE_FRAME), FALSE, &rateSet); } if (ndisStatus == NDIS_STATUS_SUCCESS) { // Association has succeeded MpTrace(COMP_ASSOC, DBG_NORMAL, ("Association ID %d\n", AID)); pStation->ConnectContext.AssociateState = ASSOC_STATE_RECEIVED_ASSOCIATE; pStation->Config.AID = AID; // // Clear non-static WEP keys. // Hw11DeleteNonPersistentKey(pStation->pNic); bSetTxDataRate = TRUE; // // Set active PhyId // pStation->Config.ActivePhyId = pAPEntry->PhyId; // // Set multicast cipher algorithm if the exact algorithm was not selected. // if (pStation->Config.MulticastCipherAlgorithmCount > 1) { Hw11SetEncryption(pStation->pNic, FALSE, pStation->Config.MulticastCipherAlgorithm); } } else { pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION; StatusCode = DOT11_FRAME_STATUS_FAILURE; // Unspecified failure } } else { // The association attempt failed MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Association failed by the access point with status %d\n", StatusCode)); pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION; } // // Copy the association response buffer into the AP Entry for completion indication // NdisDprAcquireSpinLock(&(pAPEntry->Lock)); pAPEntry->AssocResponseLength = (USHORT)TotalLength; MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, &(pAPEntry->pAssocResponse), TotalLength, STA11_MEMORY_TAG); if (pAPEntry->pAssocResponse == NULL) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to save association request packet\n")); // // We still maintain the association // pAPEntry->AssocResponseLength = 0; } else { // // Copy the association response into the packet // NdisMoveMemory(pAPEntry->pAssocResponse, pPacketBuffer, TotalLength); } // Save association ID, time, etc pAPEntry->AssocID = AID; NdisGetCurrentSystemTime(&(pAPEntry->AssociationUpTime)); pAPEntry->AssocState = dot11_assoc_state_auth_assoc; NdisDprReleaseSpinLock(&(pAPEntry->Lock)); NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); if (bSetTxDataRate == TRUE) { // // Set data TX rate // Hw11SetTXDataRate(pStation->pNic, &rateSet, Hw11GetCalibratedRSSI(pStation->pNic, pNicFragment) ); } // // Attempt to cancel the timer // /*NdisMCancelTimer(&(pStation->ConnectContext.Timer_AssociateTimeout), &bTimerCancelled); */ bTimerCancelled = WdfTimerStop(pStation->ConnectContext.Timer_AssociateTimeout, FALSE); if (bTimerCancelled) { STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); } if (StatusCode) { StaAssociateComplete(pStation, StatusCode | DOT11_ASSOC_STATUS_ASSOCIATION_RESPONSE_START); } else { StaAssociateComplete(pStation, DOT11_ASSOC_STATUS_SUCCESS); } } else { NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); } } else { NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); MpTrace(COMP_ASSOC, DBG_LOUD, ("Association already timed out\n")); } STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); }
NDIS_STATUS StaCreateAssociateRequestPacket( __in PSTATION pStation, __in PSTA_BSS_ENTRY pAPEntry, __deref_out_opt PUCHAR* ppAssocPacket, __out PUSHORT pAssocPacketLength ) { PDOT11_MGMT_HEADER pMgmtMacHeader = NULL; PDOT11_ASSOC_REQUEST_FRAME pDot11AssocRequest = NULL; USHORT IESize; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pCurrentIE = NULL; DOT11_RATE_SET RateSet; BOOLEAN set; PNIC pNic = pStation->pNic; IESize = STA11_MAX_IE_BLOB_SIZE; // SSID + Rates IE *pAssocPacketLength = sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_ASSOC_REQUEST_FRAME) + IESize; MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, ppAssocPacket, *pAssocPacketLength, STA11_MEMORY_TAG); if (*ppAssocPacket == NULL) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to allocate association request packet\n")); return NDIS_STATUS_RESOURCES; } NdisZeroMemory(*ppAssocPacket, *pAssocPacketLength); pMgmtMacHeader = (PDOT11_MGMT_HEADER)*ppAssocPacket; // // Fill the MAC header // pMgmtMacHeader->FrameControl.Version = 0x0; pMgmtMacHeader->FrameControl.Type = DOT11_FRAME_TYPE_MANAGEMENT; pMgmtMacHeader->FrameControl.Subtype = DOT11_MGMT_SUBTYPE_ASSOCIATION_REQUEST; pMgmtMacHeader->FrameControl.ToDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.FromDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.MoreFrag = 0x0; pMgmtMacHeader->FrameControl.Retry = 0x0; pMgmtMacHeader->FrameControl.PwrMgt = 0x0; pMgmtMacHeader->FrameControl.MoreData = 0x0; pMgmtMacHeader->FrameControl.WEP = 0x0; // no WEP pMgmtMacHeader->FrameControl.Order = 0x0; // no order memcpy(pMgmtMacHeader->DA, pAPEntry->MacAddress, DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->SA, Hw11GetMACAddress(pNic), DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->BSSID, pAPEntry->Dot11BSSID, DOT11_ADDRESS_SIZE ); pDot11AssocRequest = (PDOT11_ASSOC_REQUEST_FRAME)((*ppAssocPacket) + sizeof(DOT11_MGMT_HEADER)); do { // // Capabilities // NdisZeroMemory(&(pDot11AssocRequest->Capability), sizeof(DOT11_CAPABILITY)); pDot11AssocRequest->Capability.ESS = 1; pDot11AssocRequest->Capability.IBSS = 0; pDot11AssocRequest->Capability.CFPollable = (Hw11QueryCFPollable(pNic) ? 1 : 0); pDot11AssocRequest->Capability.CFPollRequest = 0; pDot11AssocRequest->Capability.Privacy = (pStation->Config.UnicastCipherAlgorithm != DOT11_CIPHER_ALGO_NONE) ? 1 : 0; switch (Hw11QueryCurrentPhyType(pNic)) { case dot11_phy_type_erp: Hw11QueryShortSlotTimeOptionImplemented(pNic, &set, FALSE); if (set) { Hw11QueryShortSlotTimeOptionEnabled(pNic, &set, FALSE); } pDot11AssocRequest->Capability.ShortSlotTime = set ? 1 : 0; Hw11QueryDsssOfdmOptionImplemented(pNic, &set, FALSE); if (set) { Hw11QueryDsssOfdmOptionEnabled(pNic, &set, FALSE); } pDot11AssocRequest->Capability.DSSSOFDM = set ? 1 : 0; // fall through case dot11_phy_type_hrdsss: // Enable/verify short preamble Hw11QueryShortPreambleOptionImplemented(pNic, &set, FALSE); pDot11AssocRequest->Capability.ShortPreamble = set ? 1: 0; Hw11QueryPbccOptionImplemented(pNic, &set, FALSE); pDot11AssocRequest->Capability.PBCC = set ? 1: 0; Hw11QueryChannelAgilityPresent(pNic, &set, FALSE); if (set) { Hw11QueryChannelAgilityEnabled(pNic, &set, FALSE); } pDot11AssocRequest->Capability.ChannelAgility = set ? 1 : 0; } pDot11AssocRequest->usListenInterval = pStation->Config.ListenInterval; pCurrentIE = ((PUCHAR)pDot11AssocRequest) + sizeof(DOT11_ASSOC_REQUEST_FRAME); // // Fill the SSID // ndisStatus = Dot11AttachElement( &pCurrentIE, &IESize, DOT11_INFO_ELEMENT_ID_SSID, (UCHAR)pStation->Config.SSID.uSSIDLength, pStation->Config.SSID.ucSSID ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to populate SSID in association request\n")); break; } // // Fill the supported rates // Hw11QueryOperationalRateSet(pNic, &RateSet, FALSE); StaFilterUnsupportedRates(pAPEntry, &RateSet); ndisStatus = Dot11AttachElement( &pCurrentIE, &IESize, DOT11_INFO_ELEMENT_ID_SUPPORTED_RATES, (UCHAR)((RateSet.uRateSetLength > 8) ? 8 : RateSet.uRateSetLength), RateSet.ucRateSet ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to populate supported rates in association request\n")); break; } // // Add the extended rate set if needed // if (RateSet.uRateSetLength > (UCHAR)8) { ndisStatus = Dot11AttachElement( &pCurrentIE, &IESize, DOT11_INFO_ELEMENT_ID_EXTD_SUPPORTED_RATES, (UCHAR)(RateSet.uRateSetLength - 8), (RateSet.ucRateSet + 8) ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to add extended rates in association request\n")); break; } } // // RSNA/WPA IE // if (pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_RSNA || pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_RSNA_PSK || pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_WPA || pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_WPA_PSK) { ndisStatus = StaAttachInfraRSNIE(pStation, pAPEntry, &pCurrentIE, &IESize); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to add RSN IE in association request\n")); break; } } // // Adjust packet length for IE space we did not use. Eg. if the SSID is not 32 bytes long, // we have empty space here that we dont want send out in the packet. // *pAssocPacketLength = *pAssocPacketLength - IESize; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { MP_FREE_MEMORY(*ppAssocPacket); *ppAssocPacket = NULL; } return ndisStatus; }
NDIS_STATUS Hvl11Fill80211Attributes( _In_ PHVL Hvl, _Out_ PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES Attr ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG vwifiAttrSize = 0; PDOT11_VWIFI_ATTRIBUTES VWiFiAttribs = NULL; PDOT11_VWIFI_COMBINATION_V2 pCombination = NULL; do { vwifiAttrSize = FIELD_OFFSET(DOT11_VWIFI_ATTRIBUTES, Combinations) + NUM_SUPPORTED_VWIFI_COMBINATIONS * DOT11_SIZEOF_VWIFI_COMBINATION_REVISION_2; MP_ALLOCATE_MEMORY( Hvl->MiniportAdapterHandle, &Attr->VWiFiAttributes, vwifiAttrSize, MP_MEMORY_TAG ); if (NULL == Attr->VWiFiAttributes) { MpTrace(COMP_OID, DBG_SERIOUS, ("Failed to allocate %d bytes for VWiFi capability.\n", vwifiAttrSize)); ndisStatus = NDIS_STATUS_RESOURCES; break; } VWiFiAttribs = Attr->VWiFiAttributes; NdisZeroMemory(VWiFiAttribs, vwifiAttrSize); MP_ASSIGN_NDIS_OBJECT_HEADER( VWiFiAttribs->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_VWIFI_ATTRIBUTES_REVISION_1, sizeof(DOT11_VWIFI_ATTRIBUTES)); VWiFiAttribs->uTotalNumOfEntries = NUM_SUPPORTED_VWIFI_COMBINATIONS; pCombination = (PDOT11_VWIFI_COMBINATION_V2)&VWiFiAttribs->Combinations[0]; // support for Infra-SoftAP MP_ASSIGN_NDIS_OBJECT_HEADER( pCombination->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_VWIFI_COMBINATION_REVISION_2, DOT11_SIZEOF_VWIFI_COMBINATION_REVISION_2); pCombination->uNumInfrastructure = 1; pCombination->uNumSoftAP = 1; } while (FALSE); return ndisStatus; }
NDIS_STATUS BasePortAllocatePort( _In_ PADAPTER Adapter, _In_ MP_PORT_TYPE PortType, _Outptr_result_nullonfailure_ PMP_PORT* Port ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PMP_PORT newPort = NULL; *Port = NULL; do { // Allocate a PORT data structure MP_ALLOCATE_MEMORY(Adapter->MiniportAdapterHandle, &newPort, sizeof(MP_PORT), PORT_MEMORY_TAG); if (newPort == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate %d bytes for port\n", sizeof(MP_PORT))); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Clear everything NdisZeroMemory(newPort, sizeof(MP_PORT)); // Allocate memory for fields inside the PORT structure NdisAllocateSpinLock(&(newPort->Lock)); NDIS_INIT_MUTEX(&(newPort->ResetPnpMutex)); // The VNIC ndisStatus = VNic11Allocate(Adapter->MiniportAdapterHandle, &(newPort->VNic), newPort); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // Save the passed data into the PORT newPort->MiniportAdapterHandle = Adapter->MiniportAdapterHandle; newPort->Adapter = Adapter; newPort->PortType = PortType; newPort->CurrentOpMode = DOT11_OPERATION_MODE_UNKNOWN; newPort->CurrentOpState = INIT_STATE; // We start in paused state MP_SET_PORT_STATUS(newPort, MP_PORT_PAUSED); newPort->PauseCount = 1; // Setup the default handler functions newPort->RequestHandler = BasePortOidHandler; newPort->DirectRequestHandler = BasePortDirectOidHandler; newPort->SendEventHandler = BasePortSendEventHandler; newPort->SendCompleteEventHandler = BasePortSendCompleteEventHandler; newPort->ReceiveEventHandler = BasePortReceiveEventHandler; newPort->ReturnEventHandler = BasePortReturnEventHandler; newPort->AutoConfigEnabled = DOT11_PHY_AUTO_CONFIG_ENABLED_FLAG | DOT11_MAC_AUTO_CONFIG_ENABLED_FLAG; // Return the newly created structure to the caller *Port = newPort; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { if (newPort != NULL) { BasePortFreePort(newPort); } } return ndisStatus; }
// BSS list lock acquired & called at Dispatch NDIS_STATUS HelperPortUpdateBSSEntry( __in PMP_HELPER_PORT HelperPort, __in PMP_BSS_ENTRY pBSSEntry, __in PMP_RX_MPDU pFragment, __in PDOT11_BEACON_FRAME pDot11BeaconPRFrame, __in ULONG BeaconPRDataLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_MGMT_HEADER pMgmtPktHeader; ULONGLONG ullHostTimeStamp; PVOID pSavedBeaconPRBuffer = NULL; ULONG uOffsetOfInfoElemBlob = FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements); UCHAR channel; DOT11_PHY_TYPE PhyType; pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment); NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp); do { // // Modifying data in the AP entry // NdisDprAcquireSpinLock(&(pBSSEntry->Lock)); if (pDot11BeaconPRFrame->Capability.IBSS) { pBSSEntry->Dot11BSSType = dot11_BSS_type_independent; } else { pBSSEntry->Dot11BSSType = dot11_BSS_type_infrastructure; } // // Adhoc station can leave adhoc cell and create a new cell. SoftAPs // can move. This means the BSSID can change // NdisMoveMemory( pBSSEntry->Dot11BSSID, pMgmtPktHeader->BSSID, sizeof(DOT11_MAC_ADDRESS) ); pBSSEntry->HostTimestamp = ullHostTimeStamp; pBSSEntry->BeaconTimestamp = pDot11BeaconPRFrame->Timestamp; pBSSEntry->BeaconInterval = pDot11BeaconPRFrame->BeaconInterval; pBSSEntry->Dot11Capability = pDot11BeaconPRFrame->Capability; pBSSEntry->RSSI = pFragment->Msdu->RecvContext.lRSSI; pBSSEntry->LinkQuality = pFragment->Msdu->LinkQuality; pBSSEntry->ChannelCenterFrequency = pFragment->Msdu->RecvContext.uChCenterFrequency; // // If signal strength was below our threshold, catch that // if (pBSSEntry->LinkQuality < HelperPort->RegInfo->RSSILinkQualityThreshold) { pBSSEntry->LowQualityCount++; } else { pBSSEntry->LowQualityCount = 0; } #if 0 if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Received beacon from associated AP: %02X-%02X-%02X-%02X-%02X-%02X\n", pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5])); } #endif // // Get channel number at which the frame was received. // if (Dot11GetChannelForDSPhy(Add2Ptr(pDot11BeaconPRFrame, uOffsetOfInfoElemBlob), BeaconPRDataLength - uOffsetOfInfoElemBlob, &channel) != NDIS_STATUS_SUCCESS) { channel = pFragment->Msdu->Channel; } if (channel != 0) { pBSSEntry->Channel = channel; } // // Get PhyType and PhyId // PhyType = VNic11DeterminePHYType(HELPPORT_GET_VNIC(HelperPort), pBSSEntry->Dot11Capability, pBSSEntry->Channel); if (pBSSEntry->Dot11PhyType != PhyType) { pBSSEntry->Dot11PhyType = PhyType; pBSSEntry->PhyId = BasePortGetPhyIdFromType(HELPPORT_GET_MP_PORT(HelperPort), PhyType); } if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_BEACON) { // // Increase the beacon frame size if necessary // if (pBSSEntry->MaxBeaconFrameSize < BeaconPRDataLength) { MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pSavedBeaconPRBuffer, BeaconPRDataLength, PORT_MEMORY_TAG ); if (pSavedBeaconPRBuffer == NULL) { // // Unable to allocate memory for information elements. // If this is a new AP entry, we wont be adding it to the list. // For existing entries, we end up ignoring the new IE blob // ndisStatus = NDIS_STATUS_RESOURCES; NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); break; } // // Delete any old blob buffer // if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); } pBSSEntry->pDot11BeaconFrame = pSavedBeaconPRBuffer; pBSSEntry->MaxBeaconFrameSize = BeaconPRDataLength; } // Update the beacon pBSSEntry->BeaconFrameSize = BeaconPRDataLength; // Also save this as the IE blob pointer pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob; pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11BeaconFrame + uOffsetOfInfoElemBlob; // // Update/Save the beacon information element block // NdisMoveMemory( pBSSEntry->pDot11BeaconFrame, pDot11BeaconPRFrame, BeaconPRDataLength ); } if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_PROBE_RESPONSE) { // // Increase the probe response frame size if necessary // if (pBSSEntry->MaxProbeFrameSize < BeaconPRDataLength) { MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pSavedBeaconPRBuffer, BeaconPRDataLength, PORT_MEMORY_TAG ); if (pSavedBeaconPRBuffer == NULL) { // // Unable to allocate memory for information elements. // If this is a new AP entry, we wont be adding it to the list. // For existing entries, we end up ignoring the new IE blob // ndisStatus = NDIS_STATUS_RESOURCES; NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); break; } // // Delete any old blob buffer // if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); } pBSSEntry->pDot11ProbeFrame = pSavedBeaconPRBuffer; pBSSEntry->MaxProbeFrameSize = BeaconPRDataLength; } pBSSEntry->ProbeFrameSize = BeaconPRDataLength; // Also save this as the IE blob pointer pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob; pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11ProbeFrame + uOffsetOfInfoElemBlob; // // Update/Save the beacon information element block // NdisMoveMemory( pBSSEntry->pDot11ProbeFrame, pDot11BeaconPRFrame, BeaconPRDataLength ); } #if 0 if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc) { MpTrace(COMP_SCAN, DBG_LOUD, ("Received %d for AP %02X-%02X-%02X-%02X-%02X-%02X \n", pMgmtPktHeader->FrameControl.Subtype, pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5])); } #endif // // Done with our modification of the AP entry // NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); } while (FALSE); return ndisStatus;
NDIS_STATUS HelperPortInsertBSSEntry( __in PMP_HELPER_PORT HelperPort, __in PMP_RX_MPDU pFragment, __in PDOT11_BEACON_FRAME pDot11BeaconFrame, __in ULONG BeaconDataLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONGLONG ullHostTimeStamp; MP_RW_LOCK_STATE LockState; PMP_BSS_ENTRY pBSSEntry = NULL; PDOT11_MGMT_HEADER pMgmtPktHeader; BOOLEAN bNewAp = FALSE; PMP_BSS_LIST pDiscoveredBSSList = &(HelperPort->BSSList); pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment); NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp); // // We acquire the write lock as we are adding entries to the list // MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); do { // // Check again if this entry already exists in the list. This is to handle // if the AP was added since we first checked (possible if the // flush routine was running) // pBSSEntry = HelperPortFindBSSEntry( pDiscoveredBSSList, pMgmtPktHeader->SA ); if (pBSSEntry == NULL) { bNewAp = TRUE; // New AP // // We havent found this AP yet, we would add it to the list // if (pDiscoveredBSSList->NumOfBSSEntries >= pDiscoveredBSSList->MaxNumOfBSSEntries) { // // We need to replace an entry thats in the list // pBSSEntry = HelperPortExpireBSSEntry( pDiscoveredBSSList, HelperPort->RegInfo->BSSEntryExpireTime, ullHostTimeStamp ); if (pBSSEntry != NULL) { // // Add initial in-use refcount // pBSSEntry->RefCount = 1; } // // Dont zero out the AP entry so that we can // reuse the info element blob // } else { // // Create a new entry for this AP // MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pBSSEntry, sizeof(MP_BSS_ENTRY), PORT_MEMORY_TAG ); if (pBSSEntry != NULL) { // // Initialize the new entry // NdisZeroMemory(pBSSEntry, sizeof(MP_BSS_ENTRY)); pBSSEntry->RefCount = 1; // Add initial in-use refcount NdisAllocateSpinLock(&(pBSSEntry->Lock)); } } if (pBSSEntry == NULL) { MpTrace(COMP_SCAN, DBG_SERIOUS, ("Not enough space to add AP: %02X-%02X-%02X-%02X-%02X-%02X\n", pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5])); ndisStatus = NDIS_STATUS_RESOURCES; break; } // // This Entry is not yet in the list // // We will be updating the beacon & probe response frames pBSSEntry->BeaconFrameSize = 0; pBSSEntry->ProbeFrameSize = 0; pBSSEntry->AssocCost = 0; NdisMoveMemory( pBSSEntry->Dot11BSSID, pMgmtPktHeader->BSSID, sizeof(DOT11_MAC_ADDRESS) ); NdisMoveMemory( pBSSEntry->MacAddress, pMgmtPktHeader->SA, sizeof(DOT11_MAC_ADDRESS) ); } // Update the information in this BSS entry (either new or reused entry) ndisStatus = HelperPortUpdateBSSEntry( HelperPort, pBSSEntry, pFragment, pDot11BeaconFrame, BeaconDataLength ); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // Add the new BSS to our list // if (bNewAp) { MpTrace(COMP_SCAN, DBG_LOUD, ("AP %02X-%02X-%02X-%02X-%02X-%02X at channel: %d (%d)\n", pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5], pBSSEntry->Channel, pFragment->Msdu->Channel)); HelperPortAddBSSEntry(pDiscoveredBSSList, pBSSEntry); } // // Note: If any code is added below here, remember to remove entry // from the list // } while (FALSE); MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); if (ndisStatus != NDIS_STATUS_SUCCESS) { // Free the new entry we may have created if ((bNewAp) && (pBSSEntry != NULL)) { if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); pBSSEntry->pDot11BeaconFrame = NULL; pBSSEntry->BeaconFrameSize = 0; pBSSEntry->MaxBeaconFrameSize= 0; } if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); pBSSEntry->pDot11ProbeFrame = NULL; pBSSEntry->ProbeFrameSize = 0; pBSSEntry->MaxProbeFrameSize= 0; } pBSSEntry->pDot11InfoElemBlob = NULL; pBSSEntry->InfoElemBlobSize = 0; MP_FREE_MEMORY(pBSSEntry); } } return ndisStatus;
NDIS_STATUS Hw11Allocate( __in NDIS_HANDLE MiniportAdapterHandle, __deref_out_opt PHW* Hw, __in PADAPTER Adapter ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PHW newHw = NULL; ULONG size; NDIS_TIMER_CHARACTERISTICS timerChar; *Hw = NULL; do { // Allocate a HW data structure MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &newHw, sizeof(HW), HW_MEMORY_TAG); if (newHw == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate %d bytes for HW\n", sizeof(HW))); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Clear everything NdisZeroMemory(newHw, sizeof(HW)); // We start in the PAUSED state HW_SET_ADAPTER_STATUS(newHw, HW_ADAPTER_PAUSED); newHw->InterruptDisableCount = 1; // Since we are paused, we want the interrupts to be disabled #if DBG NdisInterlockedIncrement(&newHw->Tracking_InterruptDisable[HW_ISR_TRACKING_PAUSE]); #endif // Allocate memory for fields inside the HW structure size = sizeof(DOT11_REG_DOMAINS_SUPPORT_VALUE) + (HW_MAX_NUM_DOT11_REG_DOMAINS_VALUE - 1) * sizeof(DOT11_REG_DOMAIN_VALUE); MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &(newHw->PhyState.RegDomainsSupportValue), size, HW_MEMORY_TAG); if (newHw->PhyState.RegDomainsSupportValue == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate memory for RegDomainsSupportValue\n")); ndisStatus = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(newHw->PhyState.RegDomainsSupportValue, size); size = sizeof(DOT11_DIVERSITY_SELECTION_RX_LIST) + (HW_MAX_NUM_DIVERSITY_SELECTION_RX_LIST - 1) * sizeof(DOT11_DIVERSITY_SELECTION_RX); MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &(newHw->PhyState.DiversitySelectionRxList), size, HW_MEMORY_TAG); if (newHw->PhyState.DiversitySelectionRxList == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate memory for DiversitySelectionRxList\n")); ndisStatus = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(newHw->PhyState.DiversitySelectionRxList, size); NdisZeroMemory(&timerChar, sizeof(NDIS_TIMER_CHARACTERISTICS)); // Allocate the power save wake timer timerChar.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS; timerChar.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1; timerChar.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS); timerChar.AllocationTag = HW_MEMORY_TAG; timerChar.TimerFunction = HwAwakeTimer; timerChar.FunctionContext = newHw; ndisStatus = NdisAllocateTimerObject( MiniportAdapterHandle, &timerChar, &newHw->PhyState.Timer_Awake ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate power save awake timer\n")); break; } // Allocate the power save sleep timer timerChar.TimerFunction = HwDozeTimer; timerChar.FunctionContext = newHw; ndisStatus = NdisAllocateTimerObject( MiniportAdapterHandle, &timerChar, &newHw->PhyState.Timer_Doze ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate power save doze timer\n")); break; } // Allocate the scan timer timerChar.TimerFunction = HwScanTimer; timerChar.FunctionContext = newHw; ndisStatus = NdisAllocateTimerObject( MiniportAdapterHandle, &timerChar, &newHw->ScanContext.Timer_Scan ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate scan timer\n")); break; } newHw->PhyState.PhyProgramWorkItem = NdisAllocateIoWorkItem(MiniportAdapterHandle); if(newHw->PhyState.PhyProgramWorkItem == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate channel switch work item\n")); ndisStatus = NDIS_STATUS_RESOURCES; break; } // The hardware lock NdisAllocateSpinLock(&newHw->Lock); // Save the Adapter pointer in the HW newHw->Adapter = Adapter; newHw->MiniportAdapterHandle = MiniportAdapterHandle; // Return the newly created structure to the caller *Hw = newHw; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { if (newHw != NULL) { Hw11Free(newHw); } } return ndisStatus; }
VOID HelperPortStartScanProcess( _In_ PMP_HELPER_PORT HelperPort, _In_ PMP_SCAN_PARAMETERS ScanParameters ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG scanChannelCount = 0; ULONG i; do { MpTrace(COMP_SCAN, DBG_NORMAL, ("Starting the scan process of %p for port %p\n", ScanParameters, ScanParameters->RequestingPort)); // // For optimal scanning, we specify the list of channels // that the HW should use if the port hasnt specified any. // Note that for ExtSTA the channels in the PhyTypeInfo // structures of the DOT11_SCAN_REQUEST are invalid. So we dont // need to consider those // if (ScanParameters->PortScanRequest->ChannelCount != 0) { // Use the list of channels specified by the port scanChannelCount = ScanParameters->PortScanRequest->ChannelCount; } else { if (HelperPort->ScanContext.MediaConnectedCount > 0) { // A port is connected (STA associated/AP started/Adhoc running) // We dont scan all channels in one shot. We do multiple partial // scans // The scan type determines the number of channels we scan at a time if (ScanParameters->PortScanRequest->Dot11ScanRequest->dot11ScanType & dot11_scan_type_active) scanChannelCount = HelperPort->RegInfo->ActiveScanChannelCount; else scanChannelCount = HelperPort->RegInfo->PassiveScanChannelCount; MpTrace(COMP_SCAN, DBG_NORMAL, ("Link Up scan will scan atmost %d channels at a time\n", scanChannelCount)); } else { // We can scan each phy in one scan. Find the maximum number of // channels in a phy & use that as our scan channels limit scanChannelCount = 0; for (i = 0; i < HW11_MAX_PHY_COUNT; i++) { if (HelperPort->ScanContext.ScanChannels[i].ChannelCount > scanChannelCount) { scanChannelCount = HelperPort->ScanContext.ScanChannels[i].ChannelCount; } } MpTrace(COMP_SCAN, DBG_NORMAL, ("Link Down scan will scan upto %d channels at a time\n", scanChannelCount)); } } ScanParameters->MaxChannelCount = scanChannelCount; // // Create a channel buffer that we would give to the lower layer // MP_ALLOCATE_MEMORY( HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &ScanParameters->VNicScanRequest.ChannelList, scanChannelCount * sizeof(ULONG), PORT_MEMORY_TAG ); if (ScanParameters->VNicScanRequest.ChannelList == NULL) { ndisStatus = NDIS_STATUS_RESOURCES; break; } // // Save scan start time // NdisGetCurrentSystemTime((PLARGE_INTEGER)&HelperPort->ScanContext.LastScanTime); ScanParameters->VNicScanRequest.Dot11ScanRequest = ScanParameters->PortScanRequest->Dot11ScanRequest; ScanParameters->VNicScanRequest.ScanRequestBufferLength = ScanParameters->PortScanRequest->ScanRequestBufferLength; MP_ACQUIRE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE); if (ScanParameters->CancelScan) { MpTrace(COMP_SCAN, DBG_NORMAL, ("Aborting scan start for a cancelled scan request\n")); ndisStatus = NDIS_STATUS_REQUEST_ABORTED; } else { // We will queue an exclusive access request ScanParameters->State = SCAN_EXCLUSIVE_ACCESS_QUEUED; } MP_RELEASE_PORT_LOCK(HELPPORT_GET_MP_PORT(HelperPort), FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // Queue an exclusive access. The scan would be done in there // ndisStatus = HelperPortRequestExclusiveAccess(HelperPort, HelperPortScanExAccessCallback, ScanParameters, FALSE ); if (NDIS_STATUS_SUCCESS == ndisStatus) { // the function completed synchronously, call the callback ourselves HelperPortScanExAccessCallback(HELPPORT_GET_MP_PORT(HelperPort), ScanParameters); } else if (ndisStatus == NDIS_STATUS_PENDING) { // Pending is same as success if (ndisStatus == NDIS_STATUS_PENDING) { ndisStatus = NDIS_STATUS_SUCCESS; } } else { // The exclusive access request failed MpTrace(COMP_SCAN, DBG_SERIOUS, ("Exclusive access request for scan start failed. Status = 0x%08x\n", ndisStatus)); } }while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { HelperPortCompleteScanProcess( HelperPort, ScanParameters, &ndisStatus ); } }
NDIS_STATUS HelperPortCreateScanChannelList( _In_ PMP_HELPER_PORT HelperPort ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG phyId, channelListIndex = 0; PDOT11_SUPPORTED_PHY_TYPES supportedPhyTypes; UCHAR buffer[(sizeof(DOT11_SUPPORTED_PHY_TYPES) + sizeof(DOT11_PHY_TYPE) * HW11_MAX_PHY_COUNT)]; PMP_SCAN_CHANNEL_LIST currentChannelList; DOT11_PHY_TYPE bgScanPhy; do { // // Get supported PHY types. // supportedPhyTypes = (PDOT11_SUPPORTED_PHY_TYPES) buffer; supportedPhyTypes->uNumOfEntries = 0; VNic11QuerySupportedPHYTypes(HELPPORT_GET_VNIC(HelperPort), HW11_MAX_PHY_COUNT, supportedPhyTypes ); // // For devices supporting both b & g phys, we only scan on g. Check if // we need to do this here // bgScanPhy = dot11_phy_type_hrdsss; for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++) { if (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_erp) { // Support g, no need to scan b bgScanPhy = dot11_phy_type_erp; break; } } // // Go through the list to see if there is a phy type we scan for // for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++) { // We only scan on g(or b) & a phy if ((supportedPhyTypes->dot11PHYType[phyId] == bgScanPhy) || (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_ofdm)) { // Query for the channel list currentChannelList = &HelperPort->ScanContext.ScanChannels[channelListIndex]; // Start with a zero length buffer to determine the size currentChannelList->ChannelCount = 0; ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), phyId, ¤tChannelList->ChannelCount, NULL ); if (ndisStatus != NDIS_STATUS_BUFFER_TOO_SHORT) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query size of the channel list for phy ID %d\n", phyId)); // We skip this PHY ndisStatus = NDIS_STATUS_SUCCESS; break; } MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, ¤tChannelList->ChannelList, currentChannelList->ChannelCount * sizeof(ULONG), PORT_MEMORY_TAG ); if (currentChannelList->ChannelList == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to allocate memory for the channel list for phy ID %d\n", phyId)); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Query again ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), phyId, ¤tChannelList->ChannelCount, currentChannelList->ChannelList ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query channel list for phy ID %d\n", phyId)); break; } currentChannelList->PhyId = phyId; // Populated one set of channels channelListIndex++; } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } } } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { for (channelListIndex = 0; channelListIndex < HW11_MAX_PHY_COUNT; channelListIndex++) { if (HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList != NULL) { MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList); HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList = NULL; } } } return ndisStatus; }