#include "Mp_Precomp.h" #if WPP_SOFTWARE_TRACE #include "P2P.tmh" #endif #include "P2P_Internal.h" #if (P2P_SUPPORT == 1) u8Byte RTL_P2P_AllocateMemory_count ; u8Byte RTL_P2P_FreeMemory_count ; u8Byte RTL_P2P_AllocateMemory_Len; u8Byte RTL_P2P_FreeMemory_Len; //====================================================================== // Wi-Fi Direct Start //====================================================================== static u1Byte BroadcastAddress[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static u1Byte P2PSocialChannels[] = { 1, 6, 11, }; static u1Byte P2PWildcardSsid[] = {'D', 'I', 'R','E', 'C', 'T', '-'}; //====================================================================== // Private Functions (Starting from Win8) (Keyword Static) //====================================================================== static BOOLEAN P2PAdapterAcceptActionFrame( PADAPTER pAdapter, OCTET_STRING osPacket ) { BOOLEAN bReturnValue = FALSE; ACT_PKT_TYPE pktType = PacketGetActionFrameType(&osPacket); switch(pktType) { default: break; // For Win8, these P2P handshake packets shall transfer to the device port. case ACT_PKT_P2P_GO_NEG_REQ: case ACT_PKT_P2P_GO_NEG_RSP: case ACT_PKT_P2P_GO_NEG_CONF: case ACT_PKT_P2P_PROV_DISC_REQ: case ACT_PKT_P2P_PROV_DISC_RSP: case ACT_PKT_P2P_INVIT_REQ: case ACT_PKT_P2P_INVIT_RSP: if(GET_P2P_INFO(pAdapter)->Role == P2P_DEVICE) bReturnValue = TRUE; // NOT Ready: break; } return bReturnValue; } static BOOLEAN P2PAdapterAcceptMgntFrame( PADAPTER pAdapter, OCTET_STRING osPacket ) { // Accept all management frames BOOLEAN bStatus = FALSE; switch(P2P_FRAME_GET_TYPE(osPacket.Octet)) { case Type_Probe_Req: case Type_Probe_Rsp: case Type_Beacon: case Type_Asoc_Req: case Type_Reasoc_Req: case Type_Asoc_Rsp: case Type_Reasoc_Rsp: case Type_Deauth: case Type_Disasoc: bStatus = TRUE; break; } return bStatus; } BOOLEAN P2PAdapterAcceptFrame( PADAPTER pAdapter, OCTET_STRING osPacket ) { BOOLEAN bStatus = FALSE; if(IsMgntAction(osPacket.Octet)) { bStatus = P2PAdapterAcceptActionFrame(pAdapter, osPacket); } else if(IsMgntFrame(osPacket.Octet)) { bStatus = P2PAdapterAcceptMgntFrame(pAdapter, osPacket); } return bStatus; } // The operations of the structure MEMORY_BUFFER static VOID P2PMemoryBufferFree( PMEMORY_BUFFER pMemoryBuffer ) { if(pMemoryBuffer->Length > 0) { PlatformFreeMemory(pMemoryBuffer->Buffer, pMemoryBuffer->Length); RTL_P2P_FreeMemory_count++; RTL_P2P_FreeMemory_Len += pMemoryBuffer->Length; } PlatformZeroMemory(pMemoryBuffer, sizeof(MEMORY_BUFFER)); pMemoryBuffer->Length = 0; } // The operations of the structure MEMORY_BUFFER static BOOLEAN P2PMemoryBufferClone( PP2P_INFO pP2PInfo, PMEMORY_BUFFER pDestination, PMEMORY_BUFFER pSource ) { BOOLEAN bStatus = FALSE; RT_STATUS rtStatus = RT_STATUS_FAILURE; if(pDestination->Length > 0) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: With Unloaded Memory!\n", __FUNCTION__)); bStatus = FALSE; } else if(pSource->Length > 0 && pSource->Buffer == NULL) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Illegal Source Memory!\n", __FUNCTION__)); bStatus = FALSE; } else if(pSource->Length == 0) { *pDestination = *pSource; bStatus = TRUE; } else { rtStatus = PlatformAllocateMemory( pP2PInfo->pAdapter, &pDestination->Buffer, pSource->Length ); if(rtStatus == RT_STATUS_SUCCESS) { pDestination->Length = pSource->Length; PlatformMoveMemory( pDestination->Buffer, pSource->Buffer, pDestination->Length ); bStatus = TRUE; RTL_P2P_AllocateMemory_count ++; RTL_P2P_AllocateMemory_Len += pSource->Length; } else { PlatformZeroMemory(pDestination, sizeof(MEMORY_BUFFER)); pDestination->Length = 0; bStatus = FALSE; RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Memory Allocation Failure!\n", __FUNCTION__)); } } return bStatus; } // The operations of the structure MEMORY_BUFFER static BOOLEAN P2PMemoryBufferCopy( PP2P_INFO pP2PInfo, PMEMORY_BUFFER pDestination, PMEMORY_BUFFER pSource ) { BOOLEAN bStatus = FALSE; RT_STATUS rtStatus = RT_STATUS_FAILURE; if(pDestination->Length > 0 && pSource->Length > 0) { if(pDestination->Length == pSource->Length) { if(PlatformCompareMemory(pDestination->Buffer, pSource->Buffer, pSource->Length) != 0) CopyMem(pDestination->Buffer, pSource->Buffer, pSource->Length); bStatus = TRUE; } } return bStatus; } static VOID P2PDeviceListDump( PP2P_DEVICE_LIST pDeviceList ) { u4Byte i = 0; RT_TRACE(COMP_P2P, DBG_LOUD, ("\n")); for(i = 0; i < pDeviceList->uNumberOfDevices; i++) { RT_TRACE(COMP_P2P, DBG_LOUD, ("=======================================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("DeviceList: Entry(%u)\n", i)); RT_TRACE(COMP_P2P, DBG_LOUD, ("=======================================================\n")); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "MacAddress: ", pDeviceList->DeviceEntry[i].MacAddress); if(pDeviceList->DeviceEntry[i].DeviceAddress != NULL) RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "DeviceAddress: ", pDeviceList->DeviceEntry[i].DeviceAddress); RT_TRACE(COMP_P2P, DBG_LOUD, ("ChannelNumber: %d\n", pDeviceList->DeviceEntry[i].ChannelNumber)); RT_TRACE(COMP_P2P, DBG_LOUD, ("RecvSignalPower: %d\n", pDeviceList->DeviceEntry[i].RecvSignalPower)); RT_TRACE(COMP_P2P, DBG_LOUD, ("SignalStrength: %d\n", pDeviceList->DeviceEntry[i].SignalStrength)); RT_TRACE(COMP_P2P, DBG_LOUD, ("ProbeResponseHostTimestamp: 0x%08X%08X\n", (u4Byte)(pDeviceList->DeviceEntry[i].ProbeResponseHostTimestamp >> 32), (u4Byte) pDeviceList->DeviceEntry[i].ProbeResponseHostTimestamp) ); RT_TRACE(COMP_P2P, DBG_LOUD, ("BeaconHostTimestamp: 0x%08X%08X\n", (u4Byte)(pDeviceList->DeviceEntry[i].BeaconHostTimestamp >> 32), (u4Byte) pDeviceList->DeviceEntry[i].BeaconHostTimestamp) ); } RT_TRACE(COMP_P2P, DBG_LOUD, ("=======================================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("Totally %d items in Device List dumped\n", i)); RT_TRACE(COMP_P2P, DBG_LOUD, ("=======================================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("\n")); } // Indicate Fake Invitation rsp frame to OS and make the state machine in OS go to next state. // BOOLEAN P2PIndicateFakeInvitRsp( IN PP2P_INFO pP2PInfo ) { PADAPTER pAdapter = pP2PInfo->pAdapter; PRT_GEN_TEMP_BUFFER pGenBuf = NULL; PP2P_DEVICE_LIST_ENTRY pListEntry = NULL; OCTET_STRING osWFDIE, osProbeRspPkt; FRAME_BUF fbuf; pListEntry = P2PDeviceListFind(&pP2PInfo->DeviceList, pP2PInfo->InvitationContext.InvitedDevice.DeviceAddress); if(pListEntry == NULL) { return FALSE; } if(NULL == (pGenBuf = GetGenTempBuffer(pAdapter, GEN_TEMP_BUFFER_SIZE))) { RT_TRACE_F(COMP_WFD, DBG_SERIOUS, ("[ERROR] Memory allocation failed!\n")); return FALSE; } FrameBuf_Init(GEN_TEMP_BUFFER_SIZE, 0, (pu1Byte)pGenBuf->Buffer.Ptr, &fbuf); // MAC Header p2p_add_ActionFrameMacHdr(&fbuf, pP2PInfo->DeviceAddress, pP2PInfo->InvitationContext.InvitedDevice.DeviceAddress, pP2PInfo->DeviceAddress); // Action Header p2p_add_P2PPublicActionHdr(&fbuf, P2P_INVITATION_RSP, pP2PInfo->InvitationContext.DialogToken); // P2P IE p2p_build_FakeInvitationRspIe(&fbuf, pP2PInfo, pP2PInfo->InvitationContext.InvitedDevice.DeviceAddress); FillOctetString(osProbeRspPkt, pListEntry->ProbeResponsePacket.Buffer, (u2Byte)pListEntry->ProbeResponsePacket.Length); osWFDIE = PacketGetElement(osProbeRspPkt, EID_Vendor, OUI_SUB_WIFI_DISPLAY, OUI_SUB_DONT_CARE); if(osWFDIE.Length > 0) { PacketMakeElement(&fbuf.os, EID_Vendor, osWFDIE); } p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_INVITATION_RESPONSE, RT_STATUS_SUCCESS, fbuf.os.Octet, fbuf.os.Length); ReturnGenTempBuffer(pAdapter, pGenBuf); return TRUE; } static VOID P2PDeviceListClear( PP2P_DEVICE_LIST pDeviceList ) { u4Byte i = 0; for(i = 0; i < pDeviceList->uNumberOfDevices; i++) { P2PMemoryBufferFree(&pDeviceList->DeviceEntry[i].ProbeResponsePacket); P2PMemoryBufferFree(&pDeviceList->DeviceEntry[i].BeaconPacket); } PlatformZeroMemory(pDeviceList, sizeof(P2P_DEVICE_LIST)); } PP2P_DEVICE_LIST_ENTRY P2PDeviceListFind( IN PP2P_DEVICE_LIST pDeviceList, IN pu1Byte pMacAddress ) { u4Byte i = 0; for(i = 0; i < pDeviceList->uNumberOfDevices; i++) { if(eqMacAddr(pDeviceList->DeviceEntry[i].MacAddress, pMacAddress)) { return &pDeviceList->DeviceEntry[i]; } } return NULL; } static BOOLEAN P2PDeviceListInsertTail( IN PP2P_INFO pP2PInfo, OUT PP2P_DEVICE_LIST pDeviceList, IN PRT_RFD pRfd, IN pu1Byte pMacAddress, IN pu1Byte pDeviceAddress, IN MEMORY_BUFFER mbPacket ) { // PMGNT_INFO pMgntInfo = &pP2PInfo->pAdapter->MgntInfo; BOOLEAN bStatus = FALSE; u1Byte index = pDeviceList->uNumberOfDevices; pu1Byte header = (pu1Byte) mbPacket.Buffer; if(index < P2P_MAX_DEVICE_LIST) { cpMacAddr(pDeviceList->DeviceEntry[index].MacAddress, pMacAddress); if(pDeviceAddress) cpMacAddr(pDeviceList->DeviceEntry[index].DeviceAddress, pDeviceAddress); pDeviceList->DeviceEntry[index].ChannelNumber= P2PGetChannel(pP2PInfo); pDeviceList->DeviceEntry[index].RecvSignalPower = pRfd->Status.RecvSignalPower; pDeviceList->DeviceEntry[index].SignalStrength= pRfd->Status.SignalStrength; if(IsMgntProbeRsp(header)) { pDeviceList->DeviceEntry[index].ProbeResponseHostTimestamp = PlatformGetCurrentTime(); bStatus = P2PMemoryBufferClone(pP2PInfo, &pDeviceList->DeviceEntry[index].ProbeResponsePacket, &mbPacket); } else if(IsMgntBeacon(header)) { pDeviceList->DeviceEntry[index].BeaconHostTimestamp = PlatformGetCurrentTime(); bStatus = P2PMemoryBufferClone(pP2PInfo, &pDeviceList->DeviceEntry[index].BeaconPacket, &mbPacket); } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Wrong Mgnt Packet Type \n", __FUNCTION__)); return FALSE; } if(bStatus) { pDeviceList->uNumberOfDevices++; } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Memory Clone Failure!\n", __FUNCTION__)); } } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Size Limit Reached!\n", __FUNCTION__)); } return bStatus; } static BOOLEAN P2PGetWpsSelectedRegistrar( OCTET_STRING osWpsIE ) { u1Byte WPS_OUI[] = {0x00, 0x50, 0xF2, 0x04}; u4Byte offset = 0; u1Byte SelectedRegistrarID[] = {0x10, 0x41}; if(!eqNByte(osWpsIE.Octet, WPS_OUI, sizeof(WPS_OUI))) { RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "Not a valid good WPS IE!\n", osWpsIE.Octet, osWpsIE.Length); return FALSE; } offset += sizeof(WPS_OUI); while(offset + 4 < osWpsIE.Length) { if(eqNByte(osWpsIE.Octet + offset, SelectedRegistrarID, sizeof(SelectedRegistrarID))) { // Length 2 Bytes and ID 2 Bytes RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Found: WpsSelectedRegistrar: %d\n", __FUNCTION__, osWpsIE.Octet[offset + 4])); return (BOOLEAN)(osWpsIE.Octet[offset + 4]); } // Length 2 Bytes and ID 2 Bytes offset += 4 + P2P_WPS_ATTR_READ_EF_2_BYTE(osWpsIE.Octet + offset + 2); } return FALSE; } static VOID P2PDeviceListUpdate ( IN PP2P_INFO pP2PInfo, OUT PP2P_DEVICE_LIST pDeviceList, IN PRT_RFD pRfd, IN pu1Byte pMacAddress, IN pu1Byte pDeviceAddress, IN MEMORY_BUFFER mbPacket ) { PP2P_DEVICE_LIST_ENTRY pListEntry = NULL; BOOLEAN bStatus = FALSE; MEMORY_BUFFER mbObject = {NULL, 0}; pu1Byte header = (pu1Byte) mbPacket.Buffer; #if 0 // Debug MAC Address Filter { #define MAX_MAX_FILTER 10 u1Byte Macfilter[MAX_MAX_FILTER][6] = { {0x00, 0xe0, 0x4c, 0x78, 0x01, 0x1c}, {0x00, 0xe0, 0x4c, 0x78, 0x00, 0x02}, {0x00, 0xe0, 0x4c, 0x00, 0xf0, 0x2b}, {0x00, 0xe0, 0x4c, 0x00, 0x50, 0x2b} }; BOOLEAN update = TRUE; u1Byte i = 0; for(i = 0; i < MAX_MAX_FILTER; i++) { if(eqMacAddr(pMacAddress, Macfilter[i])) update = FALSE; } if(update == FALSE) return; } #endif // For the OID_DOT11_WFD_CONNECT_TO_GROUP_REQUEST and OID_DOT11_WFD_GROUP_START_PARAMETERS ------------------------- if(P2P_CLIETN_JOIN_GROUP_WPS_STATE_SCANNING == pP2PInfo->ClientJoinGroupContext.WpsState) { OCTET_STRING osPacket = {mbPacket.Buffer, (u2Byte) mbPacket.Length}; OCTET_STRING osSsid = {NULL, 0}; OCTET_STRING osWpsIE = {NULL, 0}; osSsid = PacketGetElement(osPacket, EID_SsId, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE); if(CompareSSID(pP2PInfo->GroupTargetSSID, (u2Byte) pP2PInfo->uGroupTargetSSIDLength, osSsid.Octet, osSsid.Length)) { osWpsIE = PacketGetElement(osPacket, EID_Vendor, OUI_SUB_SimpleConfig, OUI_SUB_DONT_CARE); if(osWpsIE.Length != 0 && P2PGetWpsSelectedRegistrar(osWpsIE) == TRUE) { RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "Target GO WPS IE:\n", osWpsIE.Octet, osWpsIE.Length); // Mark the WPS of the target is ready to join pP2PInfo->ClientJoinGroupContext.WpsState = P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY; P2PScanListCeaseScan(pP2PInfo); } else { RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "Target GO WPS IE: No Found! Keep waiting!\n", osWpsIE.Octet, osWpsIE.Length); } } } // -------------------------------------------------------------------------------------------------------------------- pListEntry = P2PDeviceListFind(pDeviceList, pMacAddress); if(pListEntry == NULL) { bStatus = P2PDeviceListInsertTail(pP2PInfo, pDeviceList, pRfd, pMacAddress, pDeviceAddress, mbPacket); if(bStatus == FALSE) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Insert Tail Failure!\n", __FUNCTION__)); } } else { // Fill the list entry structure if(pDeviceAddress) cpMacAddr(pListEntry->DeviceAddress, pDeviceAddress); {// Query for the Correct Channel Information OCTET_STRING osPacket = {mbPacket.Buffer, (u2Byte) mbPacket.Length}; OCTET_STRING DsPmBeacon = {NULL, 0}; DsPmBeacon = PacketGetElement(osPacket, EID_DSParms, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE); if(DsPmBeacon.Length != 0) { pListEntry->ChannelNumber= EF1Byte( *(u1Byte *)(DsPmBeacon.Octet) ); } else { pListEntry->ChannelNumber= RT_GetChannelNumber(pP2PInfo->pAdapter); } } pListEntry->RecvSignalPower = pRfd->Status.RecvSignalPower; pListEntry->SignalStrength= pRfd->Status.SignalStrength; if(IsMgntProbeRsp(header)) { pListEntry->ProbeResponseHostTimestamp = PlatformGetCurrentTime(); bStatus = P2PMemoryBufferCopy(pP2PInfo, &pListEntry->ProbeResponsePacket, &mbPacket); if(!bStatus) { bStatus = P2PMemoryBufferClone(pP2PInfo, &mbObject, &mbPacket); if(bStatus == TRUE) { P2PMemoryBufferFree(&pListEntry->ProbeResponsePacket); pListEntry->ProbeResponsePacket = mbObject; } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Memory Clone Failure!\n", __FUNCTION__)); } } } else if(IsMgntBeacon(header)) { pListEntry->BeaconHostTimestamp = PlatformGetCurrentTime(); bStatus = P2PMemoryBufferCopy(pP2PInfo, &pListEntry->BeaconPacket, &mbPacket); if(!bStatus) { bStatus = P2PMemoryBufferClone(pP2PInfo, &mbObject, &mbPacket); if(bStatus == TRUE) { P2PMemoryBufferFree(&pListEntry->BeaconPacket); pListEntry->BeaconPacket= mbObject; } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Memory Clone Failure!\n", __FUNCTION__)); } } } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Wrong Mgnt Packet Type \n", __FUNCTION__)); } } } static VOID P2PDeviceListCopyWithTimeStamp( IN PP2P_INFO pP2PInfo, OUT PP2P_DEVICE_LIST pDestination, IN PP2P_DEVICE_LIST pSource ) { u4Byte i = 0; //source u4Byte j = 0; //destination u4Byte usTimeoutLimit = 3 * 60 * 1000 * 1000; // 3 minutes BOOLEAN bBeaconStatus = FALSE; BOOLEAN bProbeResponseStatus = FALSE; MEMORY_BUFFER mbBeacon = {NULL, 0}; MEMORY_BUFFER mbProbeResponse = {NULL, 0}; u8Byte usCurrentTime = PlatformGetCurrentTime(); u8Byte usMaxHostTimestamp = 0; P2PDeviceListClear(pDestination); pDestination->uNumberOfDevices = 0; for(i = 0; i < pSource->uNumberOfDevices; i++) { // Remove the stale device item ---------------------------------------------------------- // + Find MAX usMaxHostTimestamp = MAX( pSource->DeviceEntry[i].BeaconHostTimestamp, pSource->DeviceEntry[i].ProbeResponseHostTimestamp ); // + Check the timestamp if(usCurrentTime - usMaxHostTimestamp > usTimeoutLimit) { //RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: usCurrentTime: %lld\n", __FUNCTION__, usCurrentTime)); //RT_TRACE(COMP_P2P, DBG_LOUD, ("usMaxHostTimestamp: %lld\n", usMaxHostTimestamp)); //RT_TRACE(COMP_P2P, DBG_LOUD, ("usCurrentTime - usMaxHostTimestamp: %lld, usTimeoutLimit: %d\n", // usCurrentTime - usMaxHostTimestamp, usTimeoutLimit) // ); continue; } // ----------------------------------------------------------------------------------- bBeaconStatus = FALSE; bProbeResponseStatus = FALSE; pDestination->DeviceEntry[j] = pSource->DeviceEntry[i]; // Beacon Packet PlatformZeroMemory( &pDestination->DeviceEntry[j].BeaconPacket, sizeof(MEMORY_BUFFER) ); PlatformZeroMemory(&mbBeacon , sizeof(MEMORY_BUFFER)); bBeaconStatus = P2PMemoryBufferClone(pP2PInfo, &mbBeacon, &pSource->DeviceEntry[i].BeaconPacket); // Probe Response Packet PlatformZeroMemory( &pDestination->DeviceEntry[j].ProbeResponsePacket, sizeof(MEMORY_BUFFER) ); PlatformZeroMemory(&mbProbeResponse , sizeof(MEMORY_BUFFER)); bProbeResponseStatus = P2PMemoryBufferClone(pP2PInfo, &mbProbeResponse, &pSource->DeviceEntry[i].ProbeResponsePacket); // Successful if(bBeaconStatus && bProbeResponseStatus) { pDestination->DeviceEntry[j].BeaconPacket = mbBeacon; pDestination->DeviceEntry[j].ProbeResponsePacket= mbProbeResponse; j++; pDestination->uNumberOfDevices = (u1Byte) j; } else { // Error Recovery if(bBeaconStatus == TRUE) { P2PMemoryBufferFree(&mbBeacon); RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Beacon Memory Clone Failure!\n", __FUNCTION__)); } if(bProbeResponseStatus == TRUE) { P2PMemoryBufferFree(&mbProbeResponse); RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Probe Response Memory Clone Failure!\n", __FUNCTION__)); } } } } //====================================================================== // P2P Utility //====================================================================== PADAPTER P2PGetGoAdapter( IN PP2P_INFO pP2PInfo ) { PADAPTER pAdapter = pP2PInfo->pAdapter; RT_AP_TYPE DefApType = MgntActQuery_ApType(GetDefaultAdapter(pAdapter)); RT_AP_TYPE ExtApType = MgntActQuery_ApType(GetFirstExtAdapter(pAdapter)); if(P2P_GO != pP2PInfo->Role) return pAdapter; //RT_ASSERT(!(0 < DefApType && 0 < ExtApType), ("Both Default port and ext port are acting as AP\n")); //RT_ASSERT(!(0 == DefApType && 0 == ExtApType), ("Both Default port and ext port are NOT acting as AP but role is GO\n")); return (0 < DefApType) ? (GetDefaultAdapter(pAdapter)) : (GetFirstExtAdapter(pAdapter)); } BOOLEAN P2PIsN24GSupported( IN PP2P_INFO pP2PInfo ) { PADAPTER pDefAdapter = pP2PInfo->pAdapter; u2Byte SupportedWirelessMode = pDefAdapter->HalFunc.GetSupportedWirelessModeHandler(pDefAdapter); //RT_TRACE(COMP_P2P, DBG_LOUD, // ("P2PIsN24GSupported(): SupportedWirelessMode: %u\n", // SupportedWirelessMode)); if(IS_24G_WIRELESS_MODE(SupportedWirelessMode)) { return TRUE; } else { return FALSE; } } VOID P2PGOSetBeaconInterval( IN PP2P_INFO pP2PInfo, u2Byte u2BeaconPeriod ) { // Note that if under Win7, ext port is used and if not, // ADJUST_TO_ADAPTIVE_ADAPTER(pAdapter, FALSE) // always return the only one adapter. PADAPTER pAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetFirstGOPort(pP2PInfo->pAdapter); PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); // // Note that if beacon interval is changed, // it is not recovered by only re-enabled P2P mode. // if(u2BeaconPeriod != pMgntInfo->dot11BeaconPeriod) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PGOSetBeaconInterval(): set beacon interval from (%u) to (%u)\n", pMgntInfo->dot11BeaconPeriod, u2BeaconPeriod)); pMgntInfo->Regdot11BeaconPeriod = u2BeaconPeriod; pMgntInfo->dot11BeaconPeriod = pMgntInfo->Regdot11BeaconPeriod; pAdapter->HalFunc.SetHwRegHandler(pAdapter, HW_VAR_BEACON_INTERVAL, (pu1Byte)(&pMgntInfo->dot11BeaconPeriod)); } } BOOLEAN P2PProvisioning( IN PP2P_INFO pP2PInfo ) { #if (WPS_SUPPORT == 1) PADAPTER pDefAdapter = GetDefaultAdapter(pP2PInfo->pAdapter); return GET_SIMPLE_CONFIG_ENABLED(&pDefAdapter->MgntInfo); #endif return FALSE; } BOOLEAN P2PDefaultPortConnected( IN PP2P_INFO pP2PInfo ) { PADAPTER pDefaultAdapter = GetDefaultAdapter(pP2PInfo->pAdapter); return (MgntLinkStatusQuery(pDefaultAdapter) == RT_MEDIA_CONNECT) ? (TRUE) : (FALSE); } BOOLEAN P2PIsSocialChannel( IN u1Byte Channel ) { u1Byte i; for(i = 0; i < sizeof(P2PSocialChannels); i++) { if(P2PSocialChannels[i] == Channel) { return TRUE; } } return FALSE; } BOOLEAN P2PTestU2SingleBitSet( IN u2Byte u2Val ) { u2Byte i = sizeof(u2Byte) * 8; u2Byte j; BOOLEAN bHasBitSet = 0; for(j = 0; j < i; j++) { if(u2Val & 1) { if(bHasBitSet) { return FALSE; } else { bHasBitSet = 1; } } u2Val = u2Val >> 1; } return TRUE; } u1Byte P2PGetChannel( IN PP2P_INFO pP2PInfo ) { return RT_GetChannelNumber(pP2PInfo->pAdapter); } VOID P2PSetChannel( IN PP2P_INFO pP2PInfo, IN u1Byte Channel ) { PADAPTER pAdapter = pP2PInfo->pAdapter; pAdapter->HalFunc.SwChnlByTimerHandler(pAdapter, Channel); } VOID P2PSetRole( IN PP2P_INFO pP2PInfo, IN P2P_ROLE Role ) { pP2PInfo->Role = Role; P2PIndicateCurrentRole(pP2PInfo, Role); } VOID P2PSetOperatingState( IN PP2P_INFO pP2PInfo ) { if(!P2P_ENABLED(pP2PInfo)) { return; } if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery P2PScanListCeaseScan(pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); // P2P State is restored in this function. } pP2PInfo->State = P2P_STATE_OPERATING; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PSetOperatingState()\n")); } VOID P2PStopResumeGOBeaconning( IN PP2P_INFO pP2PInfo, IN BOOLEAN bToStartBeaconning ) { // // Sometimes beacon cant' resume immediately, // so we don't do beacon stop/resume now or WPS // is hare to get succeed. // return; } VOID P2PGetRandomSeries( IN u1Byte MinIndex, IN u1Byte MaxIndex, IN u1Byte nRandomSeriesToGen, OUT pu1Byte SeriesBuf ) { u1Byte Hashed[20]; u1Byte iRdm, interval; u1Byte i; // Input check interval = MaxIndex - MinIndex; if( interval <= 0 ) { RT_ASSERT( FALSE, ("P2PGetRandomSeries(): Invalid Index!\n") ); return; } if(nRandomSeriesToGen > 20) { RT_ASSERT( FALSE, ("P2PGetRandomSeries(): nRandomSeriesToGen shall be less than 20!\n") ); return; } GetRandomBuffer(Hashed); for(i = 0; i < nRandomSeriesToGen; i++) { iRdm = *( (pu1Byte)Hashed + i); // usd first 1 bytes only iRdm = iRdm % interval; // Now iRdm is in [0, interval) iRdm += MinIndex; // Now iRdm is in [MinIndex, MaxIndex) SeriesBuf[i] = iRdm; } return; } BOOLEAN P2PGetRandomChars( IN u1Byte nRandomCharToGen, OUT char* SeriesBuf ) { // // Get random num from upper case letters, lower case letters and numbers. // Total possibility: 26+26+10 = 62 => index from 0 to 61 // //int i = GetRandomNumber(0, 26 + 26 + 10); u1Byte u1RandomArray[20]; u1Byte i, j; if(nRandomCharToGen > 20) { return FALSE; } // // i to random char mapping: // i = 0 to 9 => number // i = 10 to 35 => lower case letter // i = 36 to 61 => upper case letter // P2PGetRandomSeries(0, 26 + 26 + 10, nRandomCharToGen, u1RandomArray); for(j = 0; j < nRandomCharToGen; j++) { char temp; i = u1RandomArray[j]; if(i >= 0 && i <= 9) {// number temp = '0' + (i); } else if(i >= 10 && i <= 35) {// lower case temp = 'a' + (i - 10); } else if(i >= 36 && i <= 61) {// upper case temp = 'A' + (i - 36); } else { return FALSE; } SeriesBuf[j] = temp; } return TRUE; } BOOLEAN P2PDetermineGOSsid( IN PP2P_INFO pP2PInfo, OUT pu1Byte SsidBuf, OUT pu1Byte pSsidLen ) { // // Clause 3.2.1: // Each SSID shall begin with the ASCII characters "TBD-", // where TBD is a short version of the technology name to // be determined by the Marketing TG. This SSID requirement // may enable users of Legacy Clients to differentiate between // a P2P Group and an infrastructure network. // // Following "TBD-" the SSID shall contain two ASCII characters // randomly selected with a unified distribution from the following character set: // upper case letters, lower case letters and numbers. // // This SSID requirement makes the probability low that a Legacy Client // encounters two P2P Groups with the same SSID and mistakenly // attempt to roam between them. // static u1Byte P2PTechName[] = {'D', 'I', 'R','E', 'C', 'T', '-'}; //static u1Byte P2PTechName[] = {'P', '2', 'P', '-'}; char RandomChar[2]; u1Byte index = 0; *pSsidLen = 0; if(RT_STATUS_SUCCESS == P2PSvc_DetermineGOSSID(pP2PInfo->pAdapter, SsidBuf, pSsidLen)) { return TRUE; } if(pP2PInfo->regSSIDLen > 0) { // Note: // This SSID may not include the prefix "DIRECT-" defined in P2P spec, but we do not // limit and let our driver test by other SSIDs. PlatformMoveMemory(SsidBuf, pP2PInfo->regSSIDBuf, pP2PInfo->regSSIDLen); *pSsidLen = pP2PInfo->regSSIDLen; RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2PDetermineGOSsid(): Using Reg SSID = \n", SsidBuf, *pSsidLen) return TRUE; } P2PGetRandomChars(2, RandomChar); // // Copy P2PTechName and the 2 random series // *pSsidLen += (sizeof(P2PTechName) + sizeof(RandomChar)); PlatformMoveMemory(SsidBuf + index, P2PTechName, sizeof(P2PTechName)); index += sizeof(P2PTechName); PlatformMoveMemory(SsidBuf + index, RandomChar, sizeof(RandomChar)); index += sizeof(RandomChar); // // Append SSID Postfix // *pSsidLen += (pP2PInfo->SSIDPostfixLen); PlatformMoveMemory(SsidBuf + index, pP2PInfo->SSIDPostfixBuf, pP2PInfo->SSIDPostfixLen); index += pP2PInfo->SSIDPostfixLen; RT_PRINT_STR(COMP_P2P, DBG_LOUD, "P2PDetermineGOSsid(): Random SSID:\n", SsidBuf, *pSsidLen); return TRUE; } BOOLEAN P2PIsWildcardSsid( IN OCTET_STRING osSsid ) { u1Byte i; if(osSsid.Length != sizeof(P2PWildcardSsid)) { return FALSE; } for(i = 0; i < sizeof(P2PWildcardSsid); i++) { if(osSsid.Octet[i] != P2PWildcardSsid[i]) { return FALSE; } } return TRUE; } BOOLEAN P2PIsChnlInChnlList( IN pu1Byte pChnlList, IN u1Byte ChnlListSize, IN u1Byte Chnl ) { u1Byte i; for(i = 0; i < ChnlListSize; i++) { if(pChnlList[i] == Chnl) { return TRUE; } } return FALSE; } BOOLEAN P2PIsChnlInChnlEntryList( IN P2P_CHANNELS *pChannelEntryList, IN u1Byte Chnl ) { u1Byte i = 0, j = 0; for(i = 0; i < pChannelEntryList->regClasses; i++) { if(pChannelEntryList->regClass[i].channels> 0) { for(j = 0; j < pChannelEntryList->regClass[i].channels; j++) { if(Chnl == pChannelEntryList->regClass[i].channel[j]) { return TRUE; } } } } return FALSE; } BOOLEAN P2PIsDoingGroupFormation( IN PP2P_INFO pP2PInfo ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIsDoingGroupFormation(): state: %u, bPreGroupFormation: %u\n", pP2PInfo->State, pP2PInfo->bPreGroupFormation)); if((pP2PInfo->State >= P2P_STATE_GO_NEGO_REQ_SEND && pP2PInfo->State <= P2P_STATE_GO_NEGO_COMPLETE) || pP2PInfo->bPreGroupFormation) { return TRUE; } return FALSE; } OCTET_STRING P2PWpsIEGetAttribute( IN OCTET_STRING osWpsIEAttributes, IN BOOLEAN bWpsAttributesInBE, IN u2Byte Tag // note that this is BE ) { // // Note that this function accepts osWpsIEAttributes in BE only. // u2Byte offset = 0; u2Byte length = osWpsIEAttributes.Length; OCTET_STRING ret={0, 0}; // used for return u2Byte CurrentTag; u2Byte CurrentLen; BOOLEAN bTagMatched = FALSE; // // Assumed format: // [Tag (2) + Length (2) + Value (n)]* // Return: // OCTET_STRING: {pValue, Length} // Example: get Device Name // P2PWpsIEGetAttribute(osWpsAttributes, 0x1011) // Will return a pointer to "Realtek xxx" and the length of the name // do { if((offset + sizeof(CurrentTag) + sizeof(CurrentLen)) > length) {// can't read Tag and Length return ret; } if(bWpsAttributesInBE) {// BE CurrentTag = N2H2BYTE(*((pu2Byte)(osWpsIEAttributes.Octet + offset))); offset += sizeof(CurrentTag); CurrentLen = N2H2BYTE(*((pu2Byte)(osWpsIEAttributes.Octet + offset))); offset += sizeof(CurrentLen); } else {// LE CurrentTag = ReadEF2Byte((pu2Byte)(osWpsIEAttributes.Octet + offset)); offset += sizeof(CurrentTag); CurrentLen = ReadEF2Byte((pu2Byte)(osWpsIEAttributes.Octet + offset)); offset += sizeof(CurrentLen); } if(CurrentTag == Tag) { bTagMatched = TRUE; } if(bTagMatched && (length >= offset + CurrentLen)) { FillOctetString(ret, osWpsIEAttributes.Octet + offset, CurrentLen); break; } else { offset += CurrentLen; } }while(1); return ret; } BOOLEAN P2PDeviceTypeMatches( IN PP2P_INFO pP2PInfo, IN OCTET_STRING osWpsIE ) { OCTET_STRING ReqType; OCTET_STRING osWpsAttributes; u1Byte nRequestedDeviceTypeChecked = 0; if(osWpsIE.Octet && osWpsIE.Length > 4) { FillOctetString(osWpsAttributes, osWpsIE.Octet + 4, osWpsIE.Length - 4); // offset the OUI (4) } else {// no Requested Device Type to check return TRUE; } do { #if P2P_WPS_ATTR_TRANSMITTED_USING_BE ReqType = P2PWpsIEGetAttribute(osWpsAttributes, TRUE, P2P_WP2_ATTR_TAG_REQUESTED_DEVICE_TYPE); #else ReqType = P2PWpsIEGetAttribute(osWpsAttributes, FALSE, P2P_WP2_ATTR_TAG_REQUESTED_DEVICE_TYPE); #endif if(ReqType.Length == 2 + 4 + 2) // cat id(2) + oui(4) + sub cat id(2) = 8 { u2Byte CatId = P2P_WPS_ATTR_READ_EF_2_BYTE((pu2Byte)(ReqType.Octet)); u2Byte SubCatId = P2P_WPS_ATTR_READ_EF_2_BYTE((pu2Byte)(ReqType.Octet + 2 + 4)); nRequestedDeviceTypeChecked++; // // Check primary device type // if(CatId == pP2PInfo->WpsAttributes.PrimaryDeviceType.CategoryId && SubCatId == pP2PInfo->WpsAttributes.PrimaryDeviceType.SubCategoryId) { return TRUE; } else { // // Check secondary device types // u1Byte i; for(i = 0; i < pP2PInfo->WpsAttributes.SecondaryDeviceTypeLength; i++) { if(CatId == pP2PInfo->WpsAttributes.SecondaryDeviceTypeList[i].CategoryId && SubCatId == pP2PInfo->WpsAttributes.SecondaryDeviceTypeList[i].SubCategoryId) { return TRUE; } } } } }while(FALSE);//while(ReqType.Length > 0); if(nRequestedDeviceTypeChecked > 0) {// not matched return FALSE; } else {// no Requested Device Type to check return TRUE; } } BOOLEAN P2PDeviceIDMatches( IN PP2P_INFO pP2PInfo, IN const P2P_MESSAGE *msg ) { if(msg->_devId) { if(eqMacAddr(msg->devIdDevAddr, pP2PInfo->DeviceAddress)) { return TRUE; } else { RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PDeviceIDMatches(): DeviceID specified not match:\n", msg->devIdDevAddr); return FALSE; } } else { return TRUE; } } RT_STATUS P2P_SetWpsIe( IN const ADAPTER *pAdapter, IN u2Byte iePayloadLen, IN u1Byte *pIePayload ) { RT_STATUS status = RT_STATUS_SUCCESS; P2P_INFO *pP2PInfo = GET_P2P_INFO(pAdapter); FRAME_BUF fbuf; P2P_MESSAGE msg; P2P_WPS_ATTRIBUTES *w = NULL; if(!P2P_ENABLED(pP2PInfo)) return RT_STATUS_INVALID_STATE; // Payload shall contain OUI and subtype, totally 4 bytes if(iePayloadLen < 3 + 1) return RT_STATUS_INVALID_DATA; FrameBuf_Init(iePayloadLen - 4, iePayloadLen - 4, pIePayload + 4, &fbuf); PlatformZeroMemory(&msg, sizeof(msg)); msg.dbgLevel = DBG_LOUD; if(RT_STATUS_SUCCESS != (status = p2p_parse_WpsIe(&fbuf, &msg))) { return status; } w = &pP2PInfo->WpsAttributes; if(msg._wpsConfigMethods) w->ConfigMethod = msg.wpsConfigMethods; if(msg._wpsDevName) { w->DeviceNameLength = (u1Byte)msg.wpsDevNameLen; p2p_MoveMemory(w->DeviceName, msg._wpsDevName, msg.wpsDevNameLen); } if(msg._wpsDevPasswordId) { pP2PInfo->WpsDevPasswdId = msg.wpsDevPasswordId; w->DevicePasswdId = msg.wpsDevPasswordId; // // Notify UI the current device password ID so that it can determine whether provisioning info is available // Note that UI determines which peer config method we shall use for doing WPS // P2PIndicateCurrentDevPasswdId(pP2PInfo, pP2PInfo->WpsDevPasswdId); } if(msg._wpsPrimaryDevType) { u2Byte cat = ReadN2H2BYTE(msg._wpsPrimaryDevType + 0); u2Byte subCat = ReadN2H2BYTE(msg._wpsPrimaryDevType + 6); // We do this check because the WPS module set us a WPS IE with this attribute all 0 if(0 != cat && 0 != subCat) { w->PrimaryDeviceType.CategoryId = cat; p2p_MoveMemory(w->PrimaryDeviceType.Oui, msg._wpsPrimaryDevType + 2, 4); w->PrimaryDeviceType.SubCategoryId = subCat; } } if(msg._wpsSecDevTypeList && msg.wpsSecDevTypeNum) { const u1Byte *pos = msg._wpsSecDevTypeList; const u1Byte *end = msg._wpsSecDevTypeList + msg.wpsSecDevTypeListLen; w->SecondaryDeviceTypeLength = msg.wpsSecDevTypeNum; while(pos < end) { P2P_WPS_ATTRIBUTES_DEVICE_TYPE *s = &w->SecondaryDeviceTypeList[w->SecondaryDeviceTypeLength]; s->CategoryId = ReadN2H2BYTE(pos + 0); p2p_MoveMemory(s->Oui, pos + 2, 4); s->SubCategoryId = ReadN2H2BYTE(pos + 6); pos += 8; } } P2PDumpWpsAttributes(&pP2PInfo->WpsAttributes); return status; } //====================================================================== // Sub IE handlers //====================================================================== BOOLEAN P2POnP2PNoticeOfAbsence( IN PP2P_INFO pP2PInfo, IN OCTET_STRING osPacket, IN P2P_MESSAGE *msg ) { u1Byte ID = P2P_ATTR_NOTICE_OF_ABSENCE; u2Byte Index = 0; u1Byte nNoADesc = 0; u1Byte i; P2P_POWERSAVE_SET p2pPsSet; PMGNT_INFO pMgntInfo = &(pP2PInfo->pAdapter->MgntInfo); // Win8: NdisTest Trick for WFD_Concurrent_ext: ------------------------------ // + SUT-Client -> DUT-GO and DUT-Client -> SUT-GO are in the same channel // + Use TxPause in AP_PS_UpdateStationPSState() instead if(pP2PInfo->pAdapter->bInHctTest) return TRUE; // ---------------------------------------------------------------------- // Our role isn't client. if(pP2PInfo->Role != P2P_CLIENT || !pMgntInfo->mAssoc) return TRUE; // BSSID mismatch // RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2POnP2PNoticeOfAbsence(): BSSID in packet = ", Frame_pBssid(osPacket)); if(!eqMacAddr(Frame_pBssid(osPacket), pP2PInfo->pAdapter->MgntInfo.Bssid)) return TRUE; // // Length check // if((msg->noaLen - 2) % 13 != 0) // Len of a NoA Desc is 13 { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2POnP2PNoticeOfAbsence(): invalid length: %u\n", msg->noaLen)); return FALSE; } else { nNoADesc = (msg->noaLen - 2) / 13; } // The index hasn't changed. if(pP2PInfo->bUpdateFromBeacon && msg->noaIndex == pP2PInfo->NoAIEIndex) return TRUE; pP2PInfo->bUpdateFromBeacon = TRUE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2POnP2PNoticeOfAbsence(): Role = %d, IE index = %d, MyCurIdx = %d\n", pP2PInfo->Role, msg->noaIndex, pP2PInfo->NoAIEIndex)); // CTWindow p2pPsSet.bOppPs = msg->noaCtWindowAndOppPsParam >> 7; p2pPsSet.CTWindow = msg->noaCtWindowAndOppPsParam & (~BIT7); Index = 2; // NoA Descriptors for(i = 0; i < nNoADesc; i++) { // This NoA is valid. p2pPsSet.NoASet[i].bNoAEn = TRUE; // Count/Type p2pPsSet.NoASet[i].NoACnt = ReadEF1Byte(msg->_noa + Index); Index += 1; // Duration p2pPsSet.NoASet[i].NoADur = ReadEF4Byte(msg->_noa + Index); Index += 4; // Interval p2pPsSet.NoASet[i].NoAInt= ReadEF4Byte(msg->_noa + Index); Index += 4; // Start Time p2pPsSet.NoASet[i].bUseStartTime = TRUE; p2pPsSet.NoASet[i].u4StartTime = ReadEF4Byte(msg->_noa + Index); Index += 4; } pP2PInfo->bUpdatePsParameter = TRUE; P2PSetPowerSaveMode(pP2PInfo, &p2pPsSet, msg->noaIndex, FALSE); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("<=======\n")); return TRUE; } //====================================================================== // Dump Routine //====================================================================== VOID P2PDumpWpsAttributes( IN PP2P_WPS_ATTRIBUTES pP2PWpsAttributes ) { u1Byte i; RT_TRACE(COMP_P2P, DBG_LOUD, ("WPS Attributes:\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("Config Method: 0x%X\n", pP2PWpsAttributes->ConfigMethod)); RT_TRACE(COMP_P2P, DBG_LOUD, ("Device Passwd ID: 0x%X\n", pP2PWpsAttributes->DevicePasswdId)); RT_TRACE(COMP_P2P, DBG_LOUD, ("PrimaryDevType: %u\n", pP2PWpsAttributes->PrimaryDeviceType.SubCategoryId)); RT_TRACE(COMP_P2P, DBG_LOUD, ("SecDevType Length: %u\n", pP2PWpsAttributes->SecondaryDeviceTypeLength)); if(pP2PWpsAttributes->SecondaryDeviceTypeLength) { RT_TRACE(COMP_P2P, DBG_LOUD, ("SecDevTypes: \n")); for(i = 0; i < pP2PWpsAttributes->SecondaryDeviceTypeLength; i++) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%u\n", pP2PWpsAttributes->SecondaryDeviceTypeList[i].SubCategoryId)); } } if(pP2PWpsAttributes->DeviceNameLength > 0) { RT_PRINT_STR(COMP_P2P, DBG_LOUD, "DeviceName: ", pP2PWpsAttributes->DeviceName, pP2PWpsAttributes->DeviceNameLength); } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("DeviceName: has a invalid length: %u\n", pP2PWpsAttributes->DeviceNameLength)); } } VOID P2PDumpDeviceCapability( IN u1Byte DeviceCapability ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("=== Device Capability ===\n")); if(DeviceCapability & dcServiceDiscovery) { RT_TRACE(COMP_P2P, DBG_LOUD, ("dcServiceDiscovery\n")); } if(DeviceCapability & dcP2PClientDiscoverability) { RT_TRACE(COMP_P2P, DBG_LOUD, ("dcP2PClientDiscoverability\n")); } if(DeviceCapability & dcConcurrentOperation) { RT_TRACE(COMP_P2P, DBG_LOUD, ("dcConcurrentOperation\n")); } if(DeviceCapability & dcP2PInfrastructureManaged) { RT_TRACE(COMP_P2P, DBG_LOUD, ("dcP2PInfrastructureManaged\n")); } if(DeviceCapability & dcP2PDeviceLimit) { RT_TRACE(COMP_P2P, DBG_LOUD, ("dcP2PDeviceLimit\n")); } if(DeviceCapability & dcP2PInvitationProcedure) { RT_TRACE(COMP_P2P, DBG_LOUD, ("dcP2PInvitationProcedure\n")); } } VOID P2PDumpGroupCapability( IN u1Byte GroupCapability ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("=== Group Capability ===\n")); if(GroupCapability & gcP2PGroupOwner) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcP2PGroupOwner\n")); } if(GroupCapability & gcPersistentP2PGroup) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcPersistentP2PGroup\n")); } if(GroupCapability & gcP2PGroupLimit) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcP2PGroupLimit\n")); } if(GroupCapability & gcIntraBSSDistribution) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcIntraBSSDistribution\n")); } if(GroupCapability & gcCrossConnection) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcCrossConnection\n")); } if(GroupCapability & gcPersistentReconnect) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcPersistentReconnect\n")); } if(GroupCapability & gcGroupFormation) { RT_TRACE(COMP_P2P, DBG_LOUD, ("gcGroupFormation\n")); } } VOID P2PDumpClientInfoDescList( IN PP2P_CLIENT_INFO_DISCRIPTOR P2PClientInfoDescList, IN u1Byte P2PClientInfoDescListSize ) { u1Byte i; for(i = 0; i < P2PClientInfoDescListSize; i++) { RT_TRACE(COMP_P2P, DBG_LOUD, ("=== Client %d ===\n", i)); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "DevAddr: ", P2PClientInfoDescList[i].DeviceAddress); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "InterfaceAddr: ", P2PClientInfoDescList[i].InterfaceAddress); P2PDumpDeviceCapability(P2PClientInfoDescList[i].DeviceCapability); P2PDumpWpsAttributes(&(P2PClientInfoDescList[i].WpsAttributes)); } RT_TRACE(COMP_P2P, DBG_LOUD, ("Totally %d Clients dumped\n", i)); } VOID P2PDumpScanList( IN PP2P_DEVICE_DISCRIPTOR pDevDescriptors, IN u4Byte nDevDescriptors ) { u4Byte i; for(i = 0; i < nDevDescriptors; i++) { RT_TRACE(COMP_P2P, DBG_LOUD, ("====================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("Scan List: %u\n", i)); RT_TRACE(COMP_P2P, DBG_LOUD, ("====================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("Role: %u\n", pDevDescriptors[i].Role)); P2PDumpGroupCapability(pDevDescriptors[i].GroupCapability); P2PDumpDeviceCapability(pDevDescriptors[i].DeviceCapability); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "DevAddr: ", pDevDescriptors[i].DeviceAddress); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "IntAddr: ", pDevDescriptors[i].IntendedP2PInterfaceAddress); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "SSID: ", pDevDescriptors[i].SsidBuf, pDevDescriptors[i].SsidLen); RT_TRACE(COMP_P2P, DBG_LOUD, ("ListenChnl: %u\n", pDevDescriptors[i].ListenChannel)); RT_TRACE(COMP_P2P, DBG_LOUD, ("OpChnl: %u\n", pDevDescriptors[i].OperatingChannel)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "Channel List:\n", pDevDescriptors[i].ChannelPlanChannel, pDevDescriptors[i].ChannelPlanLength); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "UUID:\n", pDevDescriptors[i].WPS_UUID, 16); P2PDumpWpsAttributes(&(pDevDescriptors[i].WpsAttributes)); RT_TRACE(COMP_P2P, DBG_LOUD, ("Num of Clients: %x\n", pDevDescriptors[i].P2PClientDescriptorListLength)); P2PDumpClientInfoDescList(pDevDescriptors[i].P2PClientDescriptorList, pDevDescriptors[i].P2PClientDescriptorListLength); RT_TRACE(COMP_P2P, DBG_LOUD, ("ExtListenTimingPeriod: %u\n", pDevDescriptors[i].ExtendedListenTimingPeriod)); RT_TRACE(COMP_P2P, DBG_LOUD, ("ExtListenTimingDuration: %u\n", pDevDescriptors[i].ExtendedListenTimingDuration)); RT_TRACE(COMP_P2P, DBG_LOUD, ("SingalStrength: %d\n", pDevDescriptors[i].SignalStrength)); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "Manufacturer name: ", pDevDescriptors->manufacturerName, 65); } RT_TRACE(COMP_P2P, DBG_LOUD, ("====================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("Totally %d items in Scan List dumped\n", i)); RT_TRACE(COMP_P2P, DBG_LOUD, ("====================================\n")); } VOID P2PDumpGroupFormationResult( PP2P_INFO pP2PInfo ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("====================================\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("Group Formation Result:\n")); RT_TRACE(COMP_P2P, DBG_LOUD, ("====================================\n")); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "DevAddr: ", pP2PInfo->ConnectionContext.ConnectingDevice.DeviceAddress); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "IntAddr: ", pP2PInfo->ConnectionContext.ConnectingDevice.IntendedP2PInterfaceAddress); if(pP2PInfo->ConnectionContext.bGoingToBeGO) { RT_TRACE(COMP_P2P, DBG_LOUD, ("I'm GO\n")); } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("I'm Client\n")); } RT_TRACE(COMP_P2P, DBG_LOUD, ("OpChnl: %u\n", pP2PInfo->OperatingChannel)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "Channel List:\n", pP2PInfo->ConnectionContext.ConnectingDevice.ChannelPlanChannel, pP2PInfo->ConnectionContext.ConnectingDevice.ChannelPlanLength); RT_TRACE(COMP_P2P, DBG_LOUD, ("Status: %u\n", pP2PInfo->ConnectionContext.Status)); RT_TRACE(COMP_P2P, DBG_LOUD, ("DialogToken: %u\n", pP2PInfo->ConnectionContext.DialogToken)); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "SSID = ", pP2PInfo->ConnectionContext.ConnectingDevice.SsidBuf, pP2PInfo->ConnectionContext.ConnectingDevice.SsidLen); } VOID P2PDumpPacketType( u1Byte TypeSubType, u1Byte Category, u1Byte OUISubType ) { switch(TypeSubType) { case Type_Beacon: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Beacon\n")); break; case Type_Probe_Req: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Probe_Req\n")); break; case Type_Probe_Rsp: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Probe_Rsp\n")); break; case Type_Asoc_Req: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Asoc_Req\n")); break; case Type_Asoc_Rsp: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Asoc_Rsp\n")); break; case Type_Reasoc_Req: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Reasoc_Req\n")); break; case Type_Reasoc_Rsp: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): Type_Reasoc_Rsp\n")); break; case Type_Action: { if(Category == WLAN_ACTION_PUBLIC) { if(OUISubType == P2P_PUB_ACT_GO_NEGO_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): GONReq\n")); if(OUISubType == P2P_PUB_ACT_GO_NEGO_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): GONRsp\n")); if(OUISubType == P2P_PUB_ACT_GO_NEGO_CONFIRM) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): GONConfirm\n")); if(OUISubType == P2P_PUB_ACT_INVITATION_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): InvitationReq\n")); if(OUISubType == P2P_PUB_ACT_INVITATION_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): InvitationRsp\n")); if(OUISubType == P2P_PUB_ACT_DEV_DISCOVERABILITY_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): DevDiscoverabilityReq\n")); if(OUISubType == P2P_PUB_ACT_DEV_DISCOVERABILITY_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): DevDiscoverabilityRsp\n")); if(OUISubType == P2P_PUB_ACT_PROVISION_DISCOVERY_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): ProvisionDiscoveryReq\n")); if(OUISubType == P2P_PUB_ACT_PROVISION_DISCOVERY_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): ProvisionDiscoveryRsp\n")); if(OUISubType == P2P_PUB_ACT_GAS_INITIAL_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): ServiceDiscoveryReq (GAS Initial Req)\n")); if(OUISubType == P2P_PUB_ACT_GAS_INITIAL_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): ServiceDiscoveryRsp (GAS Initial Rsp)\n")); if(OUISubType == P2P_PUB_ACT_GAS_COMEBACK_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): ServiceDiscoveryReq (GAS Comeback Req)\n")); if(OUISubType == P2P_PUB_ACT_GAS_COMEBACK_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): ServiceDiscoveryRsp (GAS Comeback Rsp)\n")); } else if(Category == WLAN_ACTION_VENDOR_SPECIFIC) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): TODO: P2P_ACTION_CATEGORY\n")); if(OUISubType == P2P_ACT_NOTICE_OF_ABSENCE) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): NoticeOfAbsence\n")); if(OUISubType == P2P_PUB_PRESENCE_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): PresenceReq\n")); if(OUISubType == P2P_PUB_PRESENCE_RSP) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): PresenceRsp\n")); if(OUISubType == P2P_PUB_GO_DISCOVERABILITY_REQ) RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): GODiscoverabilityReq\n")); } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): unrecognized Action Category: %u\n", Category)); } } break; default: RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDumpPacketType(): unrecognized TypeSubType: %u\n", TypeSubType)); break; } } //====================================================================== // Client Info List Hander //====================================================================== u1Byte P2PClientInfoGetCount( IN PP2P_INFO pP2PInfo ) { PADAPTER pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetFirstGOPort(pP2PInfo->pAdapter); PMGNT_INFO pExtMgntInfo = &pExtAdapter->MgntInfo; PRT_WLAN_STA pEntry = NULL; u1Byte nP2PClients = 0; u1Byte i = 0; if(pExtAdapter == NULL || pExtMgntInfo == NULL) { return 0; } for(i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { pEntry = &(pExtMgntInfo->AsocEntry[i]); if(pEntry->bUsed && pEntry->bAssociated && pEntry->bP2PClient) { nP2PClients++; } } return nP2PClients; } PP2P_CLIENT_INFO_DISCRIPTOR P2PClientInfoFindByInterfaceAddress( IN PP2P_INFO pP2PInfo, IN pu1Byte InterfaceAddress ) { BOOLEAN bFound = FALSE; PADAPTER pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetFirstGOPort(pP2PInfo->pAdapter); PMGNT_INFO pExtMgntInfo = &pExtAdapter->MgntInfo; PRT_WLAN_STA pEntry = NULL; u1Byte i = 0; if(pExtAdapter == NULL || pExtMgntInfo == NULL) { return 0; } for(i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { pEntry = &(pExtMgntInfo->AsocEntry[i]); if(pEntry->bUsed && pEntry->bAssociated && pEntry->bP2PClient) { if(eqMacAddr(pEntry->P2PClientInfoDesc.InterfaceAddress, InterfaceAddress)) { bFound = TRUE; return &(pEntry->P2PClientInfoDesc); } } } return NULL; } PP2P_CLIENT_INFO_DISCRIPTOR P2PClientInfoFindByDeviceAddress( IN PP2P_INFO pP2PInfo, IN pu1Byte DeviceAddress ) { BOOLEAN bFound = FALSE; PADAPTER pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetFirstGOPort(pP2PInfo->pAdapter); PMGNT_INFO pExtMgntInfo = &pExtAdapter->MgntInfo; PRT_WLAN_STA pEntry = NULL; u1Byte i = 0; if(pExtAdapter == NULL || pExtMgntInfo == NULL) { return 0; } for(i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { pEntry = &(pExtMgntInfo->AsocEntry[i]); if(pEntry->bUsed && pEntry->bAssociated && pEntry->bP2PClient) { if(eqMacAddr(pEntry->P2PClientInfoDesc.DeviceAddress, DeviceAddress)) { bFound = TRUE; return &(pEntry->P2PClientInfoDesc); } } } return NULL; } PP2P_CLIENT_INFO_DISCRIPTOR P2PClientInfoEnumClients( IN PP2P_INFO pP2PInfo, IN u1Byte StartIndex, OUT pu1Byte pIndex ) { BOOLEAN bFound = FALSE; PADAPTER pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetFirstGOPort(pP2PInfo->pAdapter); PMGNT_INFO pExtMgntInfo = &pExtAdapter->MgntInfo; PRT_WLAN_STA pEntry = NULL; u1Byte i = 0; if(StartIndex > ASSOCIATE_ENTRY_NUM - 1) { goto exit_P2PClientInfoEnumClients; } if(pExtAdapter == NULL || pExtMgntInfo == NULL) { return 0; } for(i = StartIndex; i < ASSOCIATE_ENTRY_NUM; i++) { pEntry = &(pExtMgntInfo->AsocEntry[i]); if(pEntry->bUsed && pEntry->bAssociated && pEntry->bP2PClient) { bFound = TRUE; if(pIndex) *pIndex = i; return &(pEntry->P2PClientInfoDesc); } } exit_P2PClientInfoEnumClients: if(pIndex) *pIndex = (u1Byte)(-1); return NULL; } //====================================================================== // Scan List Hander //====================================================================== PP2P_DEVICE_DISCRIPTOR P2PScanListFind( IN PP2P_DEVICE_DISCRIPTOR pScanList, IN u4Byte ScanListSize, IN pu1Byte DeviceAddress, IN pu1Byte InterfaceAddress, OUT pu4Byte pScanListIndex ) { u4Byte i; BOOLEAN bFound = FALSE; pu1Byte KeyAddr = (DeviceAddress) ? (DeviceAddress) : ((InterfaceAddress) ? (InterfaceAddress) : (NULL)); BOOLEAN bDevAddressAsKey = (DeviceAddress) ? (TRUE) : (FALSE); if(!KeyAddr) { return NULL; } for(i = 0; i < ScanListSize; i++) { pu1Byte AddrToCompare = (bDevAddressAsKey) ? ((pScanList[i]).DeviceAddress) : ((pScanList[i]).IntendedP2PInterfaceAddress); if(eqMacAddr(AddrToCompare, KeyAddr)) { bFound = TRUE; if(pScanListIndex) { *pScanListIndex = i; } return &(pScanList[i]); } } return NULL; } BOOLEAN P2PScanListAllFound( IN PP2P_INFO pP2PInfo ) { ULONG i = 0; u1Byte j = 0, uNumOfDevicesFound = 0; BOOLEAN bAllFound = FALSE; if(pP2PInfo->ScanDeviceIDs.uNumOfDeviceIDs == 0 ||pP2PInfo->DeviceListForQuery.uNumberOfDevices ==0) return FALSE; for(i=0;i<(pP2PInfo->ScanDeviceIDs.uNumOfDeviceIDs);i++)// { for(j = 0; j < (pP2PInfo->DeviceListForQuery.uNumberOfDevices); j++) { if(pP2PInfo->DeviceListForQuery.DeviceEntry[j].DeviceAddress != NULL) { if(eqMacAddr(pP2PInfo->ScanDeviceIDs.DeviceIDs[i], pP2PInfo->DeviceListForQuery.DeviceEntry[j].DeviceAddress) &&pP2PInfo->DeviceListForQuery.DeviceEntry[j].ProbeResponseHostTimestamp != 0) { uNumOfDevicesFound ++; } } } } if(uNumOfDevicesFound == pP2PInfo->ScanDeviceIDs.uNumOfDeviceIDs) { bAllFound =TRUE; RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: All of DeviceID Found : Terminate Device Discovery!! !\n", __FUNCTION__)); } return bAllFound; } BOOLEAN P2PScanListFindClient( IN PP2P_DEVICE_DISCRIPTOR pScanList, IN u4Byte ScanListSize, IN pu1Byte DeviceAddress, IN pu1Byte InterfaceAddress, OUT PP2P_DEVICE_DISCRIPTOR *ppGODeviceDesc, OUT PP2P_CLIENT_INFO_DISCRIPTOR *ppClientInfoDesc ) { u4Byte i; u1Byte j; BOOLEAN bFound = FALSE; pu1Byte KeyAddr = (DeviceAddress) ? (DeviceAddress) : ((InterfaceAddress) ? (InterfaceAddress) : (NULL)); BOOLEAN bDevAddressAsKey = (DeviceAddress) ? (TRUE) : (FALSE); *ppGODeviceDesc = NULL; *ppClientInfoDesc = NULL; for(i = 0; i < ScanListSize; i++) { PP2P_CLIENT_INFO_DISCRIPTOR pClientInfo = pScanList[i].P2PClientDescriptorList; u1Byte P2PClientDescriptorListLength = pScanList[i].P2PClientDescriptorListLength; for(j = 0; j < P2PClientDescriptorListLength; j++) { pu1Byte AddrToCompare = (bDevAddressAsKey) ? ((pClientInfo[j]).DeviceAddress) : ((pClientInfo[j]).InterfaceAddress); if(KeyAddr != NULL && eqMacAddr(AddrToCompare, KeyAddr)) { bFound = TRUE; *ppGODeviceDesc = (PP2P_DEVICE_DISCRIPTOR)(&(pScanList[i])); *ppClientInfoDesc = (PP2P_CLIENT_INFO_DISCRIPTOR)(&(pClientInfo[j])); goto exit_P2PScanListFindClient; } } } exit_P2PScanListFindClient: return bFound; } PP2P_DEVICE_DISCRIPTOR P2PScanListAdd( IN OUT PP2P_DEVICE_DISCRIPTOR pScanList, IN OUT pu4Byte pScanListSize ) { PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; if(*pScanListSize == P2P_MAX_SCAN_LIST) {// no more space => return the last one pP2PDeviceDesc = &(pScanList[*pScanListSize - 1]); } else { pP2PDeviceDesc = &(pScanList[*pScanListSize]); (*pScanListSize)++; } return pP2PDeviceDesc; } VOID P2PScanListClear( IN P2P_INFO *pP2PInfo ) { pP2PInfo->ScanListSize = 0; PlatformZeroMemory(pP2PInfo->ScanList, sizeof(pP2PInfo->ScanList)); pP2PInfo->ScanList4QuerySize = 0; PlatformZeroMemory(pP2PInfo->ScanList4Query, sizeof(pP2PInfo->ScanList4Query)); p2p_DevList_Flush(&pP2PInfo->devList); return; } VOID P2PScanListCopy( IN OUT PP2P_DEVICE_DISCRIPTOR pScanListDest, IN OUT pu4Byte pScanListDestSize, IN PP2P_DEVICE_DISCRIPTOR pScanListSrc, IN u4Byte ScanListSrcSize ) { *pScanListDestSize = ScanListSrcSize; PlatformMoveMemory(pScanListDest, pScanListSrc, (ScanListSrcSize * sizeof(P2P_DEVICE_DISCRIPTOR))); } BOOLEAN P2PScanListDumplicate( IN PP2P_DEVICE_DISCRIPTOR pScanList, IN u4Byte ScanListSize, IN PP2P_DEVICE_DISCRIPTOR pDevDesc ) { // // Test if pDevDesc is a duplicate item in pScanList. // PP2P_DEVICE_DISCRIPTOR pTmpDevDesc = NULL; pTmpDevDesc = P2PScanListFind(pScanList, ScanListSize, pDevDesc->DeviceAddress, NULL, NULL); if(pTmpDevDesc) { if(PlatformCompareMemory(pTmpDevDesc, pDevDesc, sizeof(P2P_DEVICE_DISCRIPTOR)) == 0) {// desc the same return TRUE; } else {// dese not the same return FALSE; } } else {// no desc found return FALSE; } return FALSE; } BOOLEAN P2PScanListEqual( IN PP2P_DEVICE_DISCRIPTOR pScanList1, IN u4Byte ScanList1Size, IN PP2P_DEVICE_DISCRIPTOR pScanList2, IN u4Byte ScanList2Size ) { u4Byte i; //RT_TRACE(COMP_P2P, DBG_LOUD, // ("P2PScanListEqual(): nlist1(%u), nlist2(%u)\n", ScanList1Size, ScanList2Size)); if(ScanList1Size != ScanList2Size) { return FALSE; } // // For each entry in scan list 1, check if the entry is duplicate in scan list 2, // if all entries are duplicate, return TRUE; // for(i = 0; i < ScanList1Size; i++) { if(!P2PScanListDumplicate(pScanList2, ScanList2Size, &(pScanList1[i]))) { return FALSE; // this entry is not duplicate } } return TRUE; // all entries are duplicate } BOOLEAN P2PScanListIsGo( IN PP2P_INFO pP2PInfo, IN pu1Byte InterfaceAddr ) { PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; pP2PDeviceDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, NULL, InterfaceAddr, NULL); if(pP2PDeviceDesc) { if(pP2PDeviceDesc->Role == P2P_GO) { return TRUE; } } return FALSE; } VOID P2PScanListEnterScanCompleteImmediately( IN PP2P_INFO pP2PInfo ) { PADAPTER pAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetDefaultAdapter(pP2PInfo->pAdapter); PADAPTER pLoopAdapter = GetDefaultAdapter(pAdapter); PRT_CHANNEL_INFO pChnlInfo; PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo; if(!MgntScanInProgress(pMgntInfo)) { return; } { while(pLoopAdapter) { pMgntInfo = &pLoopAdapter->MgntInfo; pChnlInfo = pMgntInfo->pChannelInfo; if(pChnlInfo->ChnlOp == CHNLOP_SCAN) break; else pLoopAdapter = GetNextExtAdapter(pLoopAdapter); } } if(pLoopAdapter == NULL) { pLoopAdapter = pAdapter; pMgntInfo = &pLoopAdapter->MgntInfo; } if(pMgntInfo->ScanStep != 2) { pMgntInfo->ScanStep = 0; } PlatformCancelTimer(pLoopAdapter, &(pMgntInfo->ScanTimer)); PlatformSetTimer(pLoopAdapter, &(pMgntInfo->ScanTimer), 0); } // // This function is called to cease the current scan. // The purpose is to stop the current scan to stay on the current channel for sending/receiving frames. // If called in operating state, the current channel (op channel) shall be preserved. // u1Byte P2PScanListCeaseScan( IN PP2P_INFO pP2PInfo ) { u1Byte CurrentChnl; PADAPTER pAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetDefaultAdapter(pP2PInfo->pAdapter); EXTCHNL_OFFSET hwBW40MOffset = EXTCHNL_OFFSET_NO_EXT; EXTCHNL_OFFSET hwBW80MOffset = EXTCHNL_OFFSET_NO_EXT; // Get current channel. We want to know on what channel we cease the scan. CurrentChnl = P2PGetChannel(pP2PInfo); pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_BW40MHZ_EXTCHNL, (pu1Byte)(&hwBW40MOffset)); pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_BW80MHZ_EXTCHNL, (pu1Byte)(&hwBW80MOffset)); if(!pAdapter->MgntInfo.bScanInProgress) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PScanListCeaseScan(): bScanInProgress is false\n")); return CurrentChnl; } RT_TRACE(COMP_SCAN,DBG_LOUD, ("===>P2PScanListCeaseScan portnumber %d\n", pAdapter->pNdis62Common->PortNumber)); if(pP2PInfo->bPreGroupFormation || (pP2PInfo->State == P2P_STATE_GO_NEGO_REQ_RECVD)) { PADAPTER pLoopAdapter = GetDefaultAdapter(pAdapter); CustomScan_TermReq(GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter), TRUE); while(pLoopAdapter) { pLoopAdapter->MgntInfo.SettingBeforeScan.Ext20MHzChnlOffsetOf40MHz = hwBW40MOffset; if(EXTCHNL_OFFSET_NO_EXT != hwBW80MOffset) { pLoopAdapter->MgntInfo.SettingBeforeScan.ChannelBandwidth = CHANNEL_WIDTH_80; } else if(EXTCHNL_OFFSET_NO_EXT != hwBW40MOffset) { pLoopAdapter->MgntInfo.SettingBeforeScan.ChannelBandwidth = CHANNEL_WIDTH_40; } else { pLoopAdapter->MgntInfo.SettingBeforeScan.ChannelBandwidth = CHANNEL_WIDTH_20; } pLoopAdapter->MgntInfo.SettingBeforeScan.ChannelNumber = CurrentChnl; pLoopAdapter->MgntInfo.SettingBeforeScan.CenterFrequencyIndex1 = CurrentChnl; pLoopAdapter = GetNextExtAdapter(pLoopAdapter); } } else { CustomScan_TermReq(GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter), FALSE); } //Cancel current scan timer, which may be triggered after a long time // and set it again with no delay so that it will enter ScanComplete soon. //P2PScanListEnterScanCompleteImmediately(pP2PInfo); // // Extended listening may be ceased, so we have to clear the flag. // pP2PInfo->bExtendedListening = FALSE; pP2PInfo->bDeviceDiscoveryInProgress = FALSE; RT_TRACE(COMP_P2P, DBG_LOUD, ("<===P2PScanListCeaseScan()\n")); return CurrentChnl; } static VOID p2p_ScanStateCb( IN CUSTOM_SCAN_STATE state, IN VOID *pCtx ) { ADAPTER *pAdapter = (ADAPTER *)pCtx; if(CUSTOM_SCAN_STATE_COMPLETED == state) { P2P_UpdateScanList(pAdapter); } return; } BOOLEAN P2PConstructScanList( IN P2P_INFO *pP2PInfo, IN VOID *req, IN u1Byte rate, IN FRAME_BUF *probeReqBuf ) { RT_SCAN_TYPE scanType = SCAN_PASSIVE; u2Byte duration = 0; // Scan period if(pP2PInfo->State == P2P_STATE_LISTEN) { scanType = SCAN_PASSIVE; if( pP2PInfo->bPreGroupFormation || pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery || pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe || pP2PInfo->SDContext.bDoingServiceDiscovery ) { duration = 50; } else { duration = (u2Byte)(100 * GetRandomNumber(1, 3 + 1) - 50); } } else if(pP2PInfo->State == P2P_STATE_INITIALIZED) // Extended Listen { if(pP2PInfo->bSendProbeReqInExtendedListen) { scanType = SCAN_ACTIVE; } else { scanType = SCAN_PASSIVE; } duration = pP2PInfo->ExtListenTimingDuration; //*pDuration = (pP2PInfo->ExtListenTimingDuration / 2) * ListenStateDurationMultiplier; RT_TRACE(COMP_P2P, DBG_TRACE, ("Extended Listening Duration: %u\n", duration)); } else if(pP2PInfo->State == P2P_STATE_SEARCH) { scanType = SCAN_ACTIVE; duration = 20; // P2P_SCAN_PERIOD_SEARCH; } else if(pP2PInfo->State == P2P_STATE_SCAN) { if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { scanType = pP2PInfo->ScanType; duration = 50; } else { scanType = SCAN_ACTIVE; duration = 50; } } else if(pP2PInfo->State == P2P_STATE_INVITATION_REQ_SEND) { scanType = SCAN_ACTIVE; duration = P2P_INVITATION_FRAME_TIMEOUT; } else if(pP2PInfo->State == P2P_STATE_PROVISION_DISCOVERY_REQ_SEND) { scanType = SCAN_ACTIVE; duration = P2P_PROVISION_DISCOVERY_TIMEOUT; } else if(pP2PInfo->State == P2P_STATE_SERVICE_DISCOVERY_REQ_SEND) { scanType = SCAN_ACTIVE; duration = P2P_SERVICE_DISCOVERY_TIMEOUT; } else if(pP2PInfo->State == P2P_STATE_DEVICE_DISCOVERABILITY_REQ_SEND) { scanType = SCAN_ACTIVE; duration = P2P_DEVICE_DISCOVERABILITY_FRAME_TIMEOUT; } else { return FALSE; } // Decide channels to scan if(pP2PInfo->State == P2P_STATE_LISTEN || pP2PInfo->State == P2P_STATE_INITIALIZED) // Extended Listen {// the listen channel CustomScan_AddScanChnl(req, pP2PInfo->ListenChannel, 1, scanType, duration, rate, probeReqBuf); } else if(pP2PInfo->State == P2P_STATE_SCAN) { // TODO: is this right? u1Byte i = 0; PRT_CHANNEL_LIST pChList = MgntActQuery_ChannelList(pP2PInfo->pAdapter); u2Byte SupportedWirelessMode = pP2PInfo->pAdapter->HalFunc.GetSupportedWirelessModeHandler(pP2PInfo->pAdapter); WIRELESS_MODE CurrentWirelessModeBackup = pP2PInfo->pAdapter->MgntInfo.dot11CurrentWirelessMode; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2P_STATE_SCAN: pChList->ChannelLen: %d\n", pChList->ChannelLen)); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2P_STATE_SCAN: SupportedWirelessMode: 0x%x CurrentWirelessMode 0x%x\n", SupportedWirelessMode, CurrentWirelessModeBackup)); pP2PInfo->pAdapter->MgntInfo.dot11CurrentWirelessMode = SupportedWirelessMode; RtActChannelList(pP2PInfo->pAdapter, RT_CHNL_LIST_ACTION_CONSTRUCT, NULL, NULL); RtActChannelList(pP2PInfo->pAdapter, RT_CHNL_LIST_ACTION_GET_CHANNEL_LIST, NULL, &pChList); pP2PInfo->pAdapter->MgntInfo.dot11CurrentWirelessMode = CurrentWirelessModeBackup; // Instert the Listen Channel (Listen channel first due to fast discovery of NdisTest-WFD_discover_ext) CustomScan_AddScanChnl(req, pP2PInfo->ListenChannel, 1, scanType, duration, rate, probeReqBuf); for(i = 0; i < pChList->ChannelLen; i++) { if(pChList->ChnlListEntry[i].ChannelNum != pP2PInfo->ListenChannel) { CustomScan_AddScanChnl(req, pChList->ChnlListEntry[i].ChannelNum, 1, scanType, duration, rate, probeReqBuf); } } } else if(pP2PInfo->State == P2P_STATE_INVITATION_REQ_SEND) { PP2P_DEVICE_DISCRIPTOR pDevDesc = &pP2PInfo->InvitationContext.InvitedDevice; if(pDevDesc->Role == P2P_DEVICE) {// GO/Client inviting a Dev, Instert current channel since we start to send InvitationReq upon ProbeReq or ProbeRsp is received from the Dev if(0 != pP2PInfo->InvitationContext.Channel) { CustomScan_AddScanChnl(req, pP2PInfo->InvitationContext.Channel, 1, scanType, duration, rate, probeReqBuf); } else { CustomScan_AddScanChnl(req, 1, 1, scanType, duration, rate, probeReqBuf); CustomScan_AddScanChnl(req, 6, 1, scanType, duration, rate, probeReqBuf); CustomScan_AddScanChnl(req, 11, 1, scanType, duration, rate, probeReqBuf); CustomScan_AddScanChnl(req, pP2PInfo->ListenChannel, 1, scanType, duration, rate, probeReqBuf); } } else if(pDevDesc->Role == P2P_CLIENT) {// Instert peer Op Channel CustomScan_AddScanChnl(req, pDevDesc->OperatingChannel, 1, scanType, duration, rate, probeReqBuf); } else if(pDevDesc->Role == P2P_GO) {// Instert peer Op Channel CustomScan_AddScanChnl(req, pDevDesc->OperatingChannel, 1, scanType, duration, rate, probeReqBuf); } } else if(pP2PInfo->State == P2P_STATE_PROVISION_DISCOVERY_REQ_SEND) { CustomScan_AddScanChnl(req, pP2PInfo->ProvisionDiscoveryContext.Channel, 1, scanType, duration, rate, probeReqBuf); } else if(pP2PInfo->State == P2P_STATE_SERVICE_DISCOVERY_REQ_SEND) { CustomScan_AddScanChnl(req, pP2PInfo->SDContext.Channel, 1, scanType, duration, rate, probeReqBuf); } else if(pP2PInfo->State == P2P_STATE_DEVICE_DISCOVERABILITY_REQ_SEND) { CustomScan_AddScanChnl(req, pP2PInfo->DeviceDiscoverabilityContext.GOChannel, 1, scanType, duration, rate, probeReqBuf); } else //P2P_STATE_SEARCH { // // If Device Discovery is used for finding when the target is active on its listen channel, // we can search only its listen channel to perserve time. // if(pP2PInfo->bPreGroupFormation) {//DbgPrint("a: %u, %u\n", pP2PInfo->ConnectionContext.ConnectingDevice.Channel, *pNChannels); CustomScan_AddScanChnl(req, pP2PInfo->ConnectionContext.ConnectingDevice.ListenChannel, 5, scanType, duration, rate, probeReqBuf); } else if(pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery) { CustomScan_AddScanChnl(req, pP2PInfo->ProvisionDiscoveryContext.Channel, 5, scanType, duration, rate, probeReqBuf); } else if(pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe && pP2PInfo->InvitationContext.InvitedDevice.ListenChannel != 0) { CustomScan_AddScanChnl(req, pP2PInfo->InvitationContext.InvitedDevice.ListenChannel, 5, scanType, duration, rate, probeReqBuf); } else if(pP2PInfo->SDContext.bDoingServiceDiscovery) { CustomScan_AddScanChnl(req, pP2PInfo->SDContext.Channel, 5, scanType, duration, rate, probeReqBuf); } else {// scan all social channels CustomScan_AddScanChnl(req, 1, 5, scanType, duration, rate, probeReqBuf); CustomScan_AddScanChnl(req, 6, 5, scanType, duration, rate, probeReqBuf); CustomScan_AddScanChnl(req, 11, 5, scanType, duration, rate, probeReqBuf); if( GetDefaultMgntInfo(pP2PInfo->pAdapter)->WFDPeerOpChannel > 0 ) { CustomScan_AddScanChnl(req, GetDefaultMgntInfo(pP2PInfo->pAdapter)->WFDPeerOpChannel, 2, scanType, duration, rate, probeReqBuf); } } } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("LsnCh: %u, OpCh: %u\n", pP2PInfo->ListenChannel, pP2PInfo->OperatingChannel)); if(!CustomScan_NumAddedChnl(req)) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("Error: no channel in the list, state: %u\n", pP2PInfo->State)); return FALSE; } else { CustomScan_SetupCbCtx(req, p2p_ScanStateCb, pP2PInfo->pAdapter); return TRUE; } } //====================================================================== // Wi-Fi Direct Packet Handler //====================================================================== PP2P_DEVICE_DISCRIPTOR P2PProcessSubElements( IN PP2P_INFO pP2PInfo, IN PRT_RFD pRfd, IN pu1Byte DeviceAddress, IN P2P_MESSAGE *msg, IN BOOLEAN bCreateIfNotExist ) { P2P_DEVICE_DISCRIPTOR *pDesc = NULL; if(NULL == (pDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, DeviceAddress, NULL, NULL))) { if(!bCreateIfNotExist) return NULL; if(NULL == (pDesc = P2PScanListAdd(pP2PInfo->ScanList, &pP2PInfo->ScanListSize))) return NULL; PlatformZeroMemory(pDesc, sizeof(*pDesc)); } p2p_parse_UpdateDevDesc(pRfd->Buffer.VirtualAddress, msg, pRfd->Status.SignalStrength, pDesc); return pDesc; } VOID p2pUpdateBssDescManageability( IN ADAPTER *pAdapter, IN u1Byte *bssid, IN const P2P_MESSAGE *msg ) { if(msg->_manageability) { PRT_WLAN_BSS pBssDesc = BssDescDupByBssid(pAdapter, bssid); if(pBssDesc) { pBssDesc->P2PManagedInfo = msg->manageability; } } else { RT_TRACE_F(COMP_P2P, DBG_TRACE, ("Managed P2P Device Info NULL\n")); } return; } // // Description: // Handle Beacon packet for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // This function updates the P2P scan list and check the WPS state for join. // RT_STATUS P2P_OnBeacon( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; OCTET_STRING ssidBeacon; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; MEMORY_BUFFER mb = {NULL, 0}; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PInfo->bForceScanLegacyNetworks) { ssidBeacon = PacketGetElement(*posMpdu, EID_SsId, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE); if(IsSSIDNdisTest(ssidBeacon) || !pAdapter->bInHctTest) { MEMORY_BUFFER mbPacket = {NULL, 0}; mbPacket.Buffer = posMpdu->Octet; mbPacket.Length = posMpdu->Length; RT_PRINT_STR(COMP_P2P, DBG_LOUD, "P2P_OnBeacon IsSSIDNdisTest:", ssidBeacon.Octet, ssidBeacon.Length); P2PDeviceListUpdate(pP2PInfo, &pP2PInfo->DeviceList, pRfd, Frame_pBssid(*posMpdu), NULL, mbPacket); } } p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_BEACON, pRfd, Frame_pBssid(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_BEACON]->msg; mb.Buffer = (u1Byte *)pDev; mb.Length = sizeof(*pDev); PlatformIndicateP2PEvent(pP2PInfo, P2P_EVENT_DEV_FOUND, &mb); if(!p2p_validate_Beacon(msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Update Managed P2P Device Info. p2pUpdateBssDescManageability(pP2PInfo->pAdapter, Frame_pBssid(*posMpdu), msg); // Parse all Sub IEs pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->devAddr, msg, TRUE); if(pP2PDeviceDesc == NULL) { RT_TRACE_F(COMP_P2P, DBG_TRACE, ("reject because of invalid P2P Sub IE or the corresponding entry is not in the scan list\n")); break; } if(msg->_noa) P2POnP2PNoticeOfAbsence(pP2PInfo, *posMpdu, msg); // Update the device lists -------------------------------------------------------------------------- if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { MEMORY_BUFFER mbPacket = {NULL, 0}; mbPacket.Buffer = posMpdu->Octet; mbPacket.Length = posMpdu->Length; P2PDeviceListUpdate(pP2PInfo, &pP2PInfo->DeviceList, pRfd, msg->bssid, msg->devAddr, mbPacket); } // Wait for join if(pP2PInfo->DeviceDiscoverabilityContext.bWaitingBeaconFromGO && pP2PInfo->State == P2P_STATE_DEVICE_DISCOVERABILITY_WAIT_BEACON && eqMacAddr(pP2PInfo->DeviceDiscoverabilityContext.GoBssid, msg->bssid)) { if(p2p_FindClientInfoByDevAddr(pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress, msg, NULL)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("going to send DeviceDiscoverabilityReq to the GO\n")); pP2PInfo->DeviceDiscoverabilityContext.bWaitingBeaconFromGO = FALSE; pP2PInfo->State = P2P_STATE_DEVICE_DISCOVERABILITY_REQ_SEND; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } } }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); return rtStatus; } BOOLEAN P2PHasNon11BRateAsSupportingRate( IN OCTET_STRING osPacket ) { OCTET_STRING BratesBeacon, ExtratesBeacon; BOOLEAN bHasNon11bRate = FALSE; u2Byte i; // // Note: if no supported rate IE in osPacket, FALSE is returned. // // Check Supported rate BratesBeacon = PacketGetElement(osPacket, EID_SupRates, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE ); if( BratesBeacon.Length != 0) { for(i = 0; i < BratesBeacon.Length; i++) { if(!IS_CCK_RATE((BratesBeacon.Octet)[i])) { bHasNon11bRate = TRUE; break; } } } if(!bHasNon11bRate) { // 19.Extended supported rates ExtratesBeacon = PacketGetElement(osPacket, EID_ExtSupRates, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE ); if( ExtratesBeacon.Length != 0) { for(i = 0; i < ExtratesBeacon.Length; i++) { if(!IS_CCK_RATE((ExtratesBeacon.Octet)[i])) { bHasNon11bRate = TRUE; break; } } } } return bHasNon11bRate; } BOOLEAN P2PAcceptProbeReq( IN PP2P_INFO pP2PInfo, IN const OCTET_STRING *posMpdu, IN const P2P_MESSAGE *msg ) { BOOLEAN bRet = FALSE; //OCTET_STRING osSsid = PacketGetElement(osPacket, EID_SsId, OUI_SUB_DONT_CARE, OUI_SUB_DONT_CARE); // // Check if we shall respond to the ProbeReq. // Note that when in Op mode acting as GO, // ProbeReq is not dealt with here. // do { if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { // Win8: Device port discoverability checking ------------------------------------------------------------ if(GetFirstDevicePort(pP2PInfo->pAdapter) == pP2PInfo->pAdapter) { if(GET_P2P_INFO(GetFirstDevicePort(pP2PInfo->pAdapter))->uListenStateDiscoverability == 0) { RT_TRACE(COMP_P2P, DBG_LOUD, ("Reject Probe Request: Device Port: pP2PInfo->uListenStateDiscoverability == 0\n")); break; } } } if(pP2PInfo->State == P2P_STATE_OPERATING) { if(P2P_ACTING_AS_GO(pP2PInfo)) { // check requested device type of the WPS IE matched if(!P2PDeviceTypeMatches(pP2PInfo, msg->wpsAttributes.os)) {//DbgPrint("i\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2PDeviceTypeMatches\n")); break; } // check Device ID matched if(!P2PDeviceIDMatches(pP2PInfo, msg)) {//DbgPrint("j\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2PDeviceIDMatches\n")); break; } } else {// operating but not GO => client if(FALSE == P2PSvc_Enabled(pP2PInfo->pP2PSvcInfo)) {// client does not reply to a ProbeReq, unless P2PSvc is enabled RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: operating but not GO\n")); break; } } } else if(pP2PInfo->State == P2P_STATE_INITIALIZED) { // don't reject } #if 0 else if(pP2PInfo->State == P2P_STATE_INITIALIZED && pP2PInfo->bExtendedListening) {// doing extended listen // don't reject } #endif else if(pP2PInfo->State < P2P_STATE_DEV_DISC_START || pP2PInfo->State > P2P_STATE_DEV_DISC_COMPLETE) {// only accept probe req when doing dev discovery, note that probe req of GO is dealt with by ConstructProbeRsp(). // Comment out because we hope to reduce extended listen timing while not to degrade the responsiveness //break; } // // Clause 3.1.2.1.2 // if(pP2PInfo->State == P2P_STATE_SCAN) {//DbgPrint("a\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2P_STATE_SCAN\n")); break; } if(pP2PInfo->Role == P2P_CLIENT) {//DbgPrint("b\n"); if(FALSE == P2PSvc_Enabled(pP2PInfo->pP2PSvcInfo)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2P_CLIENT\n")); break; } } //if(osP2PIE.Length != 0 && P2P_WILDCARD_SSID(osSsid) && pP2PInfo->Role != P2P_DEVICE) //{// the ProbeReq is intended only for P2P Devices //DbgPrint("c\n"); // break; //} // // Clause 3.1.2.1.3 // if( pP2PInfo->State == P2P_STATE_SEARCH) {//DbgPrint("d\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2P_STATE_SEARCH\n")); break; } // // Clause 3.1.2.1.1 // if(pP2PInfo->State == P2P_STATE_LISTEN || pP2PInfo->State == P2P_STATE_INITIALIZED) { // This has already been checked. //if(osP2PIE.Length == 0) //{// no P2P IE //DbgPrint("e\n"); // break; //} if(!P2P_WILDCARD_MAC_ADDR(msg->bssid)) {//DbgPrint("g\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2P_WILDCARD_MAC_ADDR pBssid\n")); break; } if(!(P2P_WILDCARD_MAC_ADDR(msg->da) || eqMacAddr(msg->da, pP2PInfo->DeviceAddress))) {//DbgPrint("h\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2P_WILDCARD_MAC_ADDR pDaddr\n")); break; } // check requested device type of the WPS IE matched if(!P2PDeviceTypeMatches(pP2PInfo, msg->wpsAttributes.os)) {//DbgPrint("i\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2PDeviceTypeMatches case 2\n")); break; } // check Device ID matched if(!P2PDeviceIDMatches(pP2PInfo, msg)) {//DbgPrint("j\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2PDeviceIDMatches case 2\n")); break; } } // // Clause 2.4.1: P2P Devices shall not respond to Probe Request frames that indicate support for 11b rates only. // if(!P2PHasNon11BRateAsSupportingRate(*posMpdu)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reject Probe Request: P2PHasNon11BRateAsSupportingRate \n")); break; } bRet = TRUE; } while(FALSE); return bRet; } /* BOOLEAN P2PToSendProvisionDiscoveryReq( IN u2Byte ConfigMethod ) { // // If peer's ConfigMethods is Display, Keypad or PBC, send ProvisionDiscoveryReq. // BOOLEAN bRet = FALSE; switch(ConfigMethod) { case P2P_WPS_CONFIG_METHODS_LABEL: break; case P2P_WPS_CONFIG_METHODS_DISPLAY: bRet = TRUE; break; case P2P_WPS_CONFIG_METHODS_PUSHBUTTON: bRet = TRUE; break; case P2P_WPS_CONFIG_METHODS_KEYPAD: bRet = TRUE; break; default: break; } return bRet; } WPS_CONFIG_METHODS P2PDetermineConfigMethodToUse( IN WPS_CONFIG_METHODS PeerConfigMethod ) { WPS_CONFIG_METHODS RetValue = 0xFF; // an impossible value switch(PeerConfigMethod) { case P2P_WPS_CONFIG_METHODS_LABEL: // use peer's label RetValue = P2P_WPS_CONFIG_METHODS_KEYPAD; break; case P2P_WPS_CONFIG_METHODS_DISPLAY: // use peer's displayed PIN RetValue = P2P_WPS_CONFIG_METHODS_KEYPAD; break; case P2P_WPS_CONFIG_METHODS_KEYPAD: // peer will enter my PIN RetValue = P2P_WPS_CONFIG_METHODS_DISPLAY; break; case P2P_WPS_CONFIG_METHODS_PUSHBUTTON: // PBC RetValue = P2P_WPS_CONFIG_METHODS_PUSHBUTTON; break; default: break; } return RetValue; } */ BOOLEAN P2PDetermineDevPasswdIdCompatible( IN u2Byte PeerDevicePasswdID, IN u2Byte SelfDevicePasswdID ) { WPS_DEVICE_PASSWD_ID selfDpid = (WPS_DEVICE_PASSWD_ID)SelfDevicePasswdID; WPS_DEVICE_PASSWD_ID peerDpid = (WPS_DEVICE_PASSWD_ID)PeerDevicePasswdID; switch(selfDpid) { case P2P_WPS_DEV_PASSWD_ID_DEFAULT: // // Marked: Win8 GO Negotiation: Accept all since the Listener is at this state when in initialization //if(PeerDevicePasswdID != P2P_WPS_DEV_PASSWD_ID_DEFAULT) //{ // return FALSE; //} // break; case P2P_WPS_DEV_PASSWD_ID_USER_SPEC: if(peerDpid != P2P_WPS_DEV_PASSWD_ID_DEFAULT && peerDpid != P2P_WPS_DEV_PASSWD_ID_REG_SPEC) { return FALSE; } break; case P2P_WPS_DEV_PASSWD_ID_PBC: if(peerDpid != P2P_WPS_DEV_PASSWD_ID_PBC) { return FALSE; } break; case P2P_WPS_DEV_PASSWD_ID_REG_SPEC: if(peerDpid != P2P_WPS_DEV_PASSWD_ID_USER_SPEC) { return FALSE; } break; case P2P_WPS_DEV_PASSWD_ID_WFDS_DEFAULT_PIN: //if(peerDpid != P2P_WPS_DEV_PASSWD_ID_WFDS_DEFAULT_PIN) //{ // return FALSE; //} return TRUE; break; default: return FALSE; break; } return TRUE; } BOOLEAN P2PDetermineGONegoDevPasswdIdCompaible( IN u2Byte selfDpid, IN u2Byte peerDpid ) { // // Check Device Password ID compatibility // RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDetermineGONegoDevPasswdIdCompaible(): recvd Dev Passwd ID (%u), mine (%u)\n", peerDpid, selfDpid)); if(!P2PDetermineDevPasswdIdCompatible(peerDpid, selfDpid)) {// dev passwd id incompatible RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDetermineGONegoDevPasswdIdCompaible(): DevPasswdId Incompatible\n")); return FALSE; } return TRUE; } // // Description: // Handle Probe Request packet for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_PKT_DROP if this packet is handled by P2P and can be droppd. // If the returned status is RT_STATUS_SUCCESS, the next normal process should be executed. // Remark: // When the current state is P2P Go or AP mode, the probe request is handled by AP mode. // This function only handles the probe request when the current state is P2P device mode. // RT_STATUS P2P_OnProbeReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; OCTET_STRING osWpsIE = PacketGetElement(*posMpdu, EID_Vendor, OUI_SUB_SimpleConfig, OUI_SUB_DONT_CARE); BOOLEAN bHandled = FALSE; P2P_ROLE p2pRole = pP2PInfo->Role; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; // If the state is AP mode or IBSS mode, we don't handle probe request here. if(pAdapter == GetFirstGOPort(pAdapter) || pMgntInfo->mIbss && !pMgntInfo->mDisable && pMgntInfo->bIbssCoordinator) { //RT_TRACE(COMP_P2P, DBG_LOUD, ("This pkt will be handled by GO!\n")); return RT_STATUS_SUCCESS; } if(P2P_DEVICE != pP2PInfo->Role) { RT_TRACE(COMP_P2P, DBG_LOUD, ("Return because Not Device port!\n")); return RT_STATUS_SUCCESS; } p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_PROBE_REQ, pRfd, Frame_pSaddr(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { // RT_TRACE(COMP_P2P, DBG_LOUD, ("Failed (0x%08X) from p2p_DevList_RxUpdate!\n", rtStatus)); break; } msg = pDev->rxFrames[P2P_FID_PROBE_REQ]->msg; if(!p2p_validate_ProbeReq(msg)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("RT_STATUS_MALFORMED_PKT!\n")); rtStatus = RT_STATUS_MALFORMED_PKT; break; } if(!P2PAcceptProbeReq(pP2PInfo, posMpdu, msg)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("rejected by P2PAcceptProbeReq()\n")); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "Transmitter Address: ", Frame_pTaddr(*posMpdu)); RT_TRACE(COMP_P2P, DBG_LOUD, ("pP2PInfo->State: %d\n", pP2PInfo->State)); break; } if(P2P_DEVICE == p2pRole && pP2PInfo->State > P2P_STATE_GO_NEGO_COMPLETE && FALSE == P2PSvc_Enabled(pP2PInfo->pP2PSvcInfo) ) {// when operating, ProbeReq is handled in OnProbeReq(), not here. break; } if(pP2PInfo->bExtendedListening) { //RT_TRACE_F(COMP_P2P, DBG_LOUD, ("recv ProbeReq in Extended Listen\n")); //RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2P_OnProbeReq(): recv ProbeReq in Extended Listen\n", DeviceAddress); } pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->sa, msg, TRUE); bHandled = TRUE; }while(FALSE); // Debug Device Discovery ------------------------------------------------------------ pP2PInfo->ProbeRequestSequenceNum = (u2Byte) Frame_SeqNum(*posMpdu); // 12 bits. // -------------------------------------------------------------------------------- RT_TRACE_F(COMP_P2P, DBG_TRACE, ("PlatformGetCurrentTime(): %d\n", (u4Byte)PlatformGetCurrentTime())); RT_TRACE_F(COMP_P2P, DBG_TRACE, ("pDevicePortP2PInfo->TimeStartToStopSendingProbeResponse: %d\n", (u4Byte)pP2PInfo->TimeStartToStopSendingProbeResponse)); // // Send ProbeRsp if(bHandled) { if(pP2PInfo->TimeStartToStopSendingProbeResponse == 0 || (s8Byte) (PlatformGetCurrentTime()) - pP2PInfo->TimeStartToStopSendingProbeResponse < 0) { p2p_Send_ProbeRsp(pP2PInfo, msg->sa, pRfd, posMpdu, &msg->p2pAttributes.os); // // After sending probe request, return "RT_STATUS_PKT_DROP" to notify that this pakcet was handled // here and it must be dropped. // rtStatus = RT_STATUS_PKT_DROP; } else if((s8Byte)(PlatformGetCurrentTime()) - pP2PInfo->TimeStartToStopSendingProbeResponse > 2 * P2P_RESERVED_TIME_FOR_ACTION_FRAME_MS * 1000) { RT_TRACE_F(COMP_P2P, DBG_TRACE, ("Reset pP2PInfo->TimeStartToStopSendingProbeResponse: from %d to 0\n", (u4Byte)pP2PInfo->TimeStartToStopSendingProbeResponse)); pP2PInfo->TimeStartToStopSendingProbeResponse = 0; rtStatus = RT_STATUS_PKT_DROP; } else { RT_TRACE_F(COMP_P2P, DBG_TRACE, ("No probe rsp\n")); } } p2p_DevList_Unlock(&pP2PInfo->devList); return rtStatus; } // // Description: // Handle probe response packet for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // This function updates the P2P scan list and check the WPS state for join. // RT_STATUS P2P_OnProbeRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; MEMORY_BUFFER mb = {NULL, 0}; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PInfo->bForceScanLegacyNetworks) { MEMORY_BUFFER mbPacket = {NULL, 0}; mbPacket.Buffer = posMpdu->Octet; mbPacket.Length = posMpdu->Length; P2PDeviceListUpdate(pP2PInfo, &pP2PInfo->DeviceList, pRfd, Frame_pBssid(*posMpdu), NULL, mbPacket); } p2p_DevList_Lock(&pP2PInfo->devList); do { // RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2P_OnProbeRsp(): ", Frame_pSaddr(*posMpdu)); if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_PROBE_RSP, pRfd, Frame_pBssid(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_PROBE_RSP]->msg; mb.Buffer = (u1Byte *)pDev; mb.Length = sizeof(*pDev); PlatformIndicateP2PEvent(pP2PInfo, P2P_EVENT_DEV_FOUND, &mb); if(!p2p_validate_ProbeRsp(msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Update Managed P2P Device Info. p2pUpdateBssDescManageability(pP2PInfo->pAdapter, msg->bssid, msg); if(NULL == (pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->devAddr, msg, TRUE))) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Reject because of invalid P2P Sub IE\n")); break; } if(msg->_noa) P2POnP2PNoticeOfAbsence(pP2PInfo, *posMpdu, msg); // Update the device lists -------------------------------------------------------------------------- if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { MEMORY_BUFFER mbPacket = {NULL, 0}; mbPacket.Buffer = posMpdu->Octet; mbPacket.Length = posMpdu->Length; P2PDeviceListUpdate(pP2PInfo, &pP2PInfo->DeviceList, pRfd, msg->bssid, msg->devAddr, mbPacket); if(pP2PInfo->ScanDeviceIDs.uNumOfDeviceIDs > 0) { // Finding some device now if(eqMacAddr(msg->devAddr, pP2PInfo->ScanDeviceIDs.DeviceIDs[0])) { // Device is Found: Complete the Scan Immediately for speeding up GO Negotiation RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] cease scan for dev id matched\n")); p2p_DevList_Unlock(&pP2PInfo->devList); P2PScanListCeaseScan(pP2PInfo); p2p_DevList_Lock(&pP2PInfo->devList); } } } // ---------------------------------------------------------------------------------------------- // // In this case, we are in pre GO Nego phase. We will start a GO Nego procedure. // if(P2PCommonChannelArrived(pP2PInfo, pDev, *posMpdu)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("common channel arrived\n")); //return; } if(pP2PInfo->DeviceDiscoverabilityContext.bWaitingBeaconFromGO && pP2PInfo->State == P2P_STATE_DEVICE_DISCOVERABILITY_WAIT_BEACON && eqMacAddr(pP2PInfo->DeviceDiscoverabilityContext.GoBssid, msg->bssid)) { if(p2p_FindClientInfoByDevAddr(pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress, msg, NULL)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("going to send DeviceDiscoverabilityReq to the GO\n")); pP2PInfo->DeviceDiscoverabilityContext.bWaitingBeaconFromGO = FALSE; pP2PInfo->State = P2P_STATE_DEVICE_DISCOVERABILITY_REQ_SEND; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } } P2PSvc_OnProbeRsp(pP2PInfo->pP2PSvcInfo, msg->devAddr, &msg->p2pAttributes.os); }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); return rtStatus; } // // Description: // Handle association packet for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // This function is called after this client is determined successfully associated with our AP mode. // This function checks the P2P IEs from the client and update it to the client list if it is a p2p client. // By Bruce, 2012-03-12. // RT_STATUS P2P_OnAssocReqAccept( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); pu1Byte InterfaceAddress = Frame_pSaddr(*posMpdu); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; PRT_WLAN_STA pAsocEntry = NULL; PMGNT_INFO pExtMgntInfo = &(pAdapter->MgntInfo); P2P_MESSAGE msg; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; do { if(RT_STATUS_SUCCESS == (rtStatus = p2p_parse_Ies(posMpdu, DBG_LOUD, &msg))) if(!p2p_validate_AssocReq(&msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } if(NULL == (pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg.devAddr, &msg, TRUE))) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject because of invalid P2P Sub IE\n")); break; } pAsocEntry = AsocEntry_GetEntry(&(pAdapter->MgntInfo), InterfaceAddress); if(pAsocEntry) { pAsocEntry->bP2PClient = TRUE; cpMacAddr(pAsocEntry->P2PClientInfoDesc.InterfaceAddress, pP2PDeviceDesc->IntendedP2PInterfaceAddress); cpMacAddr(pAsocEntry->P2PClientInfoDesc.DeviceAddress, pP2PDeviceDesc->DeviceAddress); pAsocEntry->P2PClientInfoDesc.DeviceCapability = pP2PDeviceDesc->DeviceCapability; PlatformMoveMemory(&pAsocEntry->P2PClientInfoDesc.WpsAttributes, &(pP2PDeviceDesc->WpsAttributes), sizeof(P2P_WPS_ATTRIBUTES)); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2P_OnAssocReqAccept(): Copy into list with client = ", pAsocEntry->P2PClientInfoDesc.InterfaceAddress); } }while(FALSE); p2p_parse_FreeMessage(&msg); FunctionOut(COMP_P2P); return rtStatus; } // // Description: // Handle deauth/disassoc packet in client mode for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // This function updates the P2P capability from the reason code. // RT_STATUS P2P_ClientOnDeauth( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); P2P_MESSAGE msg; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); do { if(RT_STATUS_SUCCESS == (rtStatus = p2p_parse_Ies(posMpdu, DBG_LOUD, &msg))) if(!p2p_validate_Deauth(&msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // TODO: we may check whether this is from an AP (either WLAN AP or P2P GO) that has manageability attribute if(msg._minorReasonCode) {// has valid minor reason code RT_TRACE_F(COMP_P2P, DBG_LOUD, ("minor rsn code: %u\n", msg.minorReasonCode)); switch(msg.minorReasonCode) { default: // Reserved break; case P2P_MINOR_RESON_CROSS_CONNECTION: pP2PInfo->bWlanApRejection_CrossConnection = TRUE; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("disable cross connection\n")); pP2PInfo->GroupCapability &= ~gcCrossConnection; // disable cross connection // // After disable cross connection, we shall reconnect to the wlan AP // without corss connection bit set. // break; case P2P_MINOR_RESON_MANAGED_BIT: if(!(pP2PInfo->DeviceCapability & dcP2PInfrastructureManaged)) { pP2PInfo->bWlanApRejection_Unmanaged = TRUE; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("disable P2P mode because of minor reason code 2 => should not send any P2P IE in ProbeReq and (Re)AssocReq\n")); MgntActSet_P2PMode(pP2PInfo->pAdapter, FALSE, FALSE, 1, 1, 1); } else { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Receive deauth with minor rsn code 2 when managed P2P is enabled => ignore it\n")); } break; case P2P_MINOR_RESON_CONCURRENT_COEXISTENCE: if(pP2PInfo->DeviceCapability & dcP2PInfrastructureManaged) { pu1Byte pBssid = Frame_pBssid(*posMpdu); PRT_WLAN_BSS pBssDesc = NULL; pP2PInfo->bWlanApRejection_IncompatibleCoexistenceParameters = TRUE; if(pP2PInfo->Role != P2P_GO) break; PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_SCAN_SPINLOCK); pBssDesc = BssDescDupByBssid(pP2PInfo->pAdapter, pBssid); if(pBssDesc) { P2PUpdateWlanApManagedInfo(pP2PInfo, pBssDesc); } PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_SCAN_SPINLOCK); //RT_TRACE_F(COMP_P2P, DBG_LOUD, // ("disable P2P mode because of minor reason code 3\n")); //P2PDisconnect(pP2PInfo); //MgntActSet_P2PMode(pP2PInfo->pAdapter, FALSE, FALSE, 1, 1, 1); } break; case P2P_MINOR_RESON_INFRASTRUCTURE_MANAGED_BIT: if(pP2PInfo->DeviceCapability & dcP2PInfrastructureManaged) { pP2PInfo->bWlanApRejection_IncompatibleP2POperation = TRUE; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("disable P2P mode because of minor reason code 4 and I'm a managed P2P Device\n")); MgntActSet_P2PMode(pP2PInfo->pAdapter, FALSE, FALSE, 1, 1, 1); } else { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("ignore the deauth with minor reason code 4 bceause I'm NOT a managed P2P Device\n")); } break; } } }while(FALSE); p2p_parse_FreeMessage(&msg); return rtStatus; } // // Description: // Handle deauth/disassoc packet in client mode for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // This function updates the P2P capability from the reason code. // RT_STATUS P2P_ClientOnDisassoc( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { return P2P_ClientOnDeauth(pAdapter, pRfd, posMpdu); } // // Description: // Handle P2P Go Negotiation Reqeust packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnGONReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo; PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; int go; P2P_STATE CurrentState = pP2PInfo->State; // For bakcup state when neg failed. P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnGONReq():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_GO_NEG_REQ, pRfd, Frame_pSaddr(*posMpdu), pP2PInfo->ListenChannel, &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_GO_NEG_REQ]->msg; if(!p2p_validate_GoNegReq(msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->devAddr, msg, TRUE); if(pP2PDeviceDesc == NULL) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject because of invalid P2P Sub IE\n")); rtStatus = RT_STATUS_INVALID_DATA; break; } // // Check state // if(pP2PInfo->Role == P2P_CLIENT) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Receive GoReq when we are client\n")); P2PIndicateDeviceReqClientGoFormation(pP2PInfo, pP2PDeviceDesc); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_REJECTED_BY_USER; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONReq; } else if(!P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PInfo->State > P2P_STATE_DEV_DISC_COMPLETE) { RT_TRACE(COMP_P2P, DBG_WARNING, ("[WARNING] recv in an invalid state: %u\n", pP2PInfo->State)); rtStatus = RT_STATUS_INVALID_DATA; break; } // // v1.07: // If a Status attribute is present in the received GO Negotiation Request frame, // the request is being used to signal user rejection of an earlier GO Negotiation Request // sent by the receiving P2P Device and shall be discarded with no further action. // if(msg->_status) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] has Status attr in GONegoReq, Status: %u\n", pP2PInfo->State)); rtStatus = RT_STATUS_INVALID_DATA; break; } // Copy device descriptor PlatformMoveMemory(&pP2PInfo->ConnectionContext.ConnectingDevice, pP2PDeviceDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); // Reject overllapped GONego Req if(P2PIsDoingGroupFormation(pP2PInfo) && !cpMacAddr(pP2PInfo->ConnectionContext.ConnectingDevice.DeviceAddress, msg->sa)) {// not to update the state machine pP2PDeviceDesc->Status = P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST; RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject overllaped GONego Req\n")); goto exit_P2POnGONReq; } pP2PInfo->State = P2P_STATE_GO_NEGO_REQ_RECVD; if( P2P_DOING_DEVICE_DISCOVERY(pP2PInfo) ) { p2p_DevList_Unlock(&pP2PInfo->devList); P2PScanListCeaseScan(pP2PInfo); p2p_DevList_Lock(&pP2PInfo->devList); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } // Determine GO go = p2p_go_det(pP2PInfo->GOIntent, pP2PDeviceDesc->GOIntent); if(go) { RT_TRACE(COMP_P2P, DBG_LOUD, ("I'm going to be the GO\n")); pP2PInfo->ConnectionContext.bGoingToBeGO = TRUE; // Determine GO SSID P2PDetermineGOSsid(pP2PInfo, pP2PInfo->SSIDBuf, &pP2PInfo->SSIDLen); } else if(0 == go) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("the target device is going to be the GO\n")); pP2PInfo->ConnectionContext.bGoingToBeGO = FALSE; } else {// shall update the state machine RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] P2P_STATUS_FAIL_BOTH_P2P_DEVICES_INDICATED_GO_INTENT_OF_15\n")); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_BOTH_P2P_DEVICES_INDICATED_GO_INTENT_OF_15; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONReq; } // Check Device Password ID compatibility { if(P2P_ADAPTER_RTK_SUPPORT_P2P(pAdapter) && !P2PDetermineGONegoDevPasswdIdCompaible(pP2PInfo->WpsDevPasswdId, msg->wpsDevPasswordId)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Fail information is unavailable\n")); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_INFORMATION_IS_UNAVAILABLE; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; // // Check if peer is waiting for our user input // if(msg->wpsDevPasswordId == P2P_WPS_DEV_PASSWD_ID_PBC || msg->wpsDevPasswordId == P2P_WPS_DEV_PASSWD_ID_DEFAULT || msg->wpsDevPasswordId == P2P_WPS_DEV_PASSWD_ID_REG_SPEC) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Start waiting for user input for 2 min\n")); pP2PInfo->bReinitiateConnection = TRUE; cpMacAddr(pP2PInfo->DevAddrToReConnect, msg->devAddr); pP2PInfo->TimeStartWaitingForReinitiate = PlatformGetCurrentTime(); } goto exit_P2POnGONReq; } } // Check if channel is compatible if(pP2PInfo->ConnectionContext.bGoingToBeGO) { p2p_Channel_Intersect(&pP2PInfo->ChannelEntryList, &pDev->p2p->channels, &pDev->p2p->commonChannels); if(pDev->p2p->commonChannels.regClasses) { // Has Common Channel // Check if our op channel is one of channels supported by peer if(!p2p_Channel_InChannelEntryList(pP2PInfo->OperatingChannel, &pDev->p2p->commonChannels)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("going to be GO, change op ch from: %d to %d\n", pP2PInfo->OperatingChannel, pDev->p2p->commonChannels.regClass[0].channel[0])); pP2PInfo->OperatingChannel = pDev->p2p->commonChannels.regClass[0].channel[0]; // alwyas use the first one } } // Win8 Go Negotiation Trick ----------------------------------------------------------------------------------------------------------------------- else if(MgntLinkStatusQuery(GetDefaultAdapter(pP2PInfo->pAdapter)) == RT_MEDIA_CONNECT) { #if (MULTICHANNEL_SUPPORT == 1) // For Compilation: Only PCI-E Support MultiChannel Now pP2PInfo->OperatingChannel = MultiChannelGetPortConnected20MhzChannel(GetDefaultAdapter(pP2PInfo->pAdapter)); #endif RT_TRACE_F(COMP_P2P, DBG_LOUD, ("WHCK Test Trick: Going to be GO, change op ch to default port connected channel: %d\n", pP2PInfo->OperatingChannel)); } // --------------------------------------------------------------------------------------------------------------------------------------------- else // No Common Channel { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] no common channels\n")); RT_PRINT_DATA(COMP_P2P, DBG_WARNING, "[WARNING] peer supported op chnl:\n", pP2PDeviceDesc->ChannelPlanChannel, pP2PDeviceDesc->ChannelPlanLength); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_NO_COMMON_CHANNELS; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONReq; } } // After here, we shall send a GONRsp of status success pP2PDeviceDesc->Status = P2P_STATUS_SUCCESS; // // Fill ConnectionContext, note that bGoingToBeGO has already been filled // pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; pP2PInfo->ConnectionContext.DialogToken = pP2PDeviceDesc->DialogToken; pP2PInfo->ConnectionContext.FindPhaseLoopTimes = P2P_SCAN_FIND_PHASE_LOOP_TIMES; // no use // ========== exit_P2POnGONReq ========== exit_P2POnGONReq: if(MgntRoamingInProgress(pMgntInfo)) { if(MgntResetOrPnPInProgress(pAdapter)) { RT_TRACE_F(COMP_MLME, DBG_LOUD, ("reset in progress case 1\n")); return RT_STATUS_FAILURE; } MgntRoamComplete(pAdapter, MlmeStatus_refused); } // < Note> If failed, we shall not modify the original state machine state. if(P2P_STATUS_SUCCESS == pP2PDeviceDesc->Status) WFD_OnP2PActionFrame(pAdapter, pRfd, posMpdu); // If failed, indicate as early as possible if(pP2PDeviceDesc->Status != P2P_STATUS_SUCCESS && FrameBuf_Length(&msg->wpsAttributes)) { pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); } else { if(!P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) // use OffChnlTx, don't extend dwell time here CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), P2P_GO_NEGO_FRAME_TIMEOUT); } // For Win8: Indicate the reception of the GO negotiation request ------------------------- // Wait for the command of OID_DOT11_WFD_SEND_GO_NEGOTIATION_RESPONSE if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { //in case OID not set pP2PInfo->State = P2P_STATE_GO_NEGO_RSP_SEND; } else { // Send GONRsp pP2PInfo->Status = pP2PInfo->ConnectionContext.Status; p2p_Send_GoNegRsp(pP2PInfo, pP2PDeviceDesc->DeviceAddress,pP2PDeviceDesc->DialogToken); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("send GORsp with status = %u, intent = %u, tie breaker: %u\n", pP2PInfo->ConnectionContext.Status, pP2PInfo->GOIntent >> 1, pP2PInfo->GOIntent & 0x01)); // Update state machine if(pP2PInfo->ConnectionContext.Status == P2P_STATUS_SUCCESS) { pP2PInfo->State = P2P_STATE_GO_NEGO_RSP_SEND; } else if(!FrameBuf_Length(&msg->wpsAttributes)) { pP2PInfo->State = CurrentState; } else if(pP2PInfo->Role != P2P_CLIENT) { pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; } if( P2P_DOING_DEVICE_DISCOVERY(pP2PInfo) ) { p2p_DevList_Unlock(&pP2PInfo->devList); P2PScanListCeaseScan(pP2PInfo); p2p_DevList_Lock(&pP2PInfo->devList); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } } }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); if(RT_STATUS_SUCCESS == rtStatus) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_GO_NEGOTIATION_REQUEST, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("<=== status: %u, next state: %u\n", pP2PInfo->ConnectionContext.Status, pP2PInfo->State)); return rtStatus; } // // Description: // Handle P2P Go Negotiation Response packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnGONRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; int go; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2P_OnGONRsp():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_GO_NEG_RSP, pRfd, Frame_pSaddr(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_GO_NEG_RSP]->msg; if(!p2p_validate_GoNegRsp(pP2PInfo, msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Store the info in the P2P IE into pP2PDeviceDesc if(!P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, msg->devAddr, NULL, NULL)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("peer is not in our scan list\n")); P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); } pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->devAddr, msg, FALSE); if(pP2PDeviceDesc == NULL) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject because of invalid P2P Sub IE\n")); rtStatus = RT_STATUS_INVALID_DATA; break; } if(!P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PInfo->State != P2P_STATE_GO_NEGO_RSP_WAIT) {// althoug incorrect state, we still record info form the GONegoRsp RT_TRACE_F(COMP_P2P, DBG_LOUD, ("[WARNING] our state (%d) not in P2P_STATE_GO_NEGO_RSP_WAIT state\n", pP2PInfo->State)); rtStatus = RT_STATUS_INVALID_DATA; break; } // // Update ConnectionContext.ConnectingDevice since after P2PProcessSubElements, // its ChannelList or other elements may be modified. // PlatformMoveMemory(&pP2PInfo->ConnectionContext.ConnectingDevice, pP2PDeviceDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); // Compare DialogToken if(!P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PDeviceDesc->DialogToken != pP2PInfo->ConnectionContext.DialogToken) {// Dialog Token mismatch RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] dialog token mismatch, recvd: %u, self: %u\n", pP2PDeviceDesc->DialogToken, pP2PInfo->ConnectionContext.DialogToken)); rtStatus = RT_STATUS_INVALID_DATA; break; } else { pP2PInfo->ConnectionContext.DialogToken++; } if(pP2PDeviceDesc->Status != P2P_STATUS_SUCCESS) {// Group Formation ends on reception of a GONRsp with status other than success pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] status (%u) of the GONRsp is not success\n", pP2PDeviceDesc->Status)); PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); if(RUNTIME_OS_WIN_FROM_WIN8(pP2PInfo->pAdapter)) { break; // break with status success to indicate go neg rsp } pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); rtStatus = RT_STATUS_INVALID_STATE; break; } // // Reject overlapped GONego Req // if(P2PIsDoingGroupFormation(pP2PInfo) && !cpMacAddr(pP2PInfo->ConnectionContext.ConnectingDevice.DeviceAddress, msg->sa)) {// not to update the state machine pP2PDeviceDesc->Status = P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST; RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Reject overlapped GONego Req\n")); goto exit_P2POnGONRsp; } // Determine GO go = p2p_go_det(pP2PInfo->GOIntent, pP2PDeviceDesc->GOIntent); if(go) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("I'm going to be the GO\n")); pP2PInfo->ConnectionContext.bGoingToBeGO = TRUE; // Determine GO SSID P2PDetermineGOSsid(pP2PInfo, pP2PInfo->SSIDBuf, &pP2PInfo->SSIDLen); } else if(0 == go) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("the target device is going to be the GO\n")); pP2PInfo->ConnectionContext.bGoingToBeGO = FALSE; } else { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] P2P_STATUS_FAIL_BOTH_P2P_DEVICES_INDICATED_GO_INTENT_OF_15\n")); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_BOTH_P2P_DEVICES_INDICATED_GO_INTENT_OF_15; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONRsp; } // Check Device Password ID compatibility if(!P2PDetermineGONegoDevPasswdIdCompaible(pP2PInfo->WpsDevPasswdId, msg->wpsDevPasswordId)) { pP2PDeviceDesc->Status = P2P_STATUS_FAIL_INCOMPATIBLE_PROVISION_METHOD; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONRsp; } // Check if channel is compatible p2p_Channel_Intersect(&pP2PInfo->ChannelEntryList, &pDev->p2p->channels, &pDev->p2p->commonChannels); if(pP2PInfo->ConnectionContext.bGoingToBeGO) { if(pDev->p2p->commonChannels.regClasses) // use P2PMakeP2PChannelEntryList to test if we have common channels { // Check if our op channel is one of channels supported by peer if(!p2p_Channel_InChannelEntryList(pP2PInfo->OperatingChannel, &pDev->p2p->commonChannels)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("going to be GO, change op ch from: %d to %d\n", pP2PInfo->OperatingChannel, pDev->p2p->commonChannels.regClass[0].channel[0])); // TODO: we may not support the 1st channel supported by peer pP2PInfo->OperatingChannel = pDev->p2p->commonChannels.regClass[0].channel[0]; // alwyas use the first one } } else // no common channel { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] no common channels: %p\n", &pP2PInfo->ConnectionContext.ConnectingDevice)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "ChnlList Recvd:\n", pP2PDeviceDesc->ChannelPlanChannel, pP2PDeviceDesc->ChannelPlanLength); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_NO_COMMON_CHANNELS; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONRsp; } } else {// Client if(pDev->p2p->commonChannels.regClasses) // use P2PMakeP2PChannelEntryList to test if we have common channels { // Common Channel found } else // No common channel { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] no common channel\n")); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_NO_COMMON_CHANNELS; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONRsp; } pP2PInfo->OperatingChannel = pP2PDeviceDesc->OperatingChannel; } // Fill ConnectionContext, note that bGoingToBeGO has already been filled pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; pP2PInfo->ConnectionContext.DialogToken = pP2PDeviceDesc->DialogToken; // no use pP2PInfo->ConnectionContext.FindPhaseLoopTimes = P2P_SCAN_FIND_PHASE_LOOP_TIMES; // no use exit_P2POnGONRsp: if(P2P_STATUS_SUCCESS == pP2PDeviceDesc->Status) WFD_OnP2PActionFrame(pAdapter, pRfd, posMpdu); // // If failed, indicate as early as possible // if(pP2PDeviceDesc->Status != P2P_STATUS_SUCCESS) { pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); } { BOOLEAN bSupportTxReport = FALSE; // // Send GONConfirm // if(FALSE == P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { pP2PInfo->Status = pP2PInfo->ConnectionContext.Status; p2p_Send_GoNegConfirm(pP2PInfo, pP2PDeviceDesc->DeviceAddress, pP2PDeviceDesc->DialogToken, &bSupportTxReport); // // Update state machine // if(bSupportTxReport) { pP2PInfo->msTimeWaitGoNegoConfirmSent = 0; pP2PInfo->State = P2P_STATE_GO_NEGO_CONFIRM_SENT_WAIT; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } else { pP2PInfo->msTimeWaitGoNegoConfirmSent = 0; pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 200); // in case P2P_STATE_GO_NEGO_COMPLETE, if w are GO, channel is switched to the op channel and the Confirm may be sent on the op channel instead of the listen channel } } } }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); if(RT_STATUS_SUCCESS == rtStatus) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_GO_NEGOTIATION_RESPONSE, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("status: %u\n", pP2PInfo->ConnectionContext.Status)); return rtStatus; } // // Description: // Handle P2P Go Negotiation Confirm packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnGONConfirm( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnGONConfirm():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_GO_NEG_CONF, pRfd, Frame_pSaddr(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_GO_NEG_CONF]->msg; if(!p2p_validate_GoNegConfirm(pP2PInfo->ConnectionContext.bGoingToBeGO, msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Check state // Possible states are confirmWait and RspSend if(!OS_SUPPORT_WDI(pP2PInfo->pAdapter) && !(pP2PInfo->State == P2P_STATE_GO_NEGO_CONFIRM_WAIT || pP2PInfo->State == P2P_STATE_GO_NEGO_RSP_SEND)) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] state (%u) is not P2P_STATE_GO_NEGO_CONFIRM_WAIT or P2P_STATE_GO_NEGO_RSP_SEND\n", pP2PInfo->State)); rtStatus = RT_STATUS_INVALID_DATA; break; } pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->sa, msg, FALSE); if(pP2PDeviceDesc == NULL) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("[WARNING] reject because of invalid P2P Sub IE\n")); rtStatus = RT_STATUS_INVALID_CONTEXT; break; } // Check DialogToken if(pP2PDeviceDesc->DialogToken != pP2PInfo->ConnectionContext.DialogToken) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] dialog token mismatch: mine(%u), peer(%u)\n", pP2PInfo->ConnectionContext.DialogToken, pP2PDeviceDesc->DialogToken)); rtStatus = RT_STATUS_INVALID_DATA; break; } else { pP2PInfo->ConnectionContext.DialogToken++; } if(pP2PDeviceDesc->Status != P2P_STATUS_SUCCESS) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WRNING] status of the GONConfirm is not success\n")); pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; if(RUNTIME_OS_WIN_FROM_WIN8(pP2PInfo->pAdapter)) { break; // break with status success to indicate go neg conf } rtStatus = RT_STATUS_INVALID_DATA; break; } PlatformMoveMemory(&pP2PInfo->ConnectionContext.ConnectingDevice, pP2PDeviceDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); // Check if channel is compatible if(pP2PInfo->ConnectionContext.bGoingToBeGO) { // Check if our op channel is one of channels supported by peer if(!P2PIsChnlInChnlList(pP2PDeviceDesc->ChannelPlanChannel, pP2PDeviceDesc->ChannelPlanLength, pP2PInfo->OperatingChannel)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("going to be GO, change op ch from: %d to %d\n", pP2PInfo->OperatingChannel, pP2PDeviceDesc->ChannelPlanChannel[0])); // TODO: we may not support the 1st channel supported by peer pP2PInfo->OperatingChannel = pP2PDeviceDesc->ChannelPlanChannel[0]; // alwyas use the first one } } else {// Client if(!P2PIsChnlInChnlEntryList(&pP2PInfo->ChannelEntryList, pP2PDeviceDesc->OperatingChannel)) {// the intended chnl of the GO is not supported RT_TRACE_F(COMP_P2P, DBG_LOUD, ("the intended channel (%u) of the GO is not supported\n", pP2PDeviceDesc->OperatingChannel)); pP2PDeviceDesc->Status = P2P_STATUS_FAIL_NO_COMMON_CHANNELS; pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; goto exit_P2POnGONConfirm; } else {// use the intended op chnl of the GO pP2PInfo->OperatingChannel = pP2PDeviceDesc->OperatingChannel; RT_PRINT_STR(COMP_P2P, DBG_LOUD, "P2P_OnGONConfirm(): I'm client, the target SSID = ", pP2PInfo->ConnectionContext.ConnectingDevice.SsidBuf, pP2PInfo->ConnectionContext.ConnectingDevice.SsidLen); } } pP2PDeviceDesc->Status = P2P_STATUS_SUCCESS; exit_P2POnGONConfirm: if(P2P_STATUS_SUCCESS == pP2PDeviceDesc->Status) { WFD_OnP2PActionFrame(pAdapter, pRfd, posMpdu); } else { pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); } // Fill ConnectionContext pP2PInfo->ConnectionContext.Status = pP2PDeviceDesc->Status; // Update state machine pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); if(RT_STATUS_SUCCESS == rtStatus) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_GO_NEGOTIATION_CONFIRM, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("status: %u\n", pP2PInfo->ConnectionContext.Status)); return rtStatus; } // // Description: // Handle P2P Go Invitation request packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnInvitationReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo; PP2P_DEVICE_DISCRIPTOR pClientInvitationInfo = NULL; static u8Byte TimeStamp = 0; static u2Byte PreviousToken = 0xFFFF; u8Byte CurrentTime = 0; u4Byte ConfigurationTimeout = 0; // in ms, note that the configuration time out in the P2P IE is defined as units of 10ms P2P_ROLE PeerRole = 0; P2P_LIB_INVITATION_REQ_CONTEXT LibInvitationReq; P2P_STATE StateBackup; PRT_GEN_TEMP_BUFFER pGenBufClientInvitationInfo = NULL; BOOLEAN bBackwardInvite = FALSE; const u1Byte *pGrpBssid = NULL; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); // We should not accept InvitationReq too often. CurrentTime = PlatformGetCurrentTime(); if(CurrentTime - TimeStamp < 2000000 && TimeStamp != 0 && (0xFFFF != PreviousToken && (u1Byte)PreviousToken == *((pu1Byte)posMpdu->Octet + FRAME_OFFSET_P2P_PUB_ACT_DIALOG_TOKEN))) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] recv InvitationReq too often => reject, time diff: %d, token = %d\n", (u4Byte)(CurrentTime - TimeStamp), *((pu1Byte)posMpdu->Octet + FRAME_OFFSET_P2P_PUB_ACT_DIALOG_TOKEN))); return RT_STATUS_MEDIA_BUSY; } // we get here at the first time (since TimeStamp is 0), and we get the correct TimeStamp TimeStamp = CurrentTime; PreviousToken = *((pu1Byte)posMpdu->Octet + FRAME_OFFSET_P2P_PUB_ACT_DIALOG_TOKEN); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnInvitationReq():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_INV_REQ, pRfd, Frame_pSaddr(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_INV_REQ]->msg; if(!p2p_validate_InvitationReq(msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } pGenBufClientInvitationInfo = GetGenTempBuffer (pAdapter, sizeof(P2P_DEVICE_DISCRIPTOR)); pClientInvitationInfo = (P2P_DEVICE_DISCRIPTOR *)pGenBufClientInvitationInfo->Buffer.Ptr; if(pP2PInfo->InvitationContext.bWaitingBackwardInvite && eqMacAddr(pP2PInfo->InvitationContext.InvitedDevice.DeviceAddress, msg->devAddr)) { bBackwardInvite = TRUE; } if(!bBackwardInvite) PlatformZeroMemory(&(pP2PInfo->InvitationContext), sizeof(P2P_INVITATION_CONTEXT)); PlatformZeroMemory((pClientInvitationInfo), sizeof(P2P_DEVICE_DISCRIPTOR)); // TODO: check capability // If we are not P2P Device, reject, since the invitor can communicate with us by join our group. if(!P2P_ACTING_AS_DEVICE(pP2PInfo)) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject because current role is: %u, state is: %u\n", pP2PInfo->Role, pP2PInfo->State)); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_INVALID_PARAMETERS; break; } // // Determine whether we are invited by a GO, Client or device. // We also determine whether its a persistent invitation here. // pP2PInfo->InvitationContext.InvitorRole = eqMacAddr(msg->grpDevAddr, msg->devAddr) ? (P2P_GO) : (P2P_CLIENT); pP2PInfo->InvitationContext.bPersistentInvitation = TEST_FLAG(msg->invitationFlags, BIT0); cpMacAddr(pP2PInfo->InvitationContext.GODeviceAddress, msg->grpDevAddr); CopySsid(pP2PInfo->InvitationContext.SsidBuf, pP2PInfo->InvitationContext.SsidLen, msg->grpSsid, msg->grpSsidLen); PeerRole = pP2PInfo->InvitationContext.InvitorRole; // Parse the subelements and store the info in P2PDeviceDesc p2p_parse_UpdateDevDesc(pRfd->Buffer.VirtualAddress, msg, pRfd->Status.SignalStrength, pClientInvitationInfo); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("bAcceptInvitation: %u\n", pP2PInfo->bAcceptInvitation)); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "AccpetInvitationDeviceAddress", pP2PInfo->AccpetInvitationDeviceAddress); if(bBackwardInvite // accept backward invitation || FALSE == pP2PInfo->InvitationContext.bPersistentInvitation // if pure invitation, always accept it ) { pP2PInfo->InvitationContext.Status = P2P_STATUS_SUCCESS; } else if(pP2PInfo->bAcceptInvitation) {// upper layer wants to accept invitation from a specific device if(eqMacAddr(pP2PInfo->AccpetInvitationDeviceAddress, msg->devAddr)) { pP2PInfo->InvitationContext.Status = P2P_STATUS_SUCCESS; } else if(MacAddr_isBcst(pP2PInfo->AccpetInvitationDeviceAddress)) {// to accept all pP2PInfo->InvitationContext.Status = P2P_STATUS_SUCCESS; } else { pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_INFORMATION_IS_UNAVAILABLE; } } else { pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_INFORMATION_IS_UNAVAILABLE; } if(PeerRole == P2P_CLIENT && pP2PInfo->InvitationContext.bPersistentInvitation) {// I'm the persistent GO, in this case, the invitation req may not have Group Bssid pGrpBssid = pP2PInfo->InterfaceAddress; } else { pGrpBssid = pClientInvitationInfo->GroupBssid; } if(0x00000004 <= P2P_VERSION // don't check profile if upper layer registered a lower version && P2P_ADAPTER_RTK_SUPPORT_P2P(pP2PInfo->pAdapter) // don't check profile if running P2P natively supported by OS ) { if(pP2PInfo->InvitationContext.bPersistentInvitation) { if(pP2PInfo->pProfileList) { u4Byte idxProfile = 0; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Profile list: %u profiles\n", pP2PInfo->pProfileList->nProfiles)); for(idxProfile = 0; idxProfile < pP2PInfo->pProfileList->nProfiles; idxProfile++) { RT_PRINT_STR(COMP_P2P, DBG_LOUD, "Compare with SSID", pP2PInfo->pProfileList->profileList[idxProfile].ssidBuf, pP2PInfo->pProfileList->profileList[idxProfile].ssidBufLen); if(CompareSSID(pP2PInfo->pProfileList->profileList[idxProfile].ssidBuf, pP2PInfo->pProfileList->profileList[idxProfile].ssidBufLen, pClientInvitationInfo->SsidBuf, pClientInvitationInfo->SsidLen) && eqMacAddr(pP2PInfo->pProfileList->profileList[idxProfile].grpBssid, pGrpBssid) ) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Profile matched\n")); break; } } if(idxProfile == pP2PInfo->pProfileList->nProfiles) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("No matching profile\n")); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_UNKNOWN_P2P_GROUP; break; } } else { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("No matching profile (pProfileList is NULL)\n")); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_UNKNOWN_P2P_GROUP; break; } } } // // Decide overlapped channel list and Op Channel // { p2p_Channel_Intersect(&pP2PInfo->ChannelEntryList, &pDev->p2p->channels, &pDev->p2p->commonChannels); if(pDev->p2p->commonChannels.regClasses) { // Has Common Channel // Check if our op channel is one of channels supported by peer if(PeerRole == P2P_CLIENT && pP2PInfo->InvitationContext.bPersistentInvitation) {// I'm persistent GO if(!p2p_Channel_InChannelEntryList(pP2PInfo->OperatingChannel, &pDev->p2p->channels)) {// the opChannel we are going to use does not exist in peer's channel list RT_TRACE_F(COMP_P2P, DBG_LOUD, ("The opChannel (%u) we are going to use does not exist in peer's channel list\n", pP2PInfo->OperatingChannel)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "peer channel list:\n", pClientInvitationInfo->ChannelPlanChannel, pClientInvitationInfo->ChannelPlanLength); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Changed to 1st channel (%d) in overlapped list\n", pDev->p2p->commonChannels.regClass[0].channel[0])); pP2PInfo->OperatingChannel = pDev->p2p->commonChannels.regClass[0].channel[0]; } } } else // No Common Channel { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] no common channels\n")); RT_PRINT_DATA(COMP_P2P, DBG_WARNING, "[WARNING] peer supported op chnl:\n", pClientInvitationInfo->ChannelPlanChannel, pClientInvitationInfo->ChannelPlanLength); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_NO_COMMON_CHANNELS; break; } } if(MgntRoamingInProgress(pMgntInfo)) MgntRoamComplete(pAdapter, MlmeStatus_refused); // // Copy required info for constructing InvitationRsp pP2PInfo->InvitationContext.InvitorRole = PeerRole; pP2PInfo->InvitationContext.DialogToken = msg->dialogToken; PlatformMoveMemory(&pP2PInfo->InvitationContext.InvitedDevice, pClientInvitationInfo, sizeof(P2P_DEVICE_DISCRIPTOR)); //pP2PInfo->InvitationContext.Status = pClientInvitationInfo->Status; pP2PInfo->InvitationContext.bInvitor = FALSE; PlatformMoveMemory(pP2PInfo->InvitationContext.SsidBuf, pClientInvitationInfo->SsidBuf, pClientInvitationInfo->SsidLen); pP2PInfo->InvitationContext.SsidLen = pClientInvitationInfo->SsidLen; cpMacAddr(pP2PInfo->InvitationContext.GroupBssid, pGrpBssid); if(PeerRole == P2P_CLIENT && pP2PInfo->InvitationContext.bPersistentInvitation) {// I'm the persistent GO, in this case, the invitation req may not have Group Bssid pP2PInfo->InvitationContext.OpChannel = pP2PInfo->OperatingChannel; } else { pP2PInfo->InvitationContext.OpChannel = pClientInvitationInfo->OperatingChannel; } pP2PInfo->InvitationContext.Channel = P2PGetChannel(pP2PInfo); if(PeerRole == P2P_GO) { PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; pP2PDeviceDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, msg->devAddr, NULL, NULL); if(NULL != pP2PDeviceDesc) { pP2PDeviceDesc->Role = PeerRole; pP2PDeviceDesc->OperatingChannel = pClientInvitationInfo->OperatingChannel; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Update peer role GO, chnl to: %u\n", pClientInvitationInfo->OperatingChannel)); } } if(P2P_ADAPTER_RTK_SUPPORT_P2P(pP2PInfo->pAdapter) && (TRUE == pP2PInfo->InvitationContext.bPersistentInvitation && PeerRole == P2P_GO || FALSE == pP2PInfo->InvitationContext.bPersistentInvitation) ) { if(RT_MEDIA_CONNECT == MgntLinkStatusQuery(GetDefaultAdapter(pAdapter))) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] invited/reinvoke by GO but default port is connected, assume no client port\n")); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST; break; } } if(P2P_STATUS_SUCCESS == pP2PInfo->InvitationContext.Status && FALSE == pP2PInfo->InvitationContext.bPersistentInvitation ) {// Invited by a P2P Group member to join the group if(FALSE == P2PIsChnlInChnlEntryList(&pP2PInfo->ChannelEntryList, pClientInvitationInfo->OperatingChannel)) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] peer GO op chnl (%u) not supported, reply no common channels\n", pClientInvitationInfo->OperatingChannel)); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_NO_COMMON_CHANNELS; pP2PInfo->ConnectionContext.Status = pP2PInfo->InvitationContext.Status; break; } } if(P2P_STATUS_SUCCESS == pP2PInfo->InvitationContext.Status && TRUE == pP2PInfo->InvitationContext.bPersistentInvitation && P2P_CLIENT == PeerRole ) {// reinvoked as a GO BOOLEAN bToIndicDevDiscComp = FALSE; if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery RT_TRACE_F(COMP_MLME, DBG_LOUD, ("P2P_DOING_DEVICE_DISCOVERY: P2PScanListCeaseScan\n")); p2p_DevList_Unlock(&pP2PInfo->devList); P2PScanListCeaseScan(pP2PInfo); p2p_DevList_Lock(&pP2PInfo->devList); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); bToIndicDevDiscComp = TRUE; } else if(pP2PInfo->bExtendedListening) {// Doing extended listening RT_TRACE_F(COMP_MLME, DBG_LOUD, ("bExtendedListening: P2PScanListCeaseScan\n")); CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), P2P_INVITATION_FRAME_TIMEOUT); ConfigurationTimeout = P2P_INVITATION_FRAME_TIMEOUT; // P2PScanListCeaseScan(pP2PInfo); // P2PExtendedListenComplete(pP2PInfo); } else if(MgntScanInProgress(&pP2PInfo->pAdapter->MgntInfo)) {// Doing normal scan RT_TRACE_F(COMP_MLME, DBG_LOUD, ("bScanInProgress: P2PScanListCeaseScan\n")); p2p_DevList_Unlock(&pP2PInfo->devList); P2PScanListCeaseScan(pP2PInfo); p2p_DevList_Lock(&pP2PInfo->devList); } if(bToIndicDevDiscComp && P2P_DOING_PURE_DEVICE_DISCOVERY(pP2PInfo)) { P2PIndicateDeviceDiscoveryComplete(pP2PInfo); } } // // If failed, we shall not modify the original state machine state. // WFD_OnP2PActionFrame(pAdapter, pRfd, posMpdu); }while(FALSE); if(FALSE == P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { // // Fill the request for indicate to upper layer // LibInvitationReq.DialogToken = msg->dialogToken; LibInvitationReq.InvitorRole = PeerRole; PlatformMoveMemory(LibInvitationReq.TargetDeviceAddress, msg->devAddr, 6); LibInvitationReq.bPersistent = pP2PInfo->InvitationContext.bPersistentInvitation; LibInvitationReq.OpChannel = pP2PInfo->InvitationContext.OpChannel; PlatformMoveMemory(LibInvitationReq.GroupBssid, pP2PInfo->InvitationContext.GroupBssid, 6); PlatformMoveMemory(LibInvitationReq.GroupDeviceAddress, pP2PInfo->InvitationContext.GODeviceAddress, 6); LibInvitationReq.GroupSsidLen = pP2PInfo->InvitationContext.SsidLen; PlatformMoveMemory(LibInvitationReq.GroupSsidBuf, pP2PInfo->InvitationContext.SsidBuf, pP2PInfo->InvitationContext.SsidLen); // // Send Invitation Rsp // StateBackup = pP2PInfo->State; pP2PInfo->State = P2P_STATE_INVITATION_REQ_RECVD; pP2PInfo->Status = pP2PInfo->InvitationContext.Status; CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); p2p_Send_InvitationRsp(pP2PInfo, msg->devAddr, LibInvitationReq.DialogToken); if(P2P_STATUS_SUCCESS == pP2PInfo->InvitationContext.Status || P2P_STATUS_FAIL_INFORMATION_IS_UNAVAILABLE == pP2PInfo->InvitationContext.Status || P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST == pP2PInfo->InvitationContext.Status ) { // Indicate ScanList first to make sure that the SDK is having the list. P2PIndicateScanList(pP2PInfo); P2PIndicateOnInvitationReq(pP2PInfo, &LibInvitationReq); } RT_TRACE_F(COMP_P2P, DBG_LOUD, (" send InvitationRsp with status = %u\n", pP2PInfo->InvitationContext.Status)); pP2PInfo->State = StateBackup; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, ConfigurationTimeout); } if(pGenBufClientInvitationInfo) ReturnGenTempBuffer (pAdapter, pGenBufClientInvitationInfo); p2p_DevList_Unlock(&pP2PInfo->devList); if(RT_STATUS_SUCCESS == rtStatus) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_INVITATION_REQUEST, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("<=== status: %u\n", pP2PInfo->InvitationContext.Status)); return rtStatus; } // // Description: // Handle P2P Go Invitation response packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnInvitationRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; static u8Byte TimeStamp = 0; u4Byte ConfigurationTimeout = 0; // in ms, note that the configuration time out in the P2P IE is defined as units of 10ms P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2POnInvitationRsp(): port number %d state %d\n", pP2PInfo->pAdapter->pNdis62Common->PortNumber, pP2PInfo->State)); FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnInvitationRsp():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_INV_RSP, pRfd, Frame_pSaddr(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_INV_RSP]->msg; if(!p2p_validate_InvitationRsp(pP2PInfo->InvitationContext.InvitorRole, msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Check state if(!P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PInfo->State != P2P_STATE_INVITATION_RSP_WAIT) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] recv InvitationRsp in an invalid state: %u\n", pP2PInfo->State)); rtStatus = RT_STATUS_INVALID_STATE; break; } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("dialog token: %u\n", msg->dialogToken)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2P_OnInvitationRsp():\n", posMpdu->Octet, posMpdu->Length); // Process subelements so that the status element would be stored in the device descriptor. pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->sa, msg, TRUE); if(pP2PDeviceDesc == NULL) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject because of invalid P2P Sub IE\n")); rtStatus = RT_STATUS_INVALID_DATA; break; } // Update ConnectionContext.ConnectingDevice since after P2PProcessSubElements, // its ChannelList or other elements may be modified. PlatformMoveMemory(&pP2PInfo->InvitationContext.InvitedDevice, pP2PDeviceDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); // If we'll be the client, we shall wait for AP configuration timeout pP2PInfo->InvitationContext.Status = (P2P_STATUS_CODE)pP2PDeviceDesc->Status; if(pP2PInfo->InvitationContext.Status == P2P_STATUS_SUCCESS) { WFD_OnP2PActionFrame(pAdapter, pRfd, posMpdu); if(eqMacAddr(pP2PInfo->InvitationContext.GODeviceAddress, pP2PInfo->DeviceAddress)) {// I'm going to be the GO ConfigurationTimeout = 0; //(10 * MAX(pP2PInfo->GOConfigurationTimeout, pP2PInfo->InvitationContext.InvitedDevice.ClientConfigurationTimeout)); } else {// I'm going to be the Client => wait for peer to be ready for connection ConfigurationTimeout = (10 * MAX(pP2PInfo->ClientConfigurationTimeout, pP2PInfo->InvitationContext.InvitedDevice.GOConfigurationTimeout)); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("ConfigurationTimeout: %d (ms)\n", ConfigurationTimeout)); } else { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING]status: %u\n", pP2PInfo->InvitationContext.Status)); } if(P2P_STATUS_FAIL_INFORMATION_IS_UNAVAILABLE == pP2PInfo->InvitationContext.Status) { pP2PInfo->InvitationContext.bWaitingBackwardInvite = TRUE; } // For Win8: Indicate the reception of the invitation response --------------------------- if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { pP2PInfo->State = P2P_STATE_INVITATION_COMPLETE; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, ConfigurationTimeout); break; } // ----------------------------------------------------------------------------- P2PScanListEnterScanCompleteImmediately(pP2PInfo); pP2PInfo->State = P2P_STATE_INVITATION_COMPLETE; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, ConfigurationTimeout); }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); if(RT_STATUS_SUCCESS == rtStatus) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_INVITATION_RESPONSE, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } return rtStatus; } // // Description: // Handle P2P Device Discoverability Request packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnDeviceDiscoverabilityReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); pu1Byte StaInterfaceAddress = NULL; u1Byte i = 0; PRT_WLAN_STA pEntry = NULL; u1Byte Status = P2P_STATUS_SUCCESS; PADAPTER pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? pP2PInfo->pAdapter : GetFirstGOPort(pP2PInfo->pAdapter); PMGNT_INFO pExtMgntInfo = &pExtAdapter->MgntInfo; P2P_MESSAGE msg; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; if(!P2P_ACTING_AS_GO(pP2PInfo)) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Not act as GO!\n")); return RT_STATUS_INVALID_STATE; } FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnDeviceDiscoverabilityReq():\n", posMpdu->Octet, posMpdu->Length); do { if(RT_STATUS_SUCCESS == (rtStatus = p2p_parse_Action(posMpdu, DBG_LOUD, &msg))) if(!p2p_validate_DevDiscReq(&msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Find STA Interface Address for(i = 0;i < ASSOCIATE_ENTRY_NUM; i++) { pEntry = &(pExtMgntInfo->AsocEntry[i]); if(pEntry->bUsed && pEntry->bAssociated && pEntry->bP2PClient) { if(eqMacAddr(pEntry->P2PClientInfoDesc.DeviceAddress, msg.devIdDevAddr)) { StaInterfaceAddress = pEntry->P2PClientInfoDesc.InterfaceAddress; break; } } } if(StaInterfaceAddress == NULL) { Status = P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST; goto send_DevDiscRsp; } // Send Go Discoverability Request to our client. p2p_Send_GoDiscoverabilityReq(pP2PInfo, StaInterfaceAddress, 1); send_DevDiscRsp: // Send DeviceDiscoverabilityRsp to the SA of DeviceDiscoverabilityReq p2p_Send_DevDiscRsp(pP2PInfo, msg.sa, msg.dialogToken, Status); }while(FALSE); p2p_parse_FreeMessage(&msg); FunctionOut(COMP_P2P); return rtStatus; } // // Description: // Handle P2P Device Discoverability Response packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnDeviceDiscoverabilityRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_CLIENT_INFO_DISCRIPTOR pClient = NULL; PP2P_DEVICE_DISCRIPTOR pGO = NULL; P2P_MESSAGE msg; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnDeviceDiscoverabilityRsp():\n", posMpdu->Octet, posMpdu->Length); do { if(RT_STATUS_SUCCESS == (rtStatus = p2p_parse_Action(posMpdu, DBG_LOUD, &msg))) if(!p2p_validate_DevDiscRsp(&msg)) { rtStatus =RT_STATUS_MALFORMED_PKT; break; } // Check state if(pP2PInfo->State != P2P_STATE_DEVICE_DISCOVERABILITY_RSP_WAIT) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Mismatch state = %d\n", pP2PInfo->State)); rtStatus = RT_STATUS_INVALID_STATE; break; } // Check DialogToken if(msg.dialogToken != pP2PInfo->DeviceDiscoverabilityContext.DialogToken) { rtStatus = RT_STATUS_INVALID_DATA; break; } else { pP2PInfo->DeviceDiscoverabilityContext.DialogToken++; } // Get status pP2PInfo->DeviceDiscoverabilityContext.Status = (P2P_STATUS_CODE)msg.status; // Find the client and its GO if(!P2PScanListFindClient(pP2PInfo->ScanList, pP2PInfo->ScanListSize, pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress, NULL, &pGO, &pClient)) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("client not found\n")); break; } if(!pClient) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("client not found\n")); break; } // // Check Capability // if(!(pClient->DeviceCapability & dcP2PClientDiscoverability)) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] dcP2PClientDiscoverability bit in client is not set!\n")); break; } PlatformMoveMemory(&(pP2PInfo->ConnectionContext.ConnectingDevice.DeviceAddress), pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress, 6); pP2PInfo->ConnectionContext.Status = P2P_STATUS_SUCCESS; pP2PInfo->ConnectionContext.DialogToken = IncreaseDialogToken(pP2PInfo->DialogToken); pP2PInfo->ConnectionContext.FindPhaseLoopTimes = P2P_SCAN_FIND_PHASE_LOOP_TIMES; pP2PInfo->ConnectionContext.bGoingToBeGO = FALSE; RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "ConnectionContext.ConnectingDevice:\n", &pP2PInfo->ConnectionContext.ConnectingDevice, sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PInfo->State = P2P_STATE_DEVICE_DISCOVERABILITY_COMPLETE; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); }while(FALSE); p2p_parse_FreeMessage(&msg); return rtStatus; } // // Description: // The client recived the GO discoverability request packet, leave PS mode for while. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnGODiscoverabilityReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PMGNT_INFO pMgntInfo = &(pP2PInfo->pAdapter->MgntInfo); PRT_POWER_SAVE_CONTROL pPSC = GET_POWER_SAVE_CONTROL(pMgntInfo); FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2P_OnGODiscoverabilityReq():\n", posMpdu->Octet, posMpdu->Length); if(pPSC->bLeisurePs || pMgntInfo->dot11PowerSaveMode != eActive) { pMgntInfo->LPSDelayCnt = (pMgntInfo->LPSDelayCnt < 10) ? 10 : pMgntInfo->LPSDelayCnt; // Send one null frame to notify AP that we are awkae. MgntActSet_802_11_PowerSaveMode(pP2PInfo->pAdapter, eActive); } return rtStatus; } // // Description: // Handle P2P Provision Discovery Request packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnProvisionDiscoveryReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); u8Byte CurrentTime = PlatformGetCurrentTime(); static u8Byte LastTime = 0; PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; BOOLEAN bToSendPDRsp = TRUE; u2Byte rspConfigMethod = 0; P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnDeviceDiscoverabilityRsp():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { BOOLEAN bFirstSeen = TRUE; bFirstSeen = (NULL == p2p_DevList_Find(&pP2PInfo->devList, Frame_pSaddr(*posMpdu), P2P_DEV_TYPE_DEV)); p2p_DevList_FlushActionFrames(&pP2PInfo->devList, Frame_pSaddr(*posMpdu), P2P_DEV_TYPE_DEV); if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_PD_REQ, pRfd, Frame_pSaddr(*posMpdu), RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_PD_REQ]->msg; if(!p2p_validate_PDReq(msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } if(CurrentTime - LastTime < 1000000) {// this is to prevent the device from showing notifications to user too often rtStatus = RT_STATUS_PKT_DROP; break; } else { LastTime = CurrentTime; } pP2PDeviceDesc = P2PProcessSubElements(pP2PInfo, pRfd, msg->devAddr, msg, TRUE); if(pP2PDeviceDesc == NULL) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] reject because of invalid P2P Sub IE\n")); rtStatus = RT_STATUS_INVALID_DATA; break; } // Check ConfigMethod compatible if(pP2PInfo->WpsAttributes.ConfigMethod & msg->wpsConfigMethods) { rspConfigMethod = msg->wpsConfigMethods; } else {// config method not compatible RT_TRACE_F(COMP_P2P, DBG_LOUD, ("[WARNING] recvd CM (%u) not compatible with my CM (%u)\n", msg->wpsConfigMethods, pP2PInfo->WpsAttributes.ConfigMethod)); rspConfigMethod = 0; // set to NULL to indicate failure } // Indicate OnPDReq before P2PSvc processes it if(bFirstSeen) { // Indicate ScanList first to make sure that the SDK is having the list. P2PIndicateScanList(pP2PInfo); } // Indicate to upper layer P2PIndicateOnProvisionDiscoveryReq(pP2PInfo, rspConfigMethod, msg->devAddr, &pP2PDeviceDesc->WpsAttributes); P2PSvc_OnPDReq(pP2PInfo->pP2PSvcInfo, msg->devAddr, msg->wpsConfigMethods, &msg->p2pAttributes.os, &bToSendPDRsp); if(bToSendPDRsp && 0 == pP2PDeviceDesc->ListenChannel) {// We need to send PD rsp, and we don't have peer's Listen Channel if(msg->_listenChannel) pP2PDeviceDesc->ListenChannel = msg->listenChannel; } // Update the latest scan list to upper layer. P2PScanListCopy(pP2PInfo->ScanList4Query, &pP2PInfo->ScanList4QuerySize, pP2PInfo->ScanList, pP2PInfo->ScanListSize); P2PIndicateScanList(pP2PInfo); WFD_OnP2PActionFrame(pAdapter, pRfd, posMpdu); if(FALSE == P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(bToSendPDRsp) { BOOLEAN bSupportTxReport = FALSE; // // Send ProvisionDiscoveryRsp // if(P2P_DEVICE == pP2PInfo->Role) { CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); } p2p_Send_PDRsp(pP2PInfo, msg->devAddr, msg->dialogToken, &msg->p2pAttributes.os, rspConfigMethod, &bSupportTxReport); if(FALSE == bSupportTxReport) { P2PSvc_OnPDRspSent(pP2PInfo->pP2PSvcInfo, TRUE); } } } }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); if(rtStatus == RT_STATUS_SUCCESS) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_PROVISION_DISCOVERY_REQUEST, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } FunctionOut(COMP_P2P); return rtStatus; } // // Description: // Handle P2P Provistion Discovery Response packet for P2P function. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnProvisionDiscoveryRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); P2P_DEV_LIST_ENTRY *pDev = NULL; P2P_MESSAGE *msg = NULL; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnDeviceDiscoverabilityRsp():\n", posMpdu->Octet, posMpdu->Length); p2p_DevList_Lock(&pP2PInfo->devList); do { if(RT_STATUS_SUCCESS != (rtStatus = p2p_DevList_RxUpdate(&pP2PInfo->devList, P2P_FID_PD_RSP, pRfd, pP2PInfo->ProvisionDiscoveryContext.go ? pP2PInfo->ProvisionDiscoveryContext.goBssid : pP2PInfo->ProvisionDiscoveryContext.devAddr, RT_GetChannelNumber(pP2PInfo->pAdapter), &pDev)) ) { break; } msg = pDev->rxFrames[P2P_FID_PD_RSP]->msg; if(!p2p_validate_PDRsp(msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Check DialogToken if(!P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && msg->dialogToken != pDev->txFrames[P2P_FID_PD_REQ]->token ) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] dialog token mismatch: peer(%u), mine(%u)\n", msg->dialogToken, pDev->txFrames[P2P_FID_PD_REQ]->token)); rtStatus = RT_STATUS_INVALID_DATA; break; } p2p_DevList_DialogTokenUpdate(pDev); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("CM requested: %u, CM responded: %u\n", pDev->p2p->pdConfigMethod, msg->wpsConfigMethods)); if(!P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(pDev->p2p->pdConfigMethod == msg->wpsConfigMethods) { pP2PInfo->ConnectionContext.Status = P2P_STATUS_SUCCESS; } else { pP2PInfo->ConnectionContext.Status = P2P_STATUS_FAIL_PROVISION_DISCOVERY_FAILED; } } p2p_DevList_Unlock(&pP2PInfo->devList); CustomScan_TermReq(GET_CUSTOM_SCAN_INFO(pAdapter), FALSE); p2p_DevList_Lock(&pP2PInfo->devList); P2PSvc_OnPDRsp(pP2PInfo->pP2PSvcInfo, pDev->mac, pDev->p2p->pdConfigMethod, msg->wpsConfigMethods, &msg->p2pAttributes.os ); pP2PInfo->State = P2P_STATE_PROVISION_DISCOVERY_COMPLETE; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 1); }while(FALSE); RT_TRACE_F(COMP_P2P, DBG_LOUD, (" %u\n", pP2PInfo->ConnectionContext.Status)); p2p_DevList_Unlock(&pP2PInfo->devList); if(rtStatus == RT_STATUS_SUCCESS) { p2p_IndicateActionFrameReceived(pP2PInfo, P2P_EVENT_RECEIVED_PROVISION_DISCOVERY_RESPONSE, RT_STATUS_SUCCESS, posMpdu->Octet, posMpdu->Length); } return rtStatus; } // // Description: // Handle Service Discovery Request packet. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnSDReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); pu1Byte SrcAddr = Frame_pSaddr(*posMpdu); // this shall be the Device Address u1Byte DialogToken; PP2P_SERVICE_REQ_TLV pSDReqRecvd = NULL; pu1Byte pSDReqRecvdSize = NULL; pu1Byte pTLVStart = posMpdu->Octet + FRAME_OFFSET_GAS_INIT_REQ_SERVICE_REQ_TLV; pu1Byte pTLVCurrent = NULL; BOOLEAN bFragmentSDRsp = FALSE; u1Byte i; BOOLEAN bToSendSDRsp = TRUE; FunctionIn(COMP_P2P); if(pP2PInfo->SDContext.bDoingServiceDiscovery) {// we are doing service disocvery, ignore further requests RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] we are doing service disocvery, ignore further requests!\n")); return RT_STATUS_INVALID_STATE; } pP2PInfo->SDContext.bDoingServiceDiscovery = TRUE; // // Make sure we can read all the mandatory field of the SDReq // if(posMpdu->Length < FRAME_OFFSET_GAS_INIT_REQ_SERVICE_REQ_TLV) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] frame lengh (%u) < min SDReq lenght (%u)\n", posMpdu->Length, FRAME_OFFSET_GAS_INIT_REQ_SERVICE_REQ_TLV)); return RT_STATUS_MALFORMED_PKT; } //RT_PRINT_DATA(COMP_P2P, DBG_LOUD, // "The ServiceDiscoveryReq Content : ", // osPacket.Octet, osPacket.Length); // // Set the Status to success // pP2PInfo->SDContext.Status = P2P_SD_STATUS_SUCCESS; // // Store Source Device Address // cpMacAddr(pP2PInfo->SDContext.TargetDeviceAddress, SrcAddr); // // Store Dialog Token // DialogToken = *((pu1Byte)(posMpdu->Octet + FRAME_OFFSET_GAS_INIT_REQ_DIALOG_TOKEN)); pP2PInfo->SDContext.DialogToken = DialogToken; // // Reset the buffer we used to store the received SDReq // pSDReqRecvd = pP2PInfo->SDContext.ServiceReqRecvd; pSDReqRecvdSize = &pP2PInfo->SDContext.ServiceReqRecvdSize; PlatformZeroMemory(pSDReqRecvd, sizeof(P2P_SERVICE_REQ_TLV) * P2P_SD_MAX_SERVICES); *pSDReqRecvdSize = 0; // // Get ALL Service Req TLVs // pTLVCurrent = pTLVStart; while(TRUE) { u2Byte TLVLenField; u2Byte QueryDataLen; // Check if we have enough room for the TLV if(*pSDReqRecvdSize >= P2P_SD_MAX_SERVICES) { break; } // Validate the TLV length if((pTLVCurrent + OFFSET_SERVICE_REQ_TLV_QUERY_DATA) > (posMpdu->Octet + posMpdu->Length)) { //pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_REQUEST; break; } // Read the length field of the TLV TLVLenField = ReadEF2Byte(pTLVCurrent + OFFSET_SERVICE_REQ_TLV_LEN); if(TLVLenField < (u2Byte)(OFFSET_SERVICE_REQ_TLV_QUERY_DATA - OFFSET_SERVICE_REQ_TLV_SERVICE_PROT_TYPE)) {// invalid TLV len pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_REQUEST; break; } if((pTLVCurrent + 2 + TLVLenField) > (posMpdu->Octet + posMpdu->Length)) {// invalid TLV len pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_REQUEST; break; } // Read Sercive Protocol Type pSDReqRecvd[*pSDReqRecvdSize].ServiceDesc.ServiceType = (P2P_SD_PROTOCOL) ( *((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_REQ_TLV_SERVICE_PROT_TYPE)) ); // Read Service Transaction ID pSDReqRecvd[*pSDReqRecvdSize].TransactionID = *((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_REQ_TLV_SERVICE_TRANSACTION_ID)); // Get Query Data length QueryDataLen = TLVLenField - 2; // exclude ServiceProtType(1) and ServiceTransactionID(1) // Check if we can copy the Query Data to our buffer if(QueryDataLen > P2P_MAX_SERVICE_DESCRIPTOR_BUFFER_LEN) { pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_REQUEST; break; } // Copy Query Data PlatformMoveMemory(pSDReqRecvd[*pSDReqRecvdSize].ServiceDesc.Buffer, pTLVCurrent + OFFSET_SERVICE_REQ_TLV_QUERY_DATA, QueryDataLen); pSDReqRecvd[*pSDReqRecvdSize].ServiceDesc.BufferLength = QueryDataLen; (*pSDReqRecvdSize)++; if(*pSDReqRecvdSize == P2P_SD_MAX_SERVICES) { break; } // Update pTLVCurrent pTLVCurrent += (2 + TLVLenField); } if(pP2PInfo->SDContext.ServiceReqRecvdSize == 0) { pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_REQUEST; } if(pP2PInfo->SDContext.Status != P2P_SD_STATUS_SUCCESS) { goto Exit_P2POnSDReq; } P2PSvc_OnSDReq(pP2PInfo->pP2PSvcInfo, SrcAddr, DialogToken, *pSDReqRecvdSize, pSDReqRecvd, &bToSendSDRsp); if(!bToSendSDRsp) { pP2PInfo->SDContext.bDoingServiceDiscovery = FALSE; goto Exit_P2POnSDReqNoRsp; } // // Print all Service Req TLVs recvd // for(i = 0; i < *pSDReqRecvdSize; i++) { RT_TRACE(COMP_P2P, DBG_LOUD, ("Servicd Req TLV %u: Protocol: %u\n", i, pSDReqRecvd[i].ServiceDesc.ServiceType)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "Query Data", pSDReqRecvd[i].ServiceDesc.Buffer, pSDReqRecvd[i].ServiceDesc.BufferLength); } Exit_P2POnSDReq: if(pP2PInfo->SDContext.Status == P2P_SD_STATUS_SUCCESS) { CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), P2P_SERVICE_DISCOVERY_TIMEOUT); P2PIndicateOnSDReq(pP2PInfo, &pP2PInfo->SDContext); } else { p2p_Send_SDRsp(pP2PInfo, SrcAddr, DialogToken, pP2PInfo->SDContext.Status, bFragmentSDRsp); } Exit_P2POnSDReqNoRsp: RT_TRACE_F(COMP_P2P, DBG_LOUD, (" Status: %u, DialogToken: %u\n", pP2PInfo->SDContext.Status, DialogToken)); return rtStatus; } // // Description: // Handle Service Discovery Response packet. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnSDRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PP2P_SD_CONTEXT pSDContext = &pP2PInfo->SDContext; pu1Byte pTLVStart = posMpdu->Octet + FRAME_OFFSET_GAS_INIT_RSP_TLV; pu1Byte pTLVCurrent = NULL; u2Byte QueryRspLen; u2Byte TLVLen = 0; BOOLEAN bFragment = FALSE; FunctionIn(COMP_P2P); // Check state //if(pP2PInfo->State != P2P_STATE_SERVICE_DISCOVERY_RSP_WAIT) //{ // RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] current state (%d) is invalid!\n", pP2PInfo->State)); // return RT_STATUS_INVALID_STATE; //} // Check if the SDRsp is from the intended peer if(!eqMacAddr(pSDContext->TargetDeviceAddress, Frame_pSaddr(*posMpdu))) { RT_PRINT_ADDR(COMP_P2P, DBG_WARNING, "P2P_OnSDRsp():[WARNING] mismatch addr = ", pSDContext->TargetDeviceAddress); return RT_STATUS_INVALID_DATA; } // Check length if(posMpdu->Length < FRAME_OFFSET_GAS_INIT_RSP_QUERY_DATA) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Invalid length of packet!\n")); return RT_STATUS_MALFORMED_PKT; } // // Check Dialog Token // After Check length, we are safe to read Dialog Token // if(*((pu1Byte)(posMpdu->Octet + FRAME_OFFSET_GAS_INIT_RSP_DIALOG_TOKEN)) != pSDContext->DialogToken) {// Dialog Token mismatch RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] mismatch token target (%d) and mine (%d)!\n", *((pu1Byte)(posMpdu->Octet + FRAME_OFFSET_GAS_INIT_RSP_DIALOG_TOKEN)), pSDContext->DialogToken)); return RT_STATUS_INVALID_DATA; } // // Clear ServiceRspRecvd for storing the Rsp we recvd // PlatformZeroMemory(pSDContext->ServiceRspRecvd, sizeof(P2P_SERVICE_RSP_TLV) * P2P_SD_MAX_SERVICES); pSDContext->ServiceRspRecvdSize = 0; // // Get SDRsp fields // { // Status (11u) // Ignore // GAS Comeback Delay if(ReadEF2Byte(posMpdu->Octet + FRAME_OFFSET_GAS_INIT_RSP_COMEBACK_DELAY)) { bFragment = TRUE; goto Exit_P2POnSDRsp; // the SDRsp shall be empty in this case // Fragment is the only case that there is no TLV in the SDRsp // So below we can assume that we shall have at lease 1 TLV. } // AD Prot IE // Ignore // Query Rsp Len QueryRspLen = ReadEF2Byte(posMpdu->Octet + FRAME_OFFSET_GAS_INIT_RSP_LEN); // ignore // Service update indicator pSDContext->ServiceUpdateIndicator = ReadEF2Byte(posMpdu->Octet + FRAME_OFFSET_GAS_INIT_RSP_SERVICE_UPDATE_INDICATOR); // ignore // // Read the TLVs, a valid Rsp shall have at lease 1 TLV // { u1Byte index; pTLVCurrent = pTLVStart; PlatformZeroMemory(pP2PInfo->SDContext.ServiceRspRecvd, sizeof(P2P_SERVICE_RSP_TLV) * P2P_SD_MAX_SERVICES); pP2PInfo->SDContext.ServiceRspRecvdSize = 0; index = pP2PInfo->SDContext.ServiceRspRecvdSize; while(TRUE) { u2Byte ResponseDataLen = 0; u1Byte TransactionId = 0; // Check if we have enough room for the TLV if(index >= P2P_SD_MAX_SERVICES) { break; } // Make sure we can read until the end of Status Code filed, which is right before RSP_DATA if((pTLVCurrent + OFFSET_SERVICE_RSP_TLV_RSP_DATA) > (posMpdu->Octet + posMpdu->Length)) { pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_RESPONSE_1; break; } // Length TLVLen = (ReadEF2Byte(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_LEN)); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("TLVLen: %u\n", TLVLen)); if(TLVLen < (u2Byte)(OFFSET_SERVICE_RSP_TLV_RSP_DATA - OFFSET_SERVICE_RSP_TLV_SERVICE_PROT_TYPE)) {// invalid TLV len pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_RESPONSE_2; break; } if((pTLVCurrent + 2 + TLVLen) > (posMpdu->Octet + posMpdu->Length)) {// invalid TLV len pP2PInfo->SDContext.Status = P2P_SD_STATUS_BAD_RESPONSE_3; break; } // Service Protocol Type (pP2PInfo->SDContext.ServiceRspRecvd)[index].ServiceDesc.ServiceType = (P2P_SD_PROTOCOL) (*((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_SERVICE_PROT_TYPE)) ); // Transactio ID TransactionId = (*((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_SERVICE_TRANSACTION_ID))); // Status Code (pP2PInfo->SDContext.ServiceRspRecvd)[index].Status = (P2P_SD_STATUS_CODE) (*((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_STATUS)) ); // For the last status (status of the entire SDRsp), we currently get it from the last TLV pP2PInfo->SDContext.Status = (pP2PInfo->SDContext.ServiceRspRecvd)[index].Status; // Response Data if((pP2PInfo->SDContext.ServiceRspRecvd)[index].Status == P2P_SD_STATUS_SUCCESS) { ResponseDataLen = TLVLen - 3; if(ResponseDataLen > P2P_MAX_SERVICE_DESCRIPTOR_BUFFER_LEN) {// buffer overflow RT_TRACE(COMP_P2P, DBG_LOUD, ("Buffer size overflow: (%u) > (%u) \n", ResponseDataLen, P2P_MAX_SERVICE_DESCRIPTOR_BUFFER_LEN)); break; } PlatformMoveMemory((pP2PInfo->SDContext.ServiceRspRecvd)[index].ServiceDesc.Buffer, pTLVCurrent + OFFSET_SERVICE_RSP_TLV_RSP_DATA, ResponseDataLen); (pP2PInfo->SDContext.ServiceRspRecvd)[index].ServiceDesc.BufferLength = ResponseDataLen; RT_PRINT_STR(COMP_P2P, DBG_LOUD, "Recv TLV: ", (pP2PInfo->SDContext.ServiceRspRecvd)[index].ServiceDesc.Buffer, (pP2PInfo->SDContext.ServiceRspRecvd)[index].ServiceDesc.BufferLength); } if(P2P_SD_PROTOCOL_P2PSVC == (pP2PInfo->SDContext.ServiceRspRecvd)[index].ServiceDesc.ServiceType) { BOOLEAN bNeedFurtherProcess = FALSE; P2PSvc_OnSDRsp(pP2PInfo->pP2PSvcInfo, Frame_pSaddr(*posMpdu), TransactionId, pP2PInfo->SDContext.ServiceRspRecvd + index, &bNeedFurtherProcess); if(!bNeedFurtherProcess) { goto Exit_P2POnSDRsp_SilentExit; // so current dev disc will not be ceased } } pP2PInfo->SDContext.ServiceRspRecvdSize++; index++; // Go to next TLV pTLVCurrent += (5 + ResponseDataLen); // 5 = length(2) + SvcProtType(1), SvcTransactionID(1), Status(1) // Check if this is the last TLV if(pTLVCurrent >= (posMpdu->Octet+ posMpdu->Length)) { break; } } } } Exit_P2POnSDRsp: if(bFragment) { // Update SDContext pSDContext->bDoingServiceDiscovery = TRUE; pSDContext->bFragment = TRUE; pSDContext->FragmentID = 0; // we are expecting FragmentID 0 pSDContext->ServiceRspRecvdSize = 0; pSDContext->ANQPQueryRspFieldToSendSize = 0; pSDContext->ANQPQueryRspFieldToSendOffset = 0; // // Since P2PMgntTimerCallback() checks bScanInProgress before it enters the state machine, // we can't use the state machine to deal with the comeback procedure. // p2p_Send_SDComebackReq(pP2PInfo, pP2PInfo->SDContext.TargetDeviceAddress, pP2PInfo->SDContext.DialogToken); pP2PInfo->State = P2P_STATE_SERVICE_DISCOVERY_COMEBACK_RSP_WAIT; } else { pP2PInfo->State = P2P_STATE_SERVICE_DISCOVERY_COMPLETE; if(pSDContext->Status == P2P_SD_STATUS_SUCCESS) { P2PIndicateOnSDRsp(pP2PInfo, pSDContext); } // Entery ScanComplete immediately P2PScanListEnterScanCompleteImmediately(pP2PInfo); // Entery P2P_STATE_SERVICE_DISCOVERY_COMPLETE (almost) right after ScanComplete PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 100); } Exit_P2POnSDRsp_SilentExit: RT_TRACE_F(COMP_P2P, DBG_LOUD, ("status: %u, bFragment: %u\n", pSDContext->Status, bFragment)); return rtStatus; } // // Description: // Handle Service Discovery Request comback packet. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnSDComebackReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); pu1Byte SrcAddr = Frame_pSaddr(*posMpdu); u1Byte DialogToken = 0; BOOLEAN bMoreData = FALSE; u2Byte BytesToCopy; u2Byte RemainingBytes; FunctionIn(COMP_P2P); // // Check status // if(!(pP2PInfo->SDContext.bDoingServiceDiscovery && pP2PInfo->SDContext.bFragment)) {// not expecting Comeback Req RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Not expect comeback request pkt!\n")); return RT_STATUS_INVALID_STATE; } // // Check peer // if(!eqMacAddr(pP2PInfo->SDContext.TargetDeviceAddress, SrcAddr)) { RT_PRINT_ADDR(COMP_P2P, DBG_WARNING, "P2P_OnSDComebackReq():[WARNING] mismatch addr = ", SrcAddr); return RT_STATUS_INVALID_DATA; } // // Check Length // if(posMpdu->Length < FRAME_OFFSET_GAS_COMEBACK_REQ_DIALOG_TOKEN + 1) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] frame lengh (%u) < min SDReq lenght (%u)\n", posMpdu->Length, FRAME_OFFSET_GAS_COMEBACK_REQ_DIALOG_TOKEN + 1)); return RT_STATUS_MALFORMED_PKT; } // // Check DialogToken // DialogToken = *((pu1Byte)posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_REQ_DIALOG_TOKEN); if(DialogToken != pP2PInfo->SDContext.DialogToken) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("[WARNING] Target DialogToken (%d) and mine (%d) are mismatch\n", DialogToken, pP2PInfo->SDContext.DialogToken)); return RT_STATUS_INVALID_DATA; } // // Decide value of bMoreData // if(pP2PInfo->SDContext.ANQPQueryRspFieldToSendOffset >= pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] no more data to send\n")); return RT_STATUS_INVALID_STATE; } else if(pP2PInfo->SDContext.ANQPQueryRspFieldToSendOffset< pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize) { u2Byte BytesSent = pP2PInfo->SDContext.ANQPQueryRspFieldToSendOffset; u2Byte TotalBytes = pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize; RemainingBytes = TotalBytes - BytesSent; if(RemainingBytes > pP2PInfo->SDRspFragmtntThreshold) { bMoreData = TRUE; BytesToCopy = pP2PInfo->SDRspFragmtntThreshold; } else { bMoreData = FALSE; BytesToCopy = RemainingBytes; } } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Remaining bytes(%u), Bytes to Copy(%u), bMoreData(%u)\n", RemainingBytes, BytesToCopy, bMoreData)); pP2PInfo->SDWaitForComebackReqSlotCount = 0; p2p_Send_SDComebackRsp(pP2PInfo, SrcAddr, DialogToken, BytesToCopy, bMoreData); pP2PInfo->SDContext.ANQPQueryRspFieldToSendOffset += BytesToCopy; pP2PInfo->SDContext.FragmentID++; if(!bMoreData) { PlatformZeroMemory(&pP2PInfo->SDContext, sizeof(P2P_SD_CONTEXT)); CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), P2P_SERVICE_DISCOVERY_COMEBACK_TIMEOUT); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("bMoreData: %u\n", bMoreData)); return rtStatus; } P2P_SD_STATUS_CODE P2POnANQPQueryRspField( IN PP2P_INFO pP2PInfo, IN pu1Byte ANQPQueryRspFieldBuf, IN u2Byte ANQPQueryRspFieldSize, IN OUT PP2P_SERVICE_RSP_TLV ServiceRspTLVList, IN OUT pu1Byte pServiceRspTLVListSize ) { // // ANQP Query Rsp Field format: // InfoID(2), Length(2), OI(3), OUISubType(1), SvcUpdateIndic(2), TLVs // // Note that we can store maximul P2P_SD_MAX_SERVICES TLVs // pu1Byte pTLVStart = ANQPQueryRspFieldBuf + 2 + 2 + 3 + 1 + 2; pu1Byte pTLVCurrent = pTLVStart; u2Byte TLVLen; P2P_SD_STATUS_CODE Ret = P2P_SD_STATUS_SUCCESS; // // Reset the output TLV list // *pServiceRspTLVListSize = 0; while(TRUE) { u2Byte ResponseDataLen = 0; // Check if we have enough room for the TLV if(*pServiceRspTLVListSize >= P2P_SD_MAX_SERVICES) { break; } // Validate the TLV length if((pTLVCurrent + OFFSET_SERVICE_RSP_TLV_RSP_DATA) > (ANQPQueryRspFieldBuf + ANQPQueryRspFieldSize)) { Ret = P2P_SD_STATUS_BAD_RESPONSE_1; break; } // Length TLVLen = (ReadEF2Byte(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_LEN)); if(TLVLen < (u2Byte)(OFFSET_SERVICE_RSP_TLV_RSP_DATA - OFFSET_SERVICE_RSP_TLV_SERVICE_PROT_TYPE)) {// invalid TLV len Ret = P2P_SD_STATUS_BAD_RESPONSE_2; break; } // if((u8Byte)(pTLVCurrent + 2 + TLVLen) > (u8Byte)(ANQPQueryRspFieldBuf + ANQPQueryRspFieldSize)) if((pTLVCurrent + 2 + TLVLen) > (ANQPQueryRspFieldBuf + ANQPQueryRspFieldSize)) {// invalid TLV len Ret = P2P_SD_STATUS_BAD_RESPONSE_3; break; } // Service Protocol Type (ServiceRspTLVList)[*pServiceRspTLVListSize].ServiceDesc.ServiceType = (P2P_SD_PROTOCOL) *((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_SERVICE_PROT_TYPE)); // Status Code (ServiceRspTLVList)[*pServiceRspTLVListSize].Status = (P2P_SD_STATUS_CODE) *((pu1Byte)(pTLVCurrent + OFFSET_SERVICE_RSP_TLV_STATUS)); // For the last status (status of the entire SDComebackRsp), we currently get it from the last TLV Ret = (ServiceRspTLVList)[*pServiceRspTLVListSize].Status; //DbgPrint("Status: %u\n", Ret); // Response Data if((ServiceRspTLVList)[*pServiceRspTLVListSize].Status == P2P_SD_STATUS_SUCCESS) { ResponseDataLen = TLVLen - 3; if(ResponseDataLen > P2P_MAX_SERVICE_DESCRIPTOR_BUFFER_LEN) {// buffer overflow RT_TRACE(COMP_P2P,DBG_LOUD, ("Buffer size overflow: (%u) > (%u) \n", ResponseDataLen, P2P_MAX_SERVICE_DESCRIPTOR_BUFFER_LEN)); break; } PlatformMoveMemory((ServiceRspTLVList)[*pServiceRspTLVListSize].ServiceDesc.Buffer, pTLVCurrent + OFFSET_SERVICE_RSP_TLV_RSP_DATA, ResponseDataLen); (ServiceRspTLVList)[*pServiceRspTLVListSize].ServiceDesc.BufferLength = ResponseDataLen; //DbgPrint("ResponseDataLen: %u\n", ResponseDataLen); } (*pServiceRspTLVListSize)++; // Go to next TLV pTLVCurrent += (5 + ResponseDataLen); // 5 = length(2) + SvcProtType(1), SvcTransactionID(1), Status(1) // Check if this is the last TLV // if((u8Byte)pTLVCurrent >= (u8Byte)(ANQPQueryRspFieldBuf + ANQPQueryRspFieldSize)) if(pTLVCurrent >= (ANQPQueryRspFieldBuf + ANQPQueryRspFieldSize)) { break; } } return Ret; } // // Description: // Handle Service Discovery Response comback packet. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // None // RT_STATUS P2P_OnSDComebackRsp( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); BOOLEAN bMoreData = FALSE; u1Byte FragmentID = 0; u2Byte QueryRspLen = 0; BOOLEAN bBufferOut = FALSE; FunctionIn(COMP_P2P); // // Check state // if(pP2PInfo->State != P2P_STATE_SERVICE_DISCOVERY_COMEBACK_RSP_WAIT) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Invalid state (%d)!\n", pP2PInfo->State)); return RT_STATUS_INVALID_STATE; } // Check if the SDRsp is from the intended peer if(!eqMacAddr(pP2PInfo->SDContext.TargetDeviceAddress, Frame_pSaddr(*posMpdu))) { RT_PRINT_ADDR(COMP_P2P, DBG_WARNING, "P2P_OnSDComebackRsp():[WARNING] Mismatch for src addr = ", Frame_pSaddr(*posMpdu)); return RT_STATUS_INVALID_DATA; } // // Check Length // if(posMpdu->Length < FRAME_OFFSET_GAS_COMEBACK_RSP_TLV) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Invalid pkt length!\n")); return RT_STATUS_MALFORMED_PKT; } // // Check Dialog Token // if(*((pu1Byte)posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_RSP_DIALOG_TOKEN) != pP2PInfo->SDContext.DialogToken) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Pkt DialogToken (%d) and mine (%d) are mismatch\n", *((pu1Byte)posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_RSP_DIALOG_TOKEN), pP2PInfo->SDContext.DialogToken)); return RT_STATUS_INVALID_DATA; } // // Get FragmentID field (including MoreData bit and FragmentID) // { u1Byte GASQueryRspFragmentID = *((pu1Byte)posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_RSP_FRAG_ID); RT_TRACE(COMP_P2P, DBG_LOUD, ("GASQueryRspFragmentID: %u\n", GASQueryRspFragmentID)); if(GASQueryRspFragmentID & 0x80) { bMoreData = TRUE; } FragmentID = GASQueryRspFragmentID & (0x7F); } // // Check FragmentID // if(FragmentID != pP2PInfo->SDContext.FragmentID) { RT_TRACE(COMP_P2P, DBG_WARNING, ("[WARNING] expected FragmentID mismatch: expected (%u), recvd (%u)\n", pP2PInfo->SDContext.FragmentID, FragmentID)); return RT_STATUS_INVALID_DATA; } else { pP2PInfo->SDContext.FragmentID++; // indicates that we are expecting the next fragment } // // Get SDComebackRsp fields // { // Status (11u) // Ignore // GAS Rsp Fragment ID // Already processed // GAS Comeback Delay // Ignore // AD Prot IE // Ignore // Query Rsp Len QueryRspLen = ReadEF2Byte(posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_RSP_LEN); // ignore // // Defrag ANQP Query Rsp Field // if(FRAME_OFFSET_GAS_COMEBACK_RSP_QUERY_RSP + QueryRspLen <= posMpdu->Length) { if(pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize + QueryRspLen <= P2P_MAX_SERVICE_BUF_SIZE) { PlatformMoveMemory(pP2PInfo->SDContext.ANQPQueryRspFieldToSendBuf + pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize, posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_RSP_QUERY_RSP, QueryRspLen); pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize += QueryRspLen; } else { // Prefast warning C6328: Size mismatch ignore #pragma warning (disable: 6328) RT_TRACE_F(COMP_P2P, DBG_SERIOUS, ("[ERROR] no enough buf for the ComebackRsp: buflen(%u) + QueryRspLen(%u) > bufsize(%u)\n", pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize, QueryRspLen, P2P_MAX_SERVICE_BUF_SIZE)); bBufferOut = TRUE; } } // Service update indicator if(FragmentID == 0) { pP2PInfo->SDContext.ServiceUpdateIndicator = ReadEF2Byte(posMpdu->Octet + FRAME_OFFSET_GAS_COMEBACK_RSP_SERVICE_UPDATE_INDICATOR); } if(QueryRspLen == 0) { return rtStatus; } } if(bMoreData) { p2p_Send_SDComebackReq(pP2PInfo, pP2PInfo->SDContext.TargetDeviceAddress, pP2PInfo->SDContext.DialogToken); } else { if(!bBufferOut) { RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "ANQP Defrag result: ", pP2PInfo->SDContext.ANQPQueryRspFieldToSendBuf, pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize); pP2PInfo->SDContext.Status = P2POnANQPQueryRspField(pP2PInfo, pP2PInfo->SDContext.ANQPQueryRspFieldToSendBuf, pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize, pP2PInfo->SDContext.ServiceRspRecvd, &pP2PInfo->SDContext.ServiceRspRecvdSize); if(pP2PInfo->SDContext.Status == P2P_SD_STATUS_SUCCESS) { P2PIndicateOnSDRsp(pP2PInfo, &pP2PInfo->SDContext); } } pP2PInfo->State = P2P_STATE_SERVICE_DISCOVERY_COMPLETE; P2PScanListEnterScanCompleteImmediately(pP2PInfo); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Status: %u, Recvd FragID: %u, nRspTLVs got from defragmented ANQP: %u\n", pP2PInfo->SDContext.Status, FragmentID, pP2PInfo->SDContext.ServiceRspRecvdSize)); return rtStatus; } BOOLEAN P2PCommonChannelArrived( IN PP2P_INFO pP2PInfo, IN P2P_DEV_LIST_ENTRY *pDev, IN OCTET_STRING osPacket ) { BOOLEAN bPacketTypeValid = FALSE; BOOLEAN bCommonChannelArrived = FALSE; P2P_STATE NextState = P2P_STATE_INITIALIZED; PP2P_DEVICE_LIST_ENTRY pP2PDeviceListEntry = NULL; u4Byte BoostInitGainValue = 0; RT_TRACE_F(COMP_MLME, DBG_LOUD, ("p2p state 0x%x bPreGroupFormation %d bDoingProvisionDiscovery %d bToSendInvitationReqOnProbe %d\n", pP2PInfo->State, pP2PInfo->bPreGroupFormation, pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery, pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe)); if(pP2PInfo->bPreGroupFormation) {// In this case, we are in pre GO Nego phase. We will start a GO Nego procedure. switch(P2P_FRAME_GET_TYPE(osPacket.Octet)) { case Type_Probe_Req: bPacketTypeValid = TRUE; break; case Type_Probe_Rsp: bPacketTypeValid = TRUE; break; default: break; } if(!bPacketTypeValid) { return FALSE; } // // PF #3: // if the target is a GO, then it replies ProbeRsp with its Interface Addr, // so here, we have to compare using its Interface Address instead of Device Address. // 2010.05.11, haich. // if(pP2PInfo->ConnectionContext.ConnectingDevice.Role == P2P_GO) { if(!eqMacAddr(pP2PInfo->ConnectionContext.ConnectingDevice.IntendedP2PInterfaceAddress, pDev->mac)) { return FALSE; } } else { if(!eqMacAddr(pP2PInfo->ConnectionContext.ConnectingDevice.DeviceAddress, pDev->mac)) { return FALSE; } } RT_TRACE_F(COMP_MLME, DBG_LOUD, ("P2PScanListCeaseScan\n")); p2p_DevList_Unlock(&pP2PInfo->devList); P2PScanListCeaseScan(pP2PInfo); p2p_DevList_Lock(&pP2PInfo->devList); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PCommonChannelArrived(): Recv ProbeRsp from the target device = > start Group Formation\n")); pP2PInfo->bPreGroupFormation = FALSE; if(pP2PInfo->State == P2P_STATE_GO_NEGO_REQ_RECVD || pP2PInfo->State == P2P_STATE_GO_NEGO_RSP_SEND || pP2PInfo->State == P2P_STATE_GO_NEGO_CONFIRM_WAIT || pP2PInfo->State == P2P_STATE_GO_NEGO_COMPLETE) { RT_TRACE_F(COMP_MLME, DBG_LOUD, ("already do GONego!!\n")); pP2PInfo->bPreGroupFormation = FALSE; return FALSE; } NextState = P2P_STATE_GO_NEGO_REQ_SEND; bCommonChannelArrived = TRUE; } if(pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery) { u1Byte *pdTargetMac = NULL; if(pP2PInfo->ProvisionDiscoveryContext.go) pdTargetMac = pP2PInfo->ProvisionDiscoveryContext.goBssid; else pdTargetMac = pP2PInfo->ProvisionDiscoveryContext.devAddr; if(eqMacAddr(pDev->mac, pdTargetMac)) {// source is the device we are trying to invite RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PCommonChannelArrived(): Recv Probe from the provision discovery request target, state: %u\n", pP2PInfo->State)); // // Retrieve specific P2P device info. from Win8 Specific Device Information Pool to initiate boost initial gain // 2014.03.23. // pP2PDeviceListEntry = P2PDeviceListFind(&pP2PInfo->DeviceList, pDev->mac); if(pP2PDeviceListEntry) { if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { BoostInitGainValue = TRUE; BoostInitGainValue = (BoostInitGainValue | ((pP2PDeviceListEntry->RecvSignalPower+110) << 8)); pP2PInfo->pAdapter->HalFunc.SetHwRegHandler(pP2PInfo->pAdapter, HW_VAR_BOOST_INIT_GAIN_OS, (pu1Byte)&BoostInitGainValue); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATE_PROVISION_DISCOVERY_REQ_SEND: SignalStrength(%#x)\n", pP2PDeviceListEntry->RecvSignalPower)); } } pP2PInfo->State = P2P_STATE_PROVISION_DISCOVERY_REQ_SEND; CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter), P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) ? P2P_PROVISION_DISCOVERY_SHORT_TIMEOUT : P2P_PROVISION_DISCOVERY_TIMEOUT ); IncreaseDialogToken(pP2PInfo->DialogToken); p2p_Send_PDReq(pP2PInfo, pDev->mac, P2P_DEV_TYPE_GO == pDev->type, pP2PInfo->DialogToken, pDev->p2p->pdConfigMethod); pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery = FALSE; NextState = P2P_STATE_PROVISION_DISCOVERY_RSP_WAIT; bCommonChannelArrived = TRUE; } } if(pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe) { if(eqMacAddr(pDev->mac, pP2PInfo->InvitationContext.InvitedDevice.DeviceAddress)) {// source is the device we are trying to invite RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PCommonChannelArrived(): Recv Probe from the invitee device = > to send invitation req, state: %u\n", pP2PInfo->State)); pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe = FALSE; //pP2PInfo->InvitationContext.Channel = P2PScanListCeaseScan(pP2PInfo); pP2PInfo->State = P2P_STATE_INVITATION_REQ_SEND; // // Retrieve specific P2P device info. from Win8 Specific Device Information Pool to initiate boost initial gain // 2013.10.15. // pP2PDeviceListEntry = P2PDeviceListFind(&pP2PInfo->DeviceList, pDev->mac); if(pP2PDeviceListEntry) { if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { BoostInitGainValue = TRUE; BoostInitGainValue = (BoostInitGainValue | ((pP2PDeviceListEntry->RecvSignalPower+110) << 8)); pP2PInfo->pAdapter->HalFunc.SetHwRegHandler(pP2PInfo->pAdapter, HW_VAR_BOOST_INIT_GAIN_OS, (pu1Byte)&BoostInitGainValue); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATE_INVITATION_REQ_SEND: SignalStrength(%#x)\n", pP2PDeviceListEntry->RecvSignalPower)); } } CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter), P2P_INVITATION_FRAME_TIMEOUT); p2p_Send_InvitationReq(pP2PInfo, pDev->mac); NextState = P2P_STATE_INVITATION_RSP_WAIT; bCommonChannelArrived = TRUE; } } if(pP2PInfo->SDContext.bDoingServiceDiscovery) { PP2P_SD_CONTEXT pServiceDiscvoery = &(pP2PInfo->SDContext); if(eqMacAddr(pServiceDiscvoery->TargetDeviceAddress, pDev->mac)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PCommonChannelArrived(): Recv Probe from the service discovery request target, state: %u\n", pP2PInfo->State)); pP2PInfo->SDContext.bDoingServiceDiscovery = FALSE; //pP2PInfo->SDContext.Channel = P2PScanListCeaseScan(pP2PInfo); pP2PInfo->State = P2P_STATE_SERVICE_DISCOVERY_REQ_SEND; CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter), P2P_SERVICE_DISCOVERY_TIMEOUT); p2p_Send_SDReq(pP2PInfo, pDev->mac); NextState = P2P_STATE_SERVICE_DISCOVERY_RSP_WAIT; bCommonChannelArrived = TRUE; } } // // Go to the intended state immediately if common channel arrived. // if(bCommonChannelArrived) { BOOLEAN bScanInProgress = MgntScanInProgress(&pP2PInfo->pAdapter->MgntInfo); u4Byte msDelayStart = 0; // Wait more time for the response packet. if(NextState == P2P_STATE_PROVISION_DISCOVERY_RSP_WAIT || NextState == P2P_STATE_INVITATION_RSP_WAIT || NextState == P2P_STATE_SERVICE_DISCOVERY_RSP_WAIT) { msDelayStart += 100; // Wait 100 ms for the rsp packet } if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery msDelayStart += 10; // if scan in progress, we have to wait until ScanComplete() finishes //P2PScanListCeaseScan(pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } else if(pP2PInfo->bExtendedListening) {// Doing extended listening //P2PScanListCeaseScan(pP2PInfo); P2PExtendedListenComplete(pP2PInfo); } else if(bScanInProgress) {// Doing normal scan msDelayStart += 10; // if scan in progress, we have to wait until ScanComplete() finishes //P2PScanListCeaseScan(pP2PInfo); } pP2PInfo->State = NextState; // PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); // PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, msDelayStart); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Set P2PMgntTimer %d ms!\n", msDelayStart)); } return bCommonChannelArrived; } //====================================================================== // P2P Managmement //====================================================================== VOID P2PInitializeChannelEntryList( PP2P_INFO pP2PInfo ) { // // Channel entry list. // Set to the channels we support by default. // PADAPTER pAdapter = pP2PInfo->pAdapter; u1Byte i; u2Byte SupportedWirelessMode = pAdapter->HalFunc.GetSupportedWirelessModeHandler(pAdapter); WIRELESS_MODE CurrentWirelessModeBackup = pAdapter->MgntInfo.dot11CurrentWirelessMode; PRT_CHANNEL_LIST pChannelList = NULL; u1Byte chList[CHANNEL_MAX_NUMBER] = {0}; u1Byte nChList = 0; pAdapter->MgntInfo.dot11CurrentWirelessMode = SupportedWirelessMode; RtActChannelList(pAdapter, RT_CHNL_LIST_ACTION_CONSTRUCT, NULL, NULL); RtActChannelList(pAdapter, RT_CHNL_LIST_ACTION_GET_CHANNEL_LIST, NULL, &pChannelList); pAdapter->MgntInfo.dot11CurrentWirelessMode = CurrentWirelessModeBackup; // // Init channel entry list // pAdapter->MgntInfo.ChannelPlan = GetDefaultAdapter(pAdapter)->MgntInfo.ChannelPlan; PlatformZeroMemory(&pP2PInfo->ChannelEntryList, sizeof(pP2PInfo->ChannelEntryList)); pChannelList = GET_RT_CHANNEL_LIST(&pAdapter->MgntInfo);//MgntActQuery_ChannelList(pP2PInfo->pAdapter); for(i = 0; i < pChannelList->ChannelLen; i++) { chList[nChList++] = pChannelList->ChnlListEntry[i].ChannelNum; } MgntActSet_P2PChannelList(pAdapter, nChList, chList); } VOID P2PInitialize( IN PP2P_INFO pP2PInfo, IN PADAPTER pAdapter, IN u1Byte ListenChannel, IN u1Byte IntendedOpChannel, IN u1Byte GOIntent ) { BOOLEAN bBoostIgi = FALSE; BOOLEAN bSupportHwP2pPs = FALSE; PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PInitialize(): \n")); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "CurrentAddress: ", pAdapter->CurrentAddress); pP2PInfo->P2PVersion = 1; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PVersion initialized to %u\n", pP2PInfo->P2PVersion)); if(pAdapter == GetDefaultAdapter(pAdapter)) // Default adapter means this is Realtek P2P { pAdapter->P2PSupport = P2P_SUPPORT_STATE_RTK_SUPPORT; } else { pAdapter->P2PSupport = P2P_SUPPORT_STATE_OS_SUPPORT; } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P Support Type = %s\n", (P2P_SUPPORT_STATE_RTK_SUPPORT == pAdapter->P2PSupport) ? "RTK_SUPPORT" : "OS_SUPPORT")); // Win8: Point to self adapter pP2PInfo->pAdapter = pAdapter; RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PInitialize(): port number %d\n", pP2PInfo->pAdapter->pNdis62Common->PortNumber)); P2PSetRole(pP2PInfo, P2P_NONE); pP2PInfo->State = P2P_STATE_INITIALIZED; pP2PInfo->PreviouslyIndicatedState = P2P_STATE_MAX; pP2PInfo->PreviouslyIndicateStateTime = 0; if(P2P_ADAPTER_RTK_SUPPORT_P2P(pAdapter)) { bBoostIgi = TRUE; pAdapter->HalFunc.SetHwRegHandler(pAdapter, HW_VAR_BOOST_INIT_GAIN, &bBoostIgi); } cpMacAddr(pP2PInfo->DeviceAddress, pAdapter->CurrentAddress); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "pP2PInfo->DeviceAddress: ", pP2PInfo->DeviceAddress); if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { // Win8: Let the interface address be the permanent address cpMacAddr(pP2PInfo->InterfaceAddress, pAdapter->PermanentAddress); } else { // In Win7: pAdapter->CurrentAddress == pAdapter->PermanentAddress cpMacAddr(pP2PInfo->InterfaceAddress, pAdapter->CurrentAddress); } // // Capability // pP2PInfo->DeviceCapability = 0; pP2PInfo->DeviceCapability |= dcServiceDiscovery; pP2PInfo->DeviceCapability |= dcP2PClientDiscoverability; pP2PInfo->DeviceCapability |= dcP2PInvitationProcedure; //pP2PInfo->DeviceCapability |= dcP2PInfrastructureManaged; pP2PInfo->GroupCapability = 0; pP2PInfo->GroupCapability |= gcCrossConnection; pP2PInfo->GroupCapability |= gcIntraBSSDistribution; pP2PInfo->GroupCapability |= gcPersistentP2PGroup; // // GO Intent // pP2PInfo->GOIntent = GOIntent; // // Channel // pP2PInfo->RegulatoryClass = 81; if(0 == MultiChannelGetConnectedChannels(pAdapter, &pP2PInfo->OperatingChannel, 1)) { pP2PInfo->OperatingChannel = IntendedOpChannel; } pP2PInfo->ListenChannel = ListenChannel; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("GOIntent = %d, OP Chnl = %d, ListenChnl = %d\n", pP2PInfo->GOIntent, pP2PInfo->OperatingChannel, pP2PInfo->ListenChannel)); if(FALSE == P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter) || pAdapter->pNdis62Common->PortType == EXT_P2P_DEVICE_PORT) { MgntActSet_P2PListenChannel(pAdapter, ListenChannel); } pP2PInfo->CountryString[0] = 0x55; //US pP2PInfo->CountryString[1] = 0x53; pP2PInfo->CountryString[2] = 0x04; // // Channel entry list. // Set to the channels we support by default. // P2PInitializeChannelEntryList(pP2PInfo); // //WPS // { // // Not to clear the WPS IE because we should use the one set by normal UI, // The testing UI does not know the exact WPS IE. // //pP2PInfo->WpsInfoLen = 0; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PInitialize(): primary dev type: %u\n", pP2PInfo->WpsAttributes.PrimaryDeviceType.CategoryId)); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "P2PInitialize(): Device Name:\n", pP2PInfo->WpsAttributes.DeviceName, pP2PInfo->WpsAttributes.DeviceNameLength); } // Configuration Timeout, in units of 10ms pP2PInfo->GOConfigurationTimeout = P2P_GO_CONFIG_TIMEOUT; pP2PInfo->ClientConfigurationTimeout = P2P_CLIENT_CONFIG_TIMEOUT; // // Scan List // pP2PInfo->ScanListSize = 0; PlatformZeroMemory(pP2PInfo->ScanList, P2P_MAX_SCAN_LIST * sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PInfo->ScanList4QuerySize = 0; PlatformZeroMemory(pP2PInfo->ScanList4Query, P2P_MAX_SCAN_LIST * sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PInfo->ForceScanListIndicateSlotCount = 0; pP2PInfo->bDeviceDiscoveryInProgress = 0; pP2PInfo->P2PGONoClientSlotCount = 0; pP2PInfo->P2PClientDisconnectedSlotCount = 0; pP2PInfo->ExtListenTimingPeriodSlotCount = 0; pP2PInfo->bExtendedListening = FALSE; pP2PInfo->DialogToken = 1; PlatformZeroMemory(&pP2PInfo->ConnectionContext, sizeof(P2P_CONNECTION_CONTEXT)); pP2PInfo->bReinitiateConnection= FALSE; pP2PInfo->TimeStartWaitingForReinitiate = 0; pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)0; PlatformZeroMemory(&pP2PInfo->InvitationContext, sizeof(P2P_INVITATION_CONTEXT)); pP2PInfo->bAcceptInvitation = FALSE; PlatformZeroMemory(pP2PInfo->AccpetInvitationDeviceAddress, 6); PlatformZeroMemory(&pP2PInfo->DeviceDiscoverabilityContext, sizeof(P2P_DEVICE_DISCOVERABILITY_CONTEXT)); pP2PInfo->ExtListenTimingPeriod = P2P_EXT_LISTEN_TIMING_PERIOD_MS; pP2PInfo->ExtListenTimingDuration = P2P_EXT_LISTEN_TIMING_DURATION_MS; pP2PInfo->bSendProbeReqInExtendedListen = FALSE; PlatformZeroMemory(&pP2PInfo->ProvisionDiscoveryContext, sizeof(P2P_PROVISION_DISCOVERY_CONTEXT)); // Service Discovery PlatformZeroMemory(&pP2PInfo->SDContext, sizeof(P2P_SD_CONTEXT)); pP2PInfo->SDRspFragmtntThreshold = P2P_SERVICE_MAX_RSP_FRAG_THRESHOLD; pP2PInfo->SDWaitForComebackReqSlotCount = 0; //PlatformZeroMemory(&pP2PInfo->PersistentProfile, sizeof(P2P_PERSISTENT_PROFILE)); // ICS pP2PInfo->CurrentIcsStatus = P2P_CURRENT_ICS_STATUS_UNKNOWN; // Profile list pP2PInfo->profileListLen = 0; pP2PInfo->pProfileList = NULL; //====================================================================== // Power Save related //====================================================================== // Clear the PS level first. RT_CLEAR_PS_LEVEL(pAdapter, RT_RF_LPS_P2P_PS); pP2PInfo->bUpdateFromBeacon = FALSE; pP2PInfo->bUpdatePsParameter = FALSE; pP2PInfo->PsFlag = 0; pP2PInfo->NextTimeout = 0; pP2PInfo->P2pPsState = P2P_PS_AWAKE; pP2PInfo->NoAIEIndex = 0; pP2PInfo->CTWindow = 0; pP2PInfo->bOppPS = 0; //pP2PInfo->SSIDLen = 0; PlatformZeroMemory(pP2PInfo->NoADescriptors, sizeof(P2P_NOA_DESCRIPTOR) * 2); // Determine whether this chip can support P2P ps mode. pP2PInfo->psExeType = RT_P2P_PS_EXE_BY_NONE; if(!pAdapter->HalFunc.GetHalDefVarHandler(pAdapter, HAL_DEF_HW_P2P_PS_SUPPORT, (pu1Byte)&bSupportHwP2pPs)) { bSupportHwP2pPs = FALSE; } if(bSupportHwP2pPs && pAdapter->MgntInfo.bWiFiConfg) { pP2PInfo->psExeType = RT_P2P_PS_EXE_BY_HW; } else if(bSupportHwP2pPs && GetDefaultAdapter(pAdapter)->MgntInfo.RegMultiChannelFcsMode >= MULTICHANNEL_FCS_SUPPORT_GO) { pP2PInfo->psExeType = RT_P2P_PS_EXE_BY_HW; } else { pP2PInfo->psExeType = RT_P2P_PS_EXE_BY_SW_TIMER; } if(pP2PInfo->psExeType > RT_P2P_PS_EXE_BY_HW) { PRT_POWER_SAVE_CONTROL pPSC = GET_POWER_SAVE_CONTROL(pMgntInfo); pPSC->bFwCtrlLPS = FALSE; } //====================================================================== // P2P Managed //====================================================================== pP2PInfo->bWlanApRejection_CrossConnection = FALSE; pP2PInfo->bWlanApRejection_Unmanaged = FALSE; pP2PInfo->bWlanApRejection_IncompatibleCoexistenceParameters = FALSE; pP2PInfo->bWlanApRejection_IncompatibleP2POperation = FALSE; //====================================================================== // Other //====================================================================== P2PSetPsState(pP2PInfo, P2P_PS_CANCEL_ALL_PS, P2P_PS_AWAKE, 0); if(pAdapter->MgntInfo.bDisableCck) { SelectRateSet(pAdapter, pAdapter->MgntInfo.Regdot11OperationalRateSet); } // // Ask for disconnection, note that these function can only be called when P2PInfo is initialized // //P2PIndicateStopApRequest(pP2PInfo); //P2PIndicateDisconnectClientRequest(pP2PInfo); P2P_AddIe_Init(&pP2PInfo->AdditionalIEs); p2p_DevList_Init(&pP2PInfo->devList); // For Win 8: OID_DOT11_WFD_LISTEN_STATE_DISCOVERABILITY ----------------------------- // The macro P2P_ENABLED() will be modified due to the Win 8. if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { pP2PInfo->uListenStateDiscoverability = 0; // Zero for not discoverable } else { pP2PInfo->uListenStateDiscoverability = 100; // Set a non-zero value } // ----------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_DISCOVER_REQUEST ------------------------------------------------------ pP2PInfo->DiscoverSequence = P2P_DISCOVERY_SCAN_PHASE | P2P_DISCOVERY_FIND_PHASE; pP2PInfo->ScanType = SCAN_ACTIVE; P2PClearScanDeviceID(&pP2PInfo->ScanDeviceIDs); pP2PInfo->bForceScanLegacyNetworks = FALSE; pP2PInfo->bDeviceDiscoveryIndicateToOS = FALSE; pP2PInfo->bDiscoverForSpecificChannels = FALSE; PlatformZeroMemory(pP2PInfo->DiscoverForSpecificChannels, sizeof(pP2PInfo->DiscoverForSpecificChannels)); pP2PInfo->uNumberOfDiscoverForSpecificChannels = 0; pP2PInfo->uNumberOfDiscoverRounds = 0; // + Win8 Trick to Speed up GO Negotiation Procedure pP2PInfo->LastDeviceDiscoveryOidIssueTime = 0; pP2PInfo->LastDeviceDiscoveryIndicatedTime = 0; // ------------------------------------------------------------------------------------------------ // Device List ------------------------------------------------------------------------- PlatformZeroMemory(&pP2PInfo->DeviceList, sizeof(P2P_DEVICE_LIST)); PlatformZeroMemory(&pP2PInfo->DeviceListForQuery, sizeof(P2P_DEVICE_LIST)); //----------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_PROVISION_DISCOVERY_REQUEST -------------------------------------- pP2PInfo->ProvisionRequestGroupCapability = 0; pP2PInfo->bProvisionRequestUseGroupID = FALSE; PlatformZeroMemory(pP2PInfo->ProvisionRequestGroupIDDeviceAddress, 6); PlatformZeroMemory(pP2PInfo->ProvisionRequestGroupIDSSID, MAX_SSID_LEN); pP2PInfo->uProvisionRequestGroupIDSSIDLength = 0; // ------------------------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_PROVISION_DISCOVERY_RESPONSE -------------------------------------- PlatformZeroMemory(pP2PInfo->ProvisionResponseReceiverDeviceAddress, 6); pP2PInfo->ProvisionResponseDialogToken = 0; // ------------------------------------------------------------------------------------------------- // For delaying operations from the OID command --------------------------------------------------------- pP2PInfo->bPostoneP2POidPostProcessWorkItem = FALSE; // RT_WORK_ITEM P2POidPostProcessWorkItem; Initialized in MgntInitializeAllWorkItem and MgntFreeAllWorkItem pP2PInfo->OidOperation = OID_OPERATION_NO_OPERATION; pP2PInfo->PacketSentInWorkItemCallback = (P2P_PUBLIC_ACTION_TYPE) 0xFF; // Send no packet //------------------------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_GO_NEGOTIATION_REQUEST --------------------------- //PlatformZeroMemory(pP2PInfo->NegotiationRequestIntendedInterfaceAddress, 6); pP2PInfo->NegotiationRequestGOIntent = 0; pP2PInfo->NegotiationRequestGroupCapability = 0; // --------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_GO_NEGOTIATION_RESPONSE ------------------------ PlatformZeroMemory(pP2PInfo->NegotiationResponsePeerDeviceAddress, 6); pP2PInfo->NegotiationResponseDialogToken = 0; pP2PInfo->NegotiationResponseStatus = 0; pP2PInfo->NegotiationResponseGroupOwnerIntent = 0; //PlatformZeroMemory(pP2PInfo->NegotiationResponseIntendedInterfaceAddress, 6); pP2PInfo->NegotiationResponseGroupCapability = 0; PlatformZeroMemory(pP2PInfo->NegotiationResponseGroupIDDeviceAddress, 6); PlatformZeroMemory(pP2PInfo->NegotiationResponseGroupIDSSID, MAX_SSID_LEN); pP2PInfo->uNegotiationResponseGroupIDSSIDLength = 0; pP2PInfo->bNegotiationResponseUseGroupID = FALSE; //--------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_GO_NEGOTIATION_CONFIRM --------------------------- PlatformZeroMemory(pP2PInfo->NegotiationConfirmPeerDeviceAddress, 6); pP2PInfo->NegotiationConfirmDialogToken = 0; pP2PInfo->NegotiationConfirmStatus = 0; pP2PInfo->NegotiationConfirmGroupCapability = 0; PlatformZeroMemory(pP2PInfo->NegotiationConfirmGroupIDDeviceAddress, 6); PlatformZeroMemory(pP2PInfo->NegotiationConfirmGroupIDSSID, MAX_SSID_LEN); pP2PInfo->uNegotiationConfirmGroupIDSSIDLength = 0; pP2PInfo->bNegotiationConfirmUseGroupID = FALSE; //--------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_INVITATION_REQUEST ------------------------------- PlatformZeroMemory(pP2PInfo->InvitationRequestGroupBSSID, 6); pP2PInfo->bInvitationRequestUseGroupBSSID = FALSE; pP2PInfo->uInvitationRequestOperatingChannelNumber = 0; pP2PInfo->bInvitationRequestUseSpecifiedOperatingChannel = FALSE; PlatformZeroMemory(pP2PInfo->InvitationRequestGroupIDDeviceAddress, 6); PlatformZeroMemory(pP2PInfo->InvitationRequestGroupIDSSID, MAX_SSID_LEN); pP2PInfo->uInvitationRequestGroupIDSSIDLength = 0; pP2PInfo->bInvitationRequestLocalGO = FALSE; //--------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_SEND_INVITATION_RESPONSE ------------------------------ PlatformZeroMemory(pP2PInfo->InvitationResponseReceiverDeviceAddress, 6); pP2PInfo->InvitationResponseDialogToken = 0; pP2PInfo->InvitationResponseStatus = 0; PlatformZeroMemory(pP2PInfo->InvitationResponseGroupBSSID, 6); pP2PInfo->bInvitationResponseUseGroupBSSID = FALSE; pP2PInfo->uInvitationResponseOperatingChannelNumber = 0; pP2PInfo->bInvitationResponseUseSpecifiedOperatingChannel = FALSE; pP2PInfo->bInvitationResponseIndicateToOS = FALSE; //--------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_GROUP_JOIN_PARAMETERS ------------------------------------ P2PResetClientJoinGroupContext(pP2PInfo); // ----------------------------------------------------------------------------------- // For Win 8: OID_DOT11_WFD_DESIRED_GROUP_ID ------------------------------------------ PlatformZeroMemory(pP2PInfo->DesiredTargetMacAddress, sizeof(pP2PInfo->DesiredTargetMacAddress)); pP2PInfo->uGroupTargetSSIDLength = 0; PlatformZeroMemory(pP2PInfo->GroupTargetSSID, sizeof(pP2PInfo->GroupTargetSSID)); // ----------------------------------------------------------------------------------- // Debug Device Discovery ------------------- pP2PInfo->ProbeRequestSequenceNum = 0; // ---------------------------------------- // Trick for knowing next channel switch time ----------- pP2PInfo->TimeStartToStopSendingProbeResponse = 0; // ----------------------------------------------- // Start Mgnt Timer ----------------------------------------------------------------- PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); if(!pP2PInfo->pAdapter->bInHctTest) PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); // -------------------------------------------------------------------------------- P2PSetRole(pP2PInfo, P2P_DEVICE); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PInitialize()\n")); } VOID P2PResetCommonChannelArrivingProcess( IN PP2P_INFO pP2PInfo ) { FunctionIn(COMP_P2P); // connection pP2PInfo->bPreGroupFormation = FALSE; PlatformZeroMemory(&pP2PInfo->ConnectionContext, sizeof(P2P_CONNECTION_CONTEXT)); // invitation pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe = FALSE; PlatformZeroMemory(&pP2PInfo->InvitationContext, sizeof(P2P_INVITATION_CONTEXT)); // provision discovery pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery = FALSE; PlatformZeroMemory(&pP2PInfo->ProvisionDiscoveryContext, sizeof(P2P_PROVISION_DISCOVERY_CONTEXT)); // sd pP2PInfo->SDContext.bDoingServiceDiscovery = FALSE; PlatformZeroMemory(&pP2PInfo->SDContext, sizeof(P2P_SD_CONTEXT)); FunctionOut(COMP_P2P); } // // This function guarantees to preserve: // * P2P State // * Channel // BOOLEAN P2PDeviceDiscovery( IN PP2P_INFO pP2PInfo, IN u1Byte FindPhaseLoopTimes ) { BOOLEAN bScanInProgress; u4Byte msDelayStart = 0; BOOLEAN bToIndicDevDiscComp = FALSE; if(!P2P_ENABLED(pP2PInfo)) { return FALSE; } // // Stop any existing scan // bScanInProgress = MgntScanInProgress(&pP2PInfo->pAdapter->MgntInfo); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDeviceDiscovery(): State: %u, bScanInProgres: %u port number %d\n", pP2PInfo->State, bScanInProgress, pP2PInfo->pAdapter->pNdis62Common->PortNumber)); if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery msDelayStart += 10; // if scan in progress, we have to wait until ScanComplete() finishes P2PScanListCeaseScan(pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); bToIndicDevDiscComp = TRUE; } else if(pP2PInfo->bExtendedListening) {// Doing extended listening P2PScanListCeaseScan(pP2PInfo); P2PExtendedListenComplete(pP2PInfo); } else if(bScanInProgress) {// Doing normal scan msDelayStart += 10; // if scan in progress, we have to wait until ScanComplete() finishes P2PScanListCeaseScan(pP2PInfo); } if(FindPhaseLoopTimes == P2P_DEV_DISC_STOP) { if(bToIndicDevDiscComp && P2P_DOING_PURE_DEVICE_DISCOVERY(pP2PInfo)) { P2PIndicateDeviceDiscoveryComplete(pP2PInfo); } return TRUE; } pP2PInfo->bDeviceDiscoveryInProgress = TRUE; pP2PInfo->StateBeforeScan = pP2PInfo->State; if(pP2PInfo->Role == P2P_GO) { P2PStopResumeGOBeaconning(pP2PInfo, FALSE); } // // Clear scan list before scan. // If we are a GO, we shall not clear our scan list since when a client associates, // it provides its info to us in AssocReq, and we record the info in our scan list. // If we clear this info, we will lost the info of the associated clients. // if(pP2PInfo->Role != P2P_GO && P2P_DOING_PURE_DEVICE_DISCOVERY(pP2PInfo)) // Can't use P2P_ACTING_AS_GO since the state now is P2P_STATE_SCAN, not operating { P2PScanListClear(pP2PInfo); } PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); P2P_INC_REF_CNT(pP2PInfo); PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); // pP2PInfo->StateBeforeScan = pP2PInfo->State; pP2PInfo->State = P2P_STATE_DEV_DISC_START; // pP2PInfo->bDeviceDiscoveryInProgress = TRUE; pP2PInfo->ConnectionContext.FindPhaseLoopTimes = FindPhaseLoopTimes; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDeviceDiscovery(): delay start after %d (ms), StateBeforeScan: %u\n", msDelayStart, pP2PInfo->StateBeforeScan)); //if(MgntActQuery_802_11_CHANNEL_NUMBER((GetDefaultAdapter(pP2PInfo->pAdapter))) != pP2PInfo->ListenChannel) //{ // // Reset Listen Channel to see if we have chance to switch current channel back to the Listen Channel. // MgntActSet_P2PListenChannel(pP2PInfo->pAdapter, pP2PInfo->ListenChannel); //} PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); P2P_DEC_REF_CNT(pP2PInfo); PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, msDelayStart); return TRUE; } VOID P2PDeviceDiscoverForSpecificChannels( PP2P_INFO pP2PInfo, pu1Byte ChannelList, u1Byte uNumberOfChannel ) { VOID *customScanInfo = GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter); VOID *req = NULL; FRAME_BUF *probeReqBuf = NULL; u4Byte itChnl = 0; if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) { return; } probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_ProbeReq(probeReqBuf, pP2PInfo); for(itChnl = 0; itChnl < uNumberOfChannel; itChnl++) { CustomScan_AddScanChnl(req, ChannelList[itChnl], 3, SCAN_ACTIVE, 20, MGN_6M, probeReqBuf); } CustomScan_SetupCbCtx(req, p2p_ScanStateCb, pP2PInfo->pAdapter); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "spec chnl disc"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2PDeviceDiscoverForSpecificChannels issued\n")); return; } VOID P2PDeviceDiscoveryComplete( IN PP2P_INFO pP2PInfo, IN BOOLEAN bRecoverState ) { // // We do some clean up task here. // // For Win8 P2P Indication ------------------------------------------------------------ if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && pP2PInfo->bDeviceDiscoveryIndicateToOS == TRUE) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: P2P_EVENT_DEVICE_DISCOVERY_COMPLETE\n", __FUNCTION__)); PlatformIndicateP2PEvent(pP2PInfo, P2P_EVENT_DEVICE_DISCOVERY_COMPLETE, NULL); // Trick Adopted for Speeding up the Go Negotiation pP2PInfo->LastDeviceDiscoveryIndicatedTime = PlatformGetCurrentTime(); P2PClearScanDeviceID(&pP2PInfo->ScanDeviceIDs); pP2PInfo->bDeviceDiscoveryIndicateToOS = FALSE; pP2PInfo->bDiscoverForSpecificChannels = FALSE; PlatformZeroMemory( pP2PInfo->DiscoverForSpecificChannels, sizeof(pP2PInfo->DiscoverForSpecificChannels) ); pP2PInfo->uNumberOfDiscoverForSpecificChannels = 0; pP2PInfo->uNumberOfDiscoverRounds = 0; } // -------------------------------------------------------------------------------- if(pP2PInfo->Role == P2P_GO) { P2PStopResumeGOBeaconning(pP2PInfo, TRUE); } if(bRecoverState) { // discovery complete, back to original state RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDeviceDiscoveryComplete(): P2P_STATE_DEV_DISC_COMPLETE: back to state (%u) from (%u)\n", pP2PInfo->StateBeforeScan, pP2PInfo->State)); pP2PInfo->State = pP2PInfo->StateBeforeScan; } pP2PInfo->bDeviceDiscoveryInProgress = FALSE; P2PSvc_OnDevDiscComplete(pP2PInfo->pP2PSvcInfo); } VOID P2PExtendedListenStart( IN PP2P_INFO pP2PInfo ) { PADAPTER pAdapter = pP2PInfo->pAdapter; VOID *customScanInfo = GET_CUSTOM_SCAN_INFO(pAdapter); VOID *req = NULL; FRAME_BUF *probeReqBuf = NULL; BOOLEAN bActiveScan = pP2PInfo->bSendProbeReqInExtendedListen; if(MgntIsLinkInProgress(GetDefaultMgntInfo(pP2PInfo->pAdapter))) { return; } RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PExtendedListenStart()\n")); #if (MULTICHANNEL_SUPPORT == 1) // Do not support 3 channel swtich: This will mess up our multichannl swtich ----------------------------------------------- if(MultiChannelSwitchNeeded(pAdapter)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Do not support extended listening on MultiChannel environment\n", __FUNCTION__)); FunctionOut(COMP_P2P); return; } // ------------------------------------------------------------------------------------------------------------- #endif // Do not use extended listening if group is constructed ------------------------------------------------------ if(GetFirstGOPort(pAdapter) || GetFirstClientPort(pAdapter)) { ADAPTER *cli = GetFirstClientPort(pAdapter); if(cli && GET_P2P_INFO(cli) && (P2P_CLIETN_JOIN_GROUP_WPS_STATE_SCANNING == (GET_P2P_INFO(cli))->ClientJoinGroupContext.WpsState || P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY == (GET_P2P_INFO(cli))->ClientJoinGroupContext.WpsState || P2P_CLIETN_JOIN_GROUP_WPS_STATE_ASSOCIATING == (GET_P2P_INFO(cli))->ClientJoinGroupContext.WpsState )) {// don't do scan in this case RT_TRACE_F(COMP_P2P, DBG_LOUD, ("do not use extended listen when cli port is doing WPS join group, state: %u\n", (GET_P2P_INFO(cli))->ClientJoinGroupContext.WpsState)); FunctionOut(COMP_P2P); return; } } if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { ADAPTER *pDev = GetFirstDevicePort(pP2PInfo->pAdapter); if(pDev) { P2P_INFO *p2p = GET_P2P_INFO(pP2PInfo->pAdapter); if(!p2p->uListenStateDiscoverability) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s:Do not use extended listening if not set to be discoverable\n", __FUNCTION__)); FunctionOut(COMP_P2P); return; } } } // -------------------------------------------------------------------------------------------------- RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: listen channel: %d, Current Channel: %d\n", __FUNCTION__, pP2PInfo->ListenChannel, RT_GetChannelNumber(pAdapter)) ); // At the same channel, no need to scan and switch channel. if(pP2PInfo->ListenChannel == RT_GetChannelNumber(pAdapter)) { // RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: In the Same Channel: %d\n", __FUNCTION__, pP2PInfo->ListenChannel)); return; } pP2PInfo->bExtendedListening = TRUE; // set to false in ScanComplete() if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) { return; } probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_ProbeReq(probeReqBuf, pP2PInfo); CustomScan_AddScanChnl(req, pP2PInfo->ListenChannel, 1, (pP2PInfo->bSendProbeReqInExtendedListen) ? SCAN_ACTIVE : SCAN_PASSIVE, pP2PInfo->ExtListenTimingDuration, P2P_LOWEST_RATE, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "ext listen"); FunctionOut(COMP_P2P); } VOID P2PExtendedListenResetCounter( IN PP2P_INFO pP2PInfo ) { FunctionIn(COMP_P2P); pP2PInfo->ExtListenTimingPeriodSlotCount = 0; } VOID P2PExtendedListenComplete( IN PP2P_INFO pP2PInfo ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PExtendedListenComplete()\n")); pP2PInfo->bExtendedListening = FALSE; if(MgntActQuery_802_11_CHANNEL_NUMBER((GetDefaultAdapter(pP2PInfo->pAdapter))) != pP2PInfo->ListenChannel && !MgntIsLinkInProgress(GetDefaultMgntInfo(pP2PInfo->pAdapter))) { // Reset Listen Channel to see if we have chance to switch current channel back to the Listen Channel. MgntActSet_P2PListenChannel(pP2PInfo->pAdapter, pP2PInfo->ListenChannel); } FunctionOut(COMP_P2P); } BOOLEAN P2PProvisionDiscovery( IN PP2P_INFO pP2PInfo, IN pu1Byte MacAddress, // shall be the device address IN u2Byte ConfigMethod // should have exactly 1 bit set ) { PP2P_PROVISION_DISCOVERY_CONTEXT pProvisionDiscContext = &pP2PInfo->ProvisionDiscoveryContext; P2P_DEV_LIST_ENTRY *pDev = NULL; // // Check state // if(pP2PInfo->State > P2P_STATE_DEV_DISC_COMPLETE && FALSE == P2P_ACTING_AS_GO(pP2PInfo) ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDeviceDiscovery(): Invalid state: %u\n",pP2PInfo->State)); return FALSE; } RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PProvisionDiscovery(): ConfigMethod: 0x%X\n", ConfigMethod)); p2p_DevList_Lock(&pP2PInfo->devList); do { P2P_DEVICE_DISCRIPTOR desc; const u1Byte *devAddr = NULL; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(pP2PInfo->bProvisionRequestUseGroupID) pDev = p2p_DevList_GetGo(&pP2PInfo->devList, MacAddress); else pDev = p2p_DevList_Get(&pP2PInfo->devList, MacAddress, P2P_DEV_TYPE_DEV); if(NULL == pDev) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PProvisionDiscovery(): device entry not found\n")); p2p_DevList_Dump(&pP2PInfo->devList); break; } } else { if(NULL == (pDev = p2p_DevList_GetGo(&pP2PInfo->devList, MacAddress))) { if(NULL == (pDev = p2p_DevList_Get(&pP2PInfo->devList, MacAddress, P2P_DEV_TYPE_DEV))) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PProvisionDiscovery(): device entry not found\n")); p2p_DevList_Dump(&pP2PInfo->devList); break; } } } p2p_DevList_TranslateDev(pDev, &desc); devAddr = desc.DeviceAddress; // // For Sigma // if(ConfigMethod == 0) { if(desc.WpsAttributes.DevicePasswdId == P2P_WPS_DEV_PASSWD_ID_PBC) ConfigMethod = P2P_WPS_CONFIG_METHODS_PUSHBUTTON; else if(desc.WpsAttributes.DevicePasswdId == P2P_WPS_DEV_PASSWD_ID_USER_SPEC) ConfigMethod = P2P_WPS_CONFIG_METHODS_KEYPAD; else if(desc.WpsAttributes.DevicePasswdId == P2P_WPS_DEV_PASSWD_ID_REG_SPEC) ConfigMethod = P2P_WPS_CONFIG_METHODS_DISPLAY; else { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PProvisionDiscovery(): ConfigMethod is 0 and we don't know peer's DPID\n")); break; } } if(!P2PTestU2SingleBitSet(ConfigMethod)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PProvisionDiscovery(): ConfigMethod has multiple bit set: %u\n", ConfigMethod)); p2p_DevList_Unlock(&pP2PInfo->devList); return FALSE; } // // Fill Provision Discovery Context // P2PResetCommonChannelArrivingProcess(pP2PInfo); cpMacAddr(pProvisionDiscContext->devAddr, devAddr); pProvisionDiscContext->go = (P2P_DEV_TYPE_GO == pDev->type); if(P2P_DEV_TYPE_GO == pDev->type) { cpMacAddr(pProvisionDiscContext->goBssid, pDev->mac); CopySsid(pProvisionDiscContext->SsidBuf, pProvisionDiscContext->SsidLen, desc.SsidBuf, desc.SsidLen); } pProvisionDiscContext->bDoingProvisionDiscovery = TRUE; pDev->p2p->pdStatus = P2P_SC_SUCCESS; pDev->p2p->pdConfigMethod = ConfigMethod; if(P2P_DEV_TYPE_GO == pDev->type) { if(0 != desc.OperatingChannel) pProvisionDiscContext->Channel = desc.OperatingChannel; else pProvisionDiscContext->Channel = desc.ListenChannel; } else { pProvisionDiscContext->Channel = desc.ListenChannel; } p2p_DevList_FlushActionFrames(&pP2PInfo->devList, pDev->mac, pDev->type); if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(&pP2PInfo->pAdapter->bInHctTest) P2PDeviceDiscovery(pP2PInfo, 12); else P2PDeviceDiscovery(pP2PInfo, 36); } else { if(&pP2PInfo->pAdapter->bInHctTest) P2PDeviceDiscovery(pP2PInfo, 12); else P2PDeviceDiscovery(pP2PInfo, P2P_SCAN_FIND_PHASE_LOOP_TIMES); } }while(FALSE); p2p_DevList_Unlock(&pP2PInfo->devList); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PProvisionDiscovery(): ch %u\n", pProvisionDiscContext->Channel)); return TRUE; } VOID P2PServiceDiscoveryReq( PP2P_INFO pP2PInfo, PP2P_SD_REQ_CONTEXT pServiceQueryContent ) { PP2P_DEVICE_DISCRIPTOR pDevDesc; PP2P_SD_CONTEXT pSDContext = &(pP2PInfo->SDContext); RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PServiceDiscoveryReq(): TLVs: %u\n", pServiceQueryContent->ServiceReqTLVSize)); if(!P2P_ENABLED(pP2PInfo)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq(): P2P NOT enabled\n")); return; } if(pP2PInfo->SDContext.bDoingServiceDiscovery) {// note that bDoingServiceDiscovery is cleared when common channel arrived RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq(): SD in progress\n")); return; } if(P2P_DOING_SERVICE_DISCOVERY_REQ(pP2PInfo)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq(): SD in progress (frame exhange started)\n")); return; } // // Validate TLV list length // if(pServiceQueryContent->ServiceReqTLVSize < 1) // must have at least 1 query TLV { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq(): error: must have at least 1 query TLV\n")); return; } if(pServiceQueryContent->ServiceReqTLVSize > P2P_SD_MAX_SERVICES) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq(): error: can have at most %u TLVs\n", P2P_SD_MAX_SERVICES)); return; } RT_PRINT_ADDRS(COMP_P2P,DBG_LOUD, ("P2PServiceDiscoveryReq(): target DevAddr: "), pServiceQueryContent->TargetDeviceAddress, 1); pDevDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, pServiceQueryContent->TargetDeviceAddress, NULL, NULL); if(pDevDesc == NULL) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq(): target device not found in the scan list\n")); return; } // // Fill SDContext // P2PResetCommonChannelArrivingProcess(pP2PInfo); { // // Copy the SD req // cpMacAddr(pSDContext->UserSDReq.TargetDeviceAddress, pServiceQueryContent->TargetDeviceAddress); pSDContext->UserSDReq.ServiceReqTLVSize = pServiceQueryContent->ServiceReqTLVSize; PlatformMoveMemory(&pSDContext->UserSDReq.ServiceReqTLVList, pServiceQueryContent->ServiceReqTLVList, sizeof(P2P_SERVICE_REQ_TLV) * pServiceQueryContent->ServiceReqTLVSize); // Store target listen channel, although we will store the channel when // ProbeRsp is received, the target listen channel // can still be a hint for where to search for its ProbeRsp pSDContext->Channel = pDevDesc->ListenChannel; // Set to Start Service Dicovery pSDContext->bDoingServiceDiscovery = TRUE; pSDContext->bRequester = TRUE; pSDContext->DialogToken = IncreaseDialogToken(pP2PInfo->DialogToken); pSDContext->TransactionID = pServiceQueryContent->ServiceReqTLVList[0].TransactionID; pSDContext->FragmentID = 0; pSDContext->ANQPQueryRspFieldToSendOffset = 0; cpMacAddr(pSDContext->TargetDeviceAddress, pServiceQueryContent->TargetDeviceAddress); } // // Do device discovery to find out when the target device is in Listen State. // P2PDeviceDiscovery(pP2PInfo, P2P_SCAN_FIND_PHASE_LOOP_TIMES); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryReq()\n")); } VOID P2PServiceDiscoveryRsp( PP2P_INFO pP2PInfo, PP2P_SD_RSP_CONTEXT pServiceRspContent ) { BOOLEAN bFragmentSDRsp = FALSE; PP2P_SD_CONTEXT pSDContext = &pP2PInfo->SDContext; if(!P2P_ENABLED(pP2PInfo)) { return; } if(!pSDContext->bDoingServiceDiscovery) { return; } // // Copy service info if we have enough space for the TLVs // if(pServiceRspContent->ServiceRspTLVSize > P2P_SD_MAX_SERVICES) { return; } RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PServiceDiscoveryRsp()\n")); // // Construct Rsp TLV list from pP2PInfo->SDRspContext // p2p_Construct_AnqpQueryRspField(pP2PInfo, pServiceRspContent, pSDContext); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PServiceDiscoveryRsp(): ANQPQueryRsp Size: %u, Frag Threshold: %u\n", pSDContext->ANQPQueryRspFieldToSendSize, pP2PInfo->SDRspFragmtntThreshold)); //RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "ANQPQueryRsp constructed: ", // pP2PInfo->SDContext.ANQPQueryRspFieldToSendBuf, // pP2PInfo->SDContext.ANQPQueryRspFieldToSendSize); // To send from offset 0 pSDContext->ANQPQueryRspFieldToSendOffset = 0; if(pSDContext->ANQPQueryRspFieldToSendSize > pP2PInfo->SDRspFragmtntThreshold) { bFragmentSDRsp = TRUE; // // Fill P2P_SD_CONTEXT for doing fragmentation // We've already filled DialogToken, TransactionID and ServiceReqRecvd. // pSDContext->Status = pServiceRspContent->SDStatus; pSDContext->bFragment = TRUE; pSDContext->FragmentID = 0; // we are going to send ComebackRsp with FragmentID 0 pSDContext->bDoingServiceDiscovery = TRUE; pSDContext->bRequester = FALSE; pSDContext->Channel = P2PGetChannel(pP2PInfo); cpMacAddr(pSDContext->TargetDeviceAddress, pServiceRspContent->SourceDeviceAddress); } p2p_Send_SDRsp(pP2PInfo, pSDContext->TargetDeviceAddress, pSDContext->DialogToken, pSDContext->Status, bFragmentSDRsp); if(bFragmentSDRsp) { pP2PInfo->SDWaitForComebackReqSlotCount = 0; } else { PlatformZeroMemory(&pP2PInfo->SDContext, sizeof(P2P_SD_CONTEXT)); CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pP2PInfo->pAdapter), P2P_SERVICE_DISCOVERY_COMEBACK_TIMEOUT); } RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PServiceDiscoveryRsp()\n")); } BOOLEAN P2PConnect( IN PP2P_INFO pP2PInfo, IN pu1Byte DeviceAddress ) { PADAPTER pAdapter = pP2PInfo->pAdapter; PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; // For the case when we are connecting to a P2P Client PP2P_DEVICE_DISCRIPTOR pGODeviceDesc = NULL; PP2P_CLIENT_INFO_DISCRIPTOR pClientInfoDesc = NULL; if(!P2P_ENABLED(pP2PInfo)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PConnect(): P2P Disabled\n")); return FALSE; } // // Find the descriptor in scan list (GO and Device are in this list) // pP2PDeviceDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, DeviceAddress, NULL, NULL); // // Find the descriptor in client info list of each GO if it can't be found in the scan list // if(pP2PDeviceDesc == NULL) { if(!P2PScanListFindClient(pP2PInfo->ScanList, pP2PInfo->ScanListSize, DeviceAddress, NULL, &pGODeviceDesc, &pClientInfoDesc)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PConnect(): can't find the device in either the scan list or the client info lists\n")); return FALSE; } // // The target device is a P2P Client // pP2PDeviceDesc = pGODeviceDesc; } // // Before calling this function, the upper layer shall make sure that // 1. Device Name is included in WPS IE // 2. Device Password ID is included in WPS IE (Clause 3.1.2.4.1) // RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PConnect()\n")); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "Target Device: ", DeviceAddress); if(pP2PInfo->State > P2P_STATE_DEV_DISC_COMPLETE) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PConnect(): State: %u\n", pP2PInfo->State)); return FALSE; } if(pP2PDeviceDesc == NULL) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PConnect(): Target device entry not found\n")); return FALSE; } if(pP2PDeviceDesc->Role == P2P_DEVICE) { // Fill ConnectionContext P2PResetCommonChannelArrivingProcess(pP2PInfo); PlatformMoveMemory(&pP2PInfo->ConnectionContext.ConnectingDevice, pP2PDeviceDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PInfo->ConnectionContext.Status = P2P_STATUS_SUCCESS; pP2PInfo->ConnectionContext.DialogToken = IncreaseDialogToken(pP2PInfo->DialogToken); if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) pP2PInfo->ConnectionContext.FindPhaseLoopTimes = 36; else pP2PInfo->ConnectionContext.FindPhaseLoopTimes = P2P_SCAN_FIND_PHASE_LOOP_TIMES; pP2PInfo->ConnectionContext.bGoingToBeGO = FALSE; pP2PInfo->bPreGroupFormation = TRUE; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(&pP2PInfo->pAdapter->bInHctTest) P2PDeviceDiscovery(pP2PInfo, 12); else P2PDeviceDiscovery(pP2PInfo, 36); } else { if(&pP2PInfo->pAdapter->bInHctTest) P2PDeviceDiscovery(pP2PInfo, 12); else P2PDeviceDiscovery(pP2PInfo, P2P_SCAN_FIND_PHASE_LOOP_TIMES); } // GO Formation should be initiated in P2POnProbeReq() } else if(pP2PDeviceDesc->Role == P2P_GO) {// note that in this case, the mac addr is the interface addr of the GO if(pClientInfoDesc) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PConnect(): peer is a P2P Client\n")); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "GO DevAddr:\n", pP2PDeviceDesc->DeviceAddress); // // Do discoverability request and then GO formation // P2PDeviceDiscoverabilityReq(pP2PInfo, DeviceAddress, TRUE); } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PConnect(): peer is a GO\n")); // // Now we shall have the dev addr and interface addr of the GO // // PF #2, Atheros device use different Dev and Int Addr. // UI send DevAddr as the MacAddress and we shall not use // it as the IntAddr. /* pP2PDeviceDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, NULL, MacAddress, NULL); // we use intended addr here */ if(pP2PDeviceDesc && pP2PDeviceDesc->SsidLen) { //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); BOOLEAN bScanInProgress = MgntScanInProgress(&pP2PInfo->pAdapter->MgntInfo); P2PResetCommonChannelArrivingProcess(pP2PInfo); if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery P2PScanListCeaseScan(pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } else if(pP2PInfo->bExtendedListening) {// Doing extended listening P2PScanListCeaseScan(pP2PInfo); P2PExtendedListenComplete(pP2PInfo); } else if(bScanInProgress) {// Doing normal scan P2PScanListCeaseScan(pP2PInfo); } // Fill ConnectionContext PlatformMoveMemory(&pP2PInfo->ConnectionContext.ConnectingDevice, pP2PDeviceDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PInfo->ConnectionContext.Status = P2P_STATUS_SUCCESS; pP2PInfo->ConnectionContext.DialogToken = 0; pP2PInfo->ConnectionContext.FindPhaseLoopTimes = 0; pP2PInfo->ConnectionContext.bGoingToBeGO = FALSE; pP2PInfo->bPreGroupFormation = FALSE; pP2PInfo->State = P2P_STATE_PRE_PROVISIONING; PlatformCancelTimer(pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 100); } else {// failed to scan the GO RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PConnect(): the target is not in the scan list\n")); //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); pP2PInfo->State = P2P_STATE_INITIALIZED; } } } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PConnect() peer role is incorrect: %u\n", pP2PDeviceDesc->Role)); //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); return FALSE; } RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PConnect()\n")); return TRUE; } VOID P2PGOStartAutomously( IN PP2P_INFO pP2PInfo ) { P2P_PROFILE P2PProfile; RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PGOStartAutomously()\n")); P2PProfile.OpChannel = pP2PInfo->OperatingChannel; P2PDetermineGOSsid(pP2PInfo, P2PProfile.SsidBuf, &P2PProfile.SsidBufLen); CopySsid(pP2PInfo->SSIDBuf, pP2PInfo->SSIDLen, P2PProfile.SsidBuf, P2PProfile.SsidBufLen); P2PSetRole(pP2PInfo, P2P_GO); P2PSetOperatingState(pP2PInfo); pP2PInfo->bGOStartedAutonomously = TRUE; pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)P2P_STATUS_MAX; P2PIndicateStartApRequest(pP2PInfo, &P2PProfile); // // For PF #1, if we do this, legacy STA without WPS can't associate with us // (associated, but the STA keeps sending AssocReq) when we are an autonomous GO. // This may not be necessary to notify the UI that we are an GO now. // /*P2PIndicateGOFormatedInfo(pP2PInfo, P2P_STATUS_SUCCESS, TRUE, NULL); */ PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PGOStartAutomously()\n")); } VOID P2PDisconnect( IN PP2P_INFO pP2PInfo ) { BOOLEAN bScanInProgress; if(!P2P_ENABLED(pP2PInfo)) { return; } RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PDisconnect()\n")); // // Stop any existing scan // P2PResetCommonChannelArrivingProcess(pP2PInfo); bScanInProgress = MgntScanInProgress(&pP2PInfo->pAdapter->MgntInfo); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PDisconnect(): State: %u, bScanInProgres: %u\n", pP2PInfo->State, bScanInProgress)); if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } else if(pP2PInfo->bExtendedListening) {// Doing extended listening P2PExtendedListenComplete(pP2PInfo); } else if(bScanInProgress) {// Doing normal scan } // Reset disconnect slot count pP2PInfo->P2PGONoClientSlotCount = 0; pP2PInfo->P2PClientDisconnectedSlotCount = 0; pP2PInfo->bOppPS = FALSE; PlatformZeroMemory(pP2PInfo->NoADescriptors, sizeof(P2P_NOA_DESCRIPTOR) * P2P_MAX_NUM_NOA_DESC); P2PSetRole(pP2PInfo, P2P_DEVICE); pP2PInfo->State = P2P_STATE_INITIALIZED; PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); P2PSvc_OnDisconnect(pP2PInfo->pP2PSvcInfo); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PDisconnect()\n")); } // // Description: // Send the device discoverability request to ask the client in the group to be discoverable. // The receiver for this packet is the GO which the client belongs to. // Arguments: // [in] pP2PInfo - // The P2P context. // [in] DeviceAddress - // The target address of P2P client that this request sent to. // [in] bConnect - // TRUE if go to connect the target in the next step; otherwise, just send device discoverability request. // Return: // TRUE if this action is accepted. // BOOLEAN P2PDeviceDiscoverabilityReq( IN PP2P_INFO pP2PInfo, IN pu1Byte DeviceAddress, IN BOOLEAN bConnect ) { // // This function is to send a DevDiscoverabilityReq to a P2P Client // so that it will keep available for a duration of at least 100TU. // PP2P_CLIENT_INFO_DISCRIPTOR pClient = NULL; PP2P_DEVICE_DISCRIPTOR pGO = NULL; BOOLEAN bScanInProgress; RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PDeviceDiscoverabilityReqStart()\n")); PlatformZeroMemory(&pP2PInfo->DeviceDiscoverabilityContext, sizeof(P2P_DEVICE_DISCOVERABILITY_CONTEXT)); // // Find the client and its GO // if(!P2PScanListFindClient(pP2PInfo->ScanList, pP2PInfo->ScanListSize, DeviceAddress, NULL, &pGO, &pClient)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PDeviceDiscoverabilityReqStart(): client not found\n")); return FALSE; } RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PDeviceDiscoverabilityReqStart(): to send DeviceDiscoverabilityReq to the GO:\n", pGO->DeviceAddress); // // Record GO info for constructing P2P GroupID Attribute // cpMacAddr(pP2PInfo->DeviceDiscoverabilityContext.GODeviceAddr, pGO->DeviceAddress); CopySsid(pP2PInfo->DeviceDiscoverabilityContext.GOSsidBuf, pP2PInfo->DeviceDiscoverabilityContext.GOSsidLen, pGO->SsidBuf, pGO->SsidLen); // // Check Capability // if(!(pClient->DeviceCapability & dcP2PClientDiscoverability)) { return FALSE; } // // Stop any existing scan // bScanInProgress = MgntScanInProgress(&pP2PInfo->pAdapter->MgntInfo); if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) {// Doing P2P Device Discovery P2PScanListCeaseScan(pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } else if(pP2PInfo->bExtendedListening) {// Doing extended listening P2PScanListCeaseScan(pP2PInfo); P2PExtendedListenComplete(pP2PInfo); } else if(bScanInProgress) {// Doing normal scan P2PScanListCeaseScan(pP2PInfo); } // // Fill the context // cpMacAddr(pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress, pClient->DeviceAddress); cpMacAddr(pP2PInfo->DeviceDiscoverabilityContext.GoBssid, pGO->IntendedP2PInterfaceAddress); pP2PInfo->DeviceDiscoverabilityContext.DialogToken = IncreaseDialogToken(pP2PInfo->DialogToken); pP2PInfo->DeviceDiscoverabilityContext.Status = P2P_STATUS_SUCCESS; pP2PInfo->DeviceDiscoverabilityContext.GOChannel = pGO->OperatingChannel; pP2PInfo->DeviceDiscoverabilityContext.OriginalChannel = P2PGetChannel(pP2PInfo); pP2PInfo->DeviceDiscoverabilityContext.OriginalState = pP2PInfo->State; pP2PInfo->DeviceDiscoverabilityContext.bWaitingBeaconFromGO = TRUE; pP2PInfo->DeviceDiscoverabilityContext.bGoConnect = bConnect; // // Send Device Discoverability to the GO of the client when beacon is received // P2PSetChannel(pP2PInfo, pGO->OperatingChannel); pP2PInfo->State = P2P_STATE_DEVICE_DISCOVERABILITY_WAIT_BEACON; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEVICE_DISCOVERABILITY_BEACON_TIMEOUT); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PDeviceDiscoverabilityReqStart(): GO Ch: %u, \n", pP2PInfo->DeviceDiscoverabilityContext.GOChannel)); return TRUE; } BOOLEAN P2PInvitePeerStart( IN PP2P_INFO pP2PInfo, IN PP2P_LIB_INVITATION_REQ_CONTEXT pLibInvittionContext ) { // // At current stage, // 1. IntAddr // 2. SSID // are valid only when bInvokePersistent is TRUE. // BOOLEAN bRet = FALSE; PP2P_DEVICE_DISCRIPTOR pDevDesc = NULL; // Win8: NdisTest -------------------------------------------------------------------------------- // + If the peer does not exist, still do the invitation procedure as device PRT_GEN_TEMP_BUFFER pRtBuffer = NULL; PP2P_DEVICE_DISCRIPTOR pPseudoDevicePeer = NULL; pRtBuffer = GetGenTempBuffer(GetDefaultAdapter(pP2PInfo->pAdapter), sizeof(P2P_DEVICE_DISCRIPTOR)); pPseudoDevicePeer = (PP2P_DEVICE_DISCRIPTOR) pRtBuffer->Buffer.Ptr; //---------------------------------------------------------------------------------------------- RT_TRACE(COMP_P2P, DBG_LOUD, ("===> P2PInvitePeerStart():() port number %d state %d\n", pP2PInfo->pAdapter->pNdis62Common->PortNumber, pP2PInfo->State)); RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "DevAddr:\n", pLibInvittionContext->TargetDeviceAddress); RT_TRACE(COMP_P2P, DBG_LOUD, ("bPersistent: %u\n", pLibInvittionContext->bPersistent)); // // Check state // if(!P2P_ENABLED(pP2PInfo)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PInvitePeerStart(): P2P not enabled\n")); goto exit_P2PInvitePeerStart; } // // Clear invitation context // PlatformZeroMemory(&(pP2PInfo->InvitationContext), sizeof(P2P_INVITATION_CONTEXT)); // // Check self capability // if(!(pP2PInfo->DeviceCapability & dcP2PInvitationProcedure)) {// this device does not support invitation procedure RT_TRACE(COMP_P2P, DBG_LOUD, ("error: my DeviceCapability is %u\n", pP2PInfo->DeviceCapability)); goto exit_P2PInvitePeerStart; } // // Get the target descriptor // pDevDesc = P2PScanListFind(pP2PInfo->ScanList, pP2PInfo->ScanListSize, pLibInvittionContext->TargetDeviceAddress, NULL, NULL); if(pDevDesc == NULL) { RT_TRACE(COMP_P2P, DBG_LOUD, ("Peer not found in the scan list\n")); // Win8: For passing NdisTest: WFD_Group_ext-Invitation --------------------- PlatformZeroMemory(pPseudoDevicePeer, sizeof(P2P_DEVICE_DISCRIPTOR)); pDevDesc = pPseudoDevicePeer; pDevDesc->Role = P2P_DEVICE; pDevDesc->ListenChannel = P2P_DEFAULT_LISTEN_CHANNEL; cpMacAddr(pDevDesc->DeviceAddress, pLibInvittionContext->TargetDeviceAddress); // ------------------------------------------------------------------- //goto exit_P2PInvitePeerStart; } // Win8: Mark for passing the NdisTest: WFD_Group_ext-Invitation ------------------------------------------ #if 0 // // Check peer device capability // if(!(pDevDesc->DeviceCapability & dcP2PInvitationProcedure)) {// peer device does not support invitation procedure RT_TRACE(COMP_P2P, DBG_LOUD, ("error: peer DeviceCapability is %u, does not support invitation\n", pDevDesc->DeviceCapability)); goto exit_P2PInvitePeerStart; } #endif // ------------------------------------------------------------------------------------------------ // // If to invoke persistent, check peer group capability // if(pLibInvittionContext->bPersistent) { /* group cap is valid only when the device is a GO if(!(pDevDesc->GroupCapability & gcPersistentP2PGroup)) {// peer device does not support persistent group RT_TRACE(COMP_P2P, DBG_LOUD, ("error: peer GroupCapability is %u, does not support persistent\n", pDevDesc->DeviceCapability)); goto exit_P2PInvitePeerStart; } */ } // // Fill invitation context // P2PResetCommonChannelArrivingProcess(pP2PInfo); pP2PInfo->InvitationContext.InvitorRole= pLibInvittionContext->InvitorRole; pP2PInfo->InvitationContext.bPersistentInvitation = pLibInvittionContext->bPersistent; pP2PInfo->InvitationContext.DialogToken = IncreaseDialogToken(pP2PInfo->DialogToken); PlatformMoveMemory(&pP2PInfo->InvitationContext.InvitedDevice, pDevDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe = FALSE; pP2PInfo->InvitationContext.bInvitor = TRUE; pP2PInfo->InvitationContext.OpChannel = pLibInvittionContext->OpChannel; RT_TRACE(COMP_P2P, DBG_LOUD, ("DialogToken: %u, state: %u\n", pP2PInfo->InvitationContext.DialogToken, pP2PInfo->State)); // // Customization for different peer roles // RT_TRACE(COMP_P2P, DBG_LOUD, ("Peer Role: %u, My role: %u\n", pDevDesc->Role, pP2PInfo->Role)); if(pDevDesc->Role == P2P_DEVICE) {// need to send InvitationReq when common chnl arrive RT_TRACE(COMP_P2P, DBG_LOUD, ("Set bToSendInvitationReqOnProbe\n")); pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe = TRUE; } else if(pDevDesc->Role == P2P_CLIENT) {// need to make sure that the client can receive our InvitationReq pP2PInfo->InvitationContext.bToUseDeviceDiscoverability = TRUE; } else if(pDevDesc->Role == P2P_GO) {// need to make sure that the GO is awake for receiving our InvitationReq } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("error: unknown peer role: %u\n", pDevDesc->Role)); goto exit_P2PInvitePeerStart; } // // Fill Group ID (Device Addr and SSID) and Group BSSID // cpMacAddr(pP2PInfo->InvitationContext.GroupBssid, pLibInvittionContext->GroupBssid); cpMacAddr(pP2PInfo->InvitationContext.GODeviceAddress, pLibInvittionContext->GroupDeviceAddress); CopySsid(pP2PInfo->InvitationContext.SsidBuf, pP2PInfo->InvitationContext.SsidLen, pLibInvittionContext->GroupSsidBuf, pLibInvittionContext->GroupSsidLen); // // Decide when to send the InvitationReq // if(pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe) {// in this case, we send the req when ProbeReq from the peer is recvd if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(pP2PInfo->pAdapter->bInHctTest) P2PDeviceDiscovery(pP2PInfo, 6); else P2PDeviceDiscovery(pP2PInfo, 36); } else { if(pP2PInfo->pAdapter->bInHctTest) P2PDeviceDiscovery(pP2PInfo, 6); else P2PDeviceDiscovery(pP2PInfo, P2P_SCAN_FIND_PHASE_LOOP_TIMES); } bRet = TRUE; } else {// we send the req immediately pP2PInfo->State = P2P_STATE_INVITATION_REQ_SEND; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } exit_P2PInvitePeerStart: ReturnGenTempBuffer(GetDefaultAdapter(pP2PInfo->pAdapter), pRtBuffer); RT_TRACE(COMP_P2P, DBG_LOUD, ("<=== P2PInvitePeerStart()\n")); return bRet; } VOID P2PInvitePeerComplete( IN PP2P_INFO pP2PInfo ) { if(P2P_ACTING_AS_GO(pP2PInfo)) {// GO // TODO: } else if(P2P_ACTING_AS_CLIENT(pP2PInfo)) {// P2P Client SendNullFunctionData(pP2PInfo->pAdapter, pP2PInfo->pAdapter->MgntInfo.Bssid, FALSE); } else {// P2P Device } } //====================================================================== // Customized Indications //====================================================================== VOID P2PIndicateOnProvisionDiscoveryRsp( IN PP2P_INFO pP2PInfo, IN u2Byte ConfigMethod, IN pu1Byte DeviceAddress ) { pu1Byte pBuf = NULL; u4Byte BufSize = sizeof(u2Byte) + 6; PlatformAllocateMemory(pP2PInfo->pAdapter, (void**)&pBuf, BufSize); if(pBuf == NULL) return; PlatformMoveMemory(pBuf, &ConfigMethod, sizeof(u2Byte)); PlatformMoveMemory(pBuf + sizeof(u2Byte), DeviceAddress, 6); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2PIndicateOnProvisionDiscoveryRsp", pBuf, BufSize); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_ON_PROVISION_DISC_RSP, RT_CUSTOM_INDI_TARGET_IHV, pBuf, sizeof(u2Byte) + 6); PlatformFreeMemory(pBuf, BufSize); } VOID P2PIndicateOnInvitationReq( IN PP2P_INFO pP2PInfo, IN PP2P_LIB_INVITATION_REQ_CONTEXT pLibInvitationReq ) { //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_ON_INVITATION_REQ, RT_CUSTOM_INDI_TARGET_IHV, pLibInvitationReq, sizeof(P2P_LIB_INVITATION_REQ_CONTEXT)); } VOID P2PIndicateOnInvitationRsp( IN PP2P_INFO pP2PInfo, IN P2P_STATUS_CODE Status, IN BOOLEAN bPersistent, IN u1Byte OpChannel, IN P2P_ROLE Role, IN u1Byte GroupSsidLen, IN pu1Byte GroupSsidBuf ) { P2P_LIB_INVITATION_RSP_CONTEXT LibInvitationRsp; LibInvitationRsp.Role= Role; LibInvitationRsp.bPersistent = bPersistent; LibInvitationRsp.OpChannel = OpChannel; LibInvitationRsp.Status = Status; CopySsid(LibInvitationRsp.GroupSsidBuf, LibInvitationRsp.GroupSsidLen, GroupSsidBuf, GroupSsidLen); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_ON_INVITATION_RSP, RT_CUSTOM_INDI_TARGET_IHV, &LibInvitationRsp, sizeof(LibInvitationRsp)); } VOID P2PIndicateOnProvisionDiscoveryReq( IN PP2P_INFO pP2PInfo, IN u2Byte ConfigMethod, IN pu1Byte DeviceAddress, IN PP2P_WPS_ATTRIBUTES pWpsAttributes ) { pu1Byte pBuf = NULL; u4Byte BufSize = sizeof(u2Byte) + 6 + sizeof(P2P_WPS_ATTRIBUTES); PlatformAllocateMemory(pP2PInfo->pAdapter, (void**)&pBuf, BufSize); if(pBuf == NULL) return; PlatformMoveMemory(pBuf, &ConfigMethod, sizeof(u2Byte)); PlatformMoveMemory(pBuf + sizeof(u2Byte), DeviceAddress, 6); PlatformMoveMemory(pBuf + sizeof(u2Byte) + 6, pWpsAttributes, sizeof(P2P_WPS_ATTRIBUTES)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2PIndicateOnProvisionDiscoveryReq", pBuf, BufSize); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_ON_PROVISION_DISC_REQ, RT_CUSTOM_INDI_TARGET_IHV, pBuf, BufSize); PlatformFreeMemory(pBuf, BufSize); } VOID P2PIndicateStartApRequest( IN PP2P_INFO pP2PInfo, IN PP2P_PROFILE pP2PProfile ) { P2P_PROFILE P2PProfile; BOOLEAN bDefPortConnected = P2PDefaultPortConnected(pP2PInfo); BOOLEAN bCrossConnectionEnabled = pP2PInfo->GroupCapability & gcCrossConnection; BOOLEAN bToEnableICS = FALSE; P2PProfile.OpChannel = pP2PProfile->OpChannel; P2PProfile.SsidBufLen = pP2PProfile->SsidBufLen; PlatformMoveMemory(P2PProfile.SsidBuf, pP2PProfile->SsidBuf, pP2PProfile->SsidBufLen); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateStartApRequest(): Indicate NDIS_STATUS_P2P_START_AP_REQ, OpChannel: %u\n", pP2PProfile->OpChannel)); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "SSID:\n", pP2PProfile->SsidBuf, pP2PProfile->SsidBufLen); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateStartApRequest(): bDefPortConnected: %u, bCrossConnectionEnabled: %u\n", bDefPortConnected, bCrossConnectionEnabled)); if(bDefPortConnected && bCrossConnectionEnabled) { bToEnableICS = TRUE; } PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_ENABLE_ICS, RT_CUSTOM_INDI_TARGET_IHV, &bToEnableICS, sizeof(BOOLEAN)); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_START_AP_REQ, RT_CUSTOM_INDI_TARGET_IHV, &P2PProfile, sizeof(P2P_PROFILE)); } VOID P2PIndicateStopApRequest( IN PP2P_INFO pP2PInfo ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateStopApRequest()\n")); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_STOP_AP_REQ, RT_CUSTOM_INDI_TARGET_IHV, NULL, 0); } VOID P2PIndicateDisconnectClientRequest( IN PP2P_INFO pP2PInfo ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateDisconnectClientRequest()\n")); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_DISCONNECT_CLIENT_REQ, RT_CUSTOM_INDI_TARGET_IHV, NULL, 0); } VOID P2PIndicateGOFormatedInfo( IN PP2P_INFO pP2PInfo, IN u1Byte Status, IN BOOLEAN bGoingToBeGO, IN PP2P_DEVICE_DISCRIPTOR pDevDesc ) { // P2P_GO_FORMATED_INFO P2PGOFormatedInfo; PP2P_GO_FORMATED_INFO pP2PGOFormatedInfo; PRT_GEN_TEMP_BUFFER pGenBufP2PGOFormatedInfo; PADAPTER Adapter = pP2PInfo->pAdapter; pGenBufP2PGOFormatedInfo = GetGenTempBuffer (Adapter, sizeof(P2P_GO_FORMATED_INFO)); pP2PGOFormatedInfo = (P2P_GO_FORMATED_INFO *)pGenBufP2PGOFormatedInfo->Buffer.Ptr; pP2PGOFormatedInfo->p2pRole = (Status != P2P_STATUS_SUCCESS) ? (P2P_DEVICE) : ((bGoingToBeGO) ? (P2P_GO) : (P2P_CLIENT)); if(pDevDesc) { PlatformMoveMemory(&(pP2PGOFormatedInfo->targetDesc), pDevDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); pP2PGOFormatedInfo->targetDesc.Status = Status; if(P2P_GO == pP2PGOFormatedInfo->p2pRole) { pP2PGOFormatedInfo->targetDesc.SsidLen = pP2PInfo->SSIDLen; PlatformMoveMemory(pP2PGOFormatedInfo->targetDesc.SsidBuf, pP2PInfo->SSIDBuf, pP2PInfo->SSIDLen); pP2PGOFormatedInfo->targetDesc.OperatingChannel = pP2PInfo->OperatingChannel; } RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateGOFormatedInfo(): Status: %u, Role: %u\n", Status, pP2PGOFormatedInfo->p2pRole)); //P2PDumpScanList(pDevDesc, 1); } else { PlatformZeroMemory(&(pP2PGOFormatedInfo->targetDesc), sizeof(P2P_DEVICE_DISCRIPTOR)); } PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_GO_FORMATED, RT_CUSTOM_INDI_TARGET_IHV, pP2PGOFormatedInfo, sizeof(P2P_GO_FORMATED_INFO)); ReturnGenTempBuffer (Adapter, pGenBufP2PGOFormatedInfo); } VOID P2PIndicateCurrentState( IN PP2P_INFO pP2PInfo, IN P2P_STATE CurrentState ) { u8Byte CurrentTime = PlatformGetCurrentTime(); BOOLEAN bToIndicate = FALSE; u8Byte TimeDiff = CurrentTime - pP2PInfo->PreviouslyIndicateStateTime; if(pP2PInfo->PreviouslyIndicatedState != CurrentState) // to prevent redundent indication { bToIndicate = TRUE; } else if(TimeDiff > 4000000) // 4sec { bToIndicate = TRUE; } if(bToIndicate) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateCurrentState(): State: %u, Role: %u, nScanList: %u, nScanList4Q: %u, IntfIndex: %u portnumber %d\n", CurrentState, pP2PInfo->Role, pP2PInfo->ScanListSize, pP2PInfo->ScanList4QuerySize, pP2PInfo->pAdapter->interfaceIndex, pP2PInfo->pAdapter->pNdis62Common->PortNumber)); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_CURRENT_STATE, RT_CUSTOM_INDI_TARGET_IHV, &CurrentState, sizeof(P2P_STATE)); pP2PInfo->PreviouslyIndicatedState = CurrentState; pP2PInfo->PreviouslyIndicateStateTime = PlatformGetCurrentTime(); } } VOID P2PIndicateCurrentRole( IN PP2P_INFO pP2PInfo, IN P2P_ROLE CurrentRole ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateCurrentRole(): Role: %u state %d\n", pP2PInfo->Role, pP2PInfo->State)); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_CURRENT_ROLE, RT_CUSTOM_INDI_TARGET_IHV, &CurrentRole, sizeof(P2P_ROLE)); } VOID P2PIndicateCurrentDevPasswdId( IN PP2P_INFO pP2PInfo, IN u2Byte CurrentDevPasswdId ) { //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateCurrentDevPasswdId(): DevPasswdId: %u\n", CurrentDevPasswdId)); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_CURRENT_DEV_PASSWD_ID, RT_CUSTOM_INDI_TARGET_IHV, &CurrentDevPasswdId, sizeof(u2Byte)); } // // Description: // Indicate that one device wants to do GO formation when we are the P2P client. // Arguments: // [in] pP2PInfo - // The P2P context. // [in] pDevDesc - // The descriptor info for this request of device. // VOID P2PIndicateDeviceReqClientGoFormation( IN PP2P_INFO pP2PInfo, IN PP2P_DEVICE_DISCRIPTOR pDevDesc ) { if(pDevDesc == NULL) return; RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PIndicateDeviceReqClientGoFormation(): ", pDevDesc->DeviceAddress); //P2PDumpScanList(pDevDesc, 1); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_DEV_REQ_CLIENT_GO_FORMATION, RT_CUSTOM_INDI_TARGET_IHV, pDevDesc, sizeof(P2P_DEVICE_DISCRIPTOR)); } VOID P2PIndicateClientConnected( IN PP2P_INFO pP2PInfo, IN pu1Byte ClientInterfaceAddr ) { if(ClientInterfaceAddr == NULL) return; RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PIndicateClientConnected(): ", ClientInterfaceAddr); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_CLIENT_CONNECTED, RT_CUSTOM_INDI_TARGET_IHV, ClientInterfaceAddr, 6); } VOID P2PIndicateClientDisconnected( IN PP2P_INFO pP2PInfo, IN pu1Byte ClientInterfaceAddr ) { if(ClientInterfaceAddr == NULL) return; RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PIndicateClientDisconnected(): ", ClientInterfaceAddr); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_CLIENT_DISCONNECTED, RT_CUSTOM_INDI_TARGET_IHV, ClientInterfaceAddr, 6); } VOID P2PIndicateDeviceDiscoveryComplete( IN PP2P_INFO pP2PInfo ) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateDeviceDiscoveryComplete()\n")); //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_DEV_DISC_COMPLETE, RT_CUSTOM_INDI_TARGET_IHV, NULL, 0); } VOID P2PIndicateOnSDRsp( IN PP2P_INFO pP2PInfo, IN PP2P_SD_CONTEXT pSDContext ) { u1Byte i = 0; u4Byte BufSize = FIELD_OFFSET(P2P_SD_RSP_CONTEXT, ServiceRspTLVList) + pSDContext->ServiceRspRecvdSize * sizeof(P2P_SERVICE_RSP_TLV); PP2P_SD_RSP_CONTEXT pSDRspContext = NULL; PlatformAllocateMemory(pP2PInfo->pAdapter, (void**)&pSDRspContext, BufSize); if(!pSDRspContext) return; if(!pSDContext->bRequester) return; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateOnSDRsp: Recv Service Rsp TLVs:\n")); // Fill the SDRspContext pSDRspContext->SDStatus= pSDContext->Status; cpMacAddr(pSDRspContext->SourceDeviceAddress, pSDContext->TargetDeviceAddress); pSDRspContext->ServiceUpdateIndicator = pSDContext->ServiceUpdateIndicator; pSDRspContext->ServiceRspTLVSize = pSDContext->ServiceRspRecvdSize; for(i = 0; i < pSDContext->ServiceRspRecvdSize; i++) {// copy each Rsp TLV RT_TRACE(COMP_P2P, DBG_LOUD, ("TLV %u, Protocol ID: %u\n", i, pSDContext->ServiceRspRecvd[i].ServiceDesc.ServiceType)); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "Recv Service Rsp TLV:", pSDContext->ServiceRspRecvd[i].ServiceDesc.Buffer, pSDContext->ServiceRspRecvd[i].ServiceDesc.BufferLength); PlatformMoveMemory(&(pSDRspContext->ServiceRspTLVList[i]), &(pSDContext->ServiceRspRecvd[i]), sizeof(P2P_SERVICE_RSP_TLV)); } PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_SD_RSP, RT_CUSTOM_INDI_TARGET_IHV, pSDRspContext, BufSize); PlatformFreeMemory(pSDRspContext, BufSize); } VOID P2PIndicateOnSDReq( IN PP2P_INFO pP2PInfo, IN PP2P_SD_CONTEXT pSDContext ) { u1Byte i = 0; u4Byte BufSize = FIELD_OFFSET(P2P_SD_REQ_CONTEXT, ServiceReqTLVList) + pSDContext->ServiceReqRecvdSize * sizeof(P2P_SERVICE_REQ_TLV); PP2P_SD_REQ_CONTEXT pSDReqContext = NULL; if(pSDContext->bRequester) return; PlatformAllocateMemory(pP2PInfo->pAdapter, (void**)&pSDReqContext, BufSize); if(!pSDReqContext) return; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateOnSDReq()\n")); // Fill the SDReqContext cpMacAddr(pSDReqContext->TargetDeviceAddress, pSDContext->TargetDeviceAddress); pSDReqContext->ServiceReqTLVSize = pSDContext->ServiceReqRecvdSize; for(i = 0; i < pSDContext->ServiceReqRecvdSize; i++) {// copy each Rsp TLV RT_TRACE(COMP_P2P, DBG_LOUD, ("TLV %u, Protocol ID: %u\n", i, pSDContext->ServiceRspRecvd[i].ServiceDesc.ServiceType)); RT_PRINT_STR(COMP_P2P, DBG_LOUD, "Recv Service Req TLV:", pSDContext->ServiceRspRecvd[i].ServiceDesc.Buffer, pSDContext->ServiceRspRecvd[i].ServiceDesc.BufferLength); PlatformMoveMemory(&(pSDReqContext->ServiceReqTLVList[i]), &(pSDContext->ServiceReqRecvd[i]), sizeof(P2P_SERVICE_REQ_TLV)); } PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_SD_REQ, RT_CUSTOM_INDI_TARGET_IHV, pSDReqContext, BufSize); PlatformFreeMemory(pSDReqContext, BufSize); } VOID P2PIndicateScanList( IN PP2P_INFO pP2PInfo ) { u4Byte BufSize = 0; pu1Byte pBuf = NULL; u4Byte idxScanList = 0; BOOLEAN bAlloc = TRUE; do { //p2p_DevList_Translate(&pP2PInfo->devList, P2P_MAX_SCAN_LIST, &pP2PInfo->ScanList4QuerySize, pP2PInfo->ScanList4Query); if(0 == pP2PInfo->ScanList4QuerySize) { break; } if(0x00000000 == pP2PInfo->P2PVersion) {// v0 PP2P_DEVICE_DESCRIPTOR_V0 pDesc = NULL; BufSize = sizeof(P2P_DEVICE_DESCRIPTOR_V0) * pP2PInfo->ScanList4QuerySize; if(0 == BufSize) break; PlatformAllocateMemory(pP2PInfo->pAdapter, &pBuf, BufSize); if(NULL == pBuf) break; pDesc = (PP2P_DEVICE_DESCRIPTOR_V0)pBuf; for(idxScanList = 0; idxScanList < pP2PInfo->ScanList4QuerySize; idxScanList++) { memcpy(pDesc + idxScanList, &pP2PInfo->ScanList4Query[idxScanList], sizeof(P2P_DEVICE_DESCRIPTOR_V0)); } } else if(0x00000001 == pP2PInfo->P2PVersion) {// v1 PP2P_DEVICE_DESCRIPTOR_V1 pDesc = NULL; BufSize = sizeof(P2P_DEVICE_DESCRIPTOR_V1) * pP2PInfo->ScanList4QuerySize; if(0 == BufSize) break; PlatformAllocateMemory(pP2PInfo->pAdapter, &pBuf, BufSize); if(NULL == pBuf) break; pDesc = (PP2P_DEVICE_DESCRIPTOR_V1)pBuf; for(idxScanList = 0; idxScanList < pP2PInfo->ScanList4QuerySize; idxScanList++) { memcpy(pDesc + idxScanList, &pP2PInfo->ScanList4Query[idxScanList], sizeof(P2P_DEVICE_DESCRIPTOR_V1)); } } else {// v2/v3 pBuf = (pu1Byte)pP2PInfo->ScanList4Query; BufSize = sizeof(P2P_DEVICE_DESCRIPTOR_V2) * pP2PInfo->ScanList4QuerySize; bAlloc = FALSE; } }while(FALSE); if(pBuf || (NULL == pBuf && 0 == BufSize)) { PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_SCAN_LIST, RT_CUSTOM_INDI_TARGET_IHV, pBuf, BufSize); if(bAlloc && pBuf) PlatformFreeMemory(pBuf, BufSize); } } VOID P2PIndicateChangingApChnl( IN PP2P_INFO pP2PInfo, IN u1Byte oldChnl, IN u1Byte newChnl ) { u1Byte buf[2]; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PIndicateChangingApChnl(): %u -> %u\n", oldChnl, newChnl)); buf[0] = oldChnl; buf[1] = newChnl; PlatformIndicateCustomStatus( pP2PInfo->pAdapter, RT_CUSTOM_EVENT_P2P_CHANGING_AP_CHANNEL, RT_CUSTOM_INDI_TARGET_IHV, buf, sizeof(buf)); } //====================================================================== // P2P Managmement //====================================================================== VOID P2PMgntTimerCallback( IN PRT_TIMER pTimer ) { PADAPTER pAdapter = (PADAPTER)pTimer->Adapter; PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); BOOLEAN bToFireTimer = TRUE; PADAPTER pLoopAdapter = NULL; PP2P_DEVICE_LIST_ENTRY pP2PDeviceListEntry = NULL; u4Byte BoostInitGainValue = 0; BOOLEAN bScanInProgress; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); VOID *customScanInfo = GET_CUSTOM_SCAN_INFO(pAdapter); VOID *req = NULL; FRAME_BUF *probeReqBuf = NULL; pP2PInfo->LastTimerFired = PlatformGetCurrentTime(); if(!P2P_ENABLED(pP2PInfo)) { PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); return; } if(RT_DRIVER_STOP(pAdapter)) { PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); return; } PlatformAcquireSpinLock(pAdapter, RT_P2P_SPIN_LOCK); if(P2P_GET_REF_CNT(pP2PInfo) > 0) { PlatformReleaseSpinLock(pAdapter, RT_P2P_SPIN_LOCK); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("The P2P command is setting in progress (RefCnt = %d), skip timer and set later!\n", pP2PInfo->RefCnt)); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEFAULT_MGNT_PERIOD); goto exit_P2PMgntTimerCallback; } PlatformReleaseSpinLock(pAdapter, RT_P2P_SPIN_LOCK); // Let the default port can connect to AP ----------------------------------------------------------- { PADAPTER pClientPort = GetFirstClientPort(pP2PInfo->pAdapter); PADAPTER pDefaultPort = GetDefaultAdapter(pP2PInfo->pAdapter); if(pClientPort == NULL) pClientPort = pDefaultPort; if(MgntIsLinkInProgress(&pDefaultPort->MgntInfo) || MgntIsLinkInProgress(&pClientPort->MgntInfo)) { RT_TRACE(COMP_P2P, DBG_LOUD, ("MgntIsLinkInProgress(): default/client port link in progress\n")); return; } } // ------------------------------------------------------------------------------------------- // // We assume that the optional Privision Discovery has already been done by the WPS module in the upper layer. // // // Indicate P2P State to IHVSvc // if(P2P_ADAPTER_RTK_SUPPORT_P2P(pP2PInfo->pAdapter)) { P2PIndicateCurrentState(pP2PInfo, pP2PInfo->State); // // Force scan list indication // pP2PInfo->ForceScanListIndicateSlotCount++; if(pP2PInfo->ForceScanListIndicateSlotCount == P2P_FORCE_SCAN_LIST_INDICATE_PERIOD_SC) { //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Forced scan list indication\n")); pP2PInfo->ForceScanListIndicateSlotCount = 0; PlatformIndicateCustomStatus( pAdapter, RT_CUSTOM_EVENT_P2P_INDICATE_SCAN_LIST, RT_CUSTOM_INDI_TARGET_IHV, pP2PInfo->ScanList4Query, (sizeof(P2P_DEVICE_DISCRIPTOR) * pP2PInfo->ScanList4QuerySize)); } } // // Notify UI the current device password ID so that it can determine whether provisioning info is available // Note that UI determines which peer config method we shall use for doing WPS //// TODO: this may be too regular, but note that UI may counting on this indication for determine provision info timeout //P2PIndicateCurrentDevPasswdId(pP2PInfo, pP2PInfo->WpsDevPasswdId); if(pP2PInfo->State == P2P_STATE_INITIALIZED) { pP2PInfo->ExtListenTimingPeriodSlotCount++; } else {// start counting in only initialized state pP2PInfo->ExtListenTimingPeriodSlotCount = 0; } if(pP2PInfo->bReinitiateConnection) { if(PlatformGetCurrentTime() - pP2PInfo->TimeStartWaitingForReinitiate > 120000000) {// 120 sec timeout pP2PInfo->bReinitiateConnection = FALSE; pP2PInfo->TimeStartWaitingForReinitiate = 0; } } // Timeout mechanism for Comeback Request if(pP2PInfo->SDContext.bDoingServiceDiscovery && pP2PInfo->SDContext.bFragment && !pP2PInfo->SDContext.bRequester) { pP2PInfo->SDWaitForComebackReqSlotCount++; if(pP2PInfo->SDWaitForComebackReqSlotCount == P2P_SD_COMEBACK_REQ_TIMEOUT_SC) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): timeout waiting for ComebackReq\n")); PlatformZeroMemory(&pP2PInfo->SDContext, sizeof(P2P_SD_CONTEXT)); pP2PInfo->SDWaitForComebackReqSlotCount = 0; } } /*RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): dc: %u, gc: %u, ExtSlot: %u, bExtListen: %u, bPreGroupFormation: %u\n", pP2PInfo->DeviceCapability, pP2PInfo->GroupCapability, pP2PInfo->ExtListenTimingPeriodSlotCount, pP2PInfo->bExtendedListening, pP2PInfo->bPreGroupFormation)); */ // Add "pHalData->SwChnlInProgress" to protect the 92D IQK process. if(pHalData->SwChnlInProgress) { PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_SWITCH_CHNL_PERIOD); goto exit_P2PMgntTimerCallback; } bScanInProgress = MgntScanInProgress(pMgntInfo); //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): state: %u\n", pP2PInfo->State)); if(bScanInProgress) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): scan in progress\n")); if(pP2PInfo->State == P2P_STATE_GO_NEGO_REQ_SEND || pP2PInfo->State == P2P_STATE_PROVISION_DISCOVERY_REQ_SEND || pP2PInfo->State == P2P_STATE_INVITATION_REQ_SEND || pP2PInfo->State == P2P_STATE_SERVICE_DISCOVERY_REQ_SEND) { // // For these state, we shall enter them ASAP so that when the packet is sent, // the peer is still on the listen channel. // However, we can't arbitrarily change the timer because that will make extended listen // timing incorrect. // PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_SWITCH_CHNL_PERIOD); goto exit_P2PMgntTimerCallback; } else { PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_SCAN_PERIOD_SCAN); goto exit_P2PMgntTimerCallback; } } else {// this is by referencing InactivePsTimerCallback() PADAPTER pDefaultAdapter = GetDefaultAdapter(pP2PInfo->pAdapter); PMGNT_INFO pDefaultMgntInfo = &pDefaultAdapter->MgntInfo; PRT_POWER_SAVE_CONTROL pPSC = GET_POWER_SAVE_CONTROL(pDefaultMgntInfo); // // If processing, we may have issued a customized scan and InactivePsWorkItemCallback // is still processing. In this case, bScanInProgress is false (but we expect it to be true). // If we let it go down, the P2P state machine will go to next state immediately, // and the action should be taken in the previous state will not be done. // if (pPSC->bSwRfProcessing) { //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback():bSwRfProcessing\n")); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_SCAN_PERIOD_SCAN); goto exit_P2PMgntTimerCallback; } } switch(pP2PInfo->State) { case P2P_STATE_INITIALIZED: { u8Byte curTime = PlatformGetCurrentTime(); if(!P2PIsN24GSupported(pP2PInfo)) {// don't do extended listening if 2.4G is not supported break; } if(pP2PInfo->bExtendedListening) { P2PExtendedListenComplete(pP2PInfo); } if(pP2PInfo->ExtListenTimingPeriodSlotCount >= (u4Byte)P2P_EXT_LISTEN_TIMING_PERIOD_SC && MultiportGetLastConnectionActionTime(pAdapter) + P2P_BLOCK_NORMAL_SCAN_PERIOD <= curTime ) {// enter Listen State for pP2PInfo->ExtListenTimingDuration pP2PInfo->ExtListenTimingPeriodSlotCount = 1; // this slot also be the first slot if(pP2PInfo->ExtListenTimingDuration > 0) { P2PExtendedListenStart(pP2PInfo); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Wait for ExtListen: P2P_EXT_LISTEN_TIMING_PERIOD_SC = %d\n", P2P_EXT_LISTEN_TIMING_PERIOD_SC)); // // Next time we get in P2P_STATE_INITIALIZED is when Extended Listen complete. // } break; } } break; //====================================================================== // Device Discovery //====================================================================== case P2P_STATE_DEV_DISC_START: { if(!P2PIsN24GSupported(pP2PInfo)) {// don't do find and listen phase on 5G pP2PInfo->State = P2P_STATE_SCAN; if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) break; probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_ProbeReq(probeReqBuf, pP2PInfo); P2PConstructScanList(pP2PInfo, req, P2P_LOWEST_RATE, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "dev disc start"); pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; break; } RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Start Device Discovery: loop times: %u\n", pP2PInfo->ConnectionContext.FindPhaseLoopTimes)); pP2PInfo->State = P2P_STATE_SCAN; // enter Scan Phase if(pP2PInfo->bPreGroupFormation|| pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe || pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery || pP2PInfo->SDContext.bDoingServiceDiscovery || pP2PInfo->ConnectionContext.FindPhaseLoopTimes == 0xFC) {// this is a discovery issued by invitation procedure => //don't need the scan phase, enter listen state directly pP2PInfo->State = P2P_STATE_SEARCH; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(pP2PInfo->bDiscoverForSpecificChannels) { P2PDeviceDiscoverForSpecificChannels( pP2PInfo, pP2PInfo->DiscoverForSpecificChannels, pP2PInfo->uNumberOfDiscoverForSpecificChannels ); pP2PInfo->State = P2P_STATE_SPECIAL_PEER_SEARCH; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 50); bToFireTimer = FALSE; break; } } if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { // For Win 8: OID_DOT11_WFD_DISCOVER_REQUEST ------------------------------------------ if(pP2PInfo->DiscoverSequence & P2P_DISCOVERY_SCAN_PHASE) { RT_TRACE(COMP_P2P,DBG_LOUD, ("DiscoverSequence & P2PDiscovery_scan_phase\n")); } else { //Jump to the search state directly since the scan is not needed pP2PInfo->State = P2P_STATE_SEARCH; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } // ------------------------------------------------------------------------------------ } //Sinda: temporarily mark. Because OS does not care bForceScanLegacyNetworks and it is always 0. //So at this condition, we do not check bForceScanLegacyNetworks and always do legacy scan. #if 0 if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(pP2PInfo->bForceScanLegacyNetworks == FALSE) { RT_TRACE(COMP_P2P,DBG_LOUD, ("pP2PInfo->bForceScanLegacyNetworks is FALSE and goto search state to scan social channel\n")); //Jump to the search state directly since the scan is not needed pP2PInfo->State = P2P_STATE_SEARCH; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } } #endif } /*FALL THROUGH*/ case P2P_STATE_SCAN: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Scan Phase\n")); if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) break; probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_ProbeReq(probeReqBuf, pP2PInfo); P2PConstructScanList(pP2PInfo, req, MGN_1M, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "scan phase"); pP2PInfo->State = P2P_STATE_LISTEN; // enter Listen State } break; case P2P_STATE_LISTEN: { if(pP2PInfo->ScanDeviceIDs.uNumOfDeviceIDs > 0) { u1Byte i = 0; BOOLEAN bFound = FALSE; for(i = 0; i < pP2PInfo->DeviceListForQuery.uNumberOfDevices; i++) { if(pP2PInfo->DeviceListForQuery.DeviceEntry[i].DeviceAddress != NULL) { if( // Make sure the probe response is received eqMacAddr(pP2PInfo->ScanDeviceIDs.DeviceIDs[0], pP2PInfo->DeviceListForQuery.DeviceEntry[i].DeviceAddress) && pP2PInfo->DeviceListForQuery.DeviceEntry[i].ProbeResponseHostTimestamp != 0 ) { bFound = TRUE; } } } if(bFound == TRUE) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: DeviceID Found : Terminate Search State !\n", __FUNCTION__)); pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } } // For Win 8: OID_DOT11_WFD_DISCOVER_REQUEST ------------------------------------------ if(!(pP2PInfo->DiscoverSequence & P2P_DISCOVERY_FIND_PHASE) && P2PScanListAllFound(pP2PInfo)) { //Bypass the find phase RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Find device\n")); pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } // ------------------------------------------------------------------------------------ if(pP2PInfo->ConnectionContext.FindPhaseLoopTimes != 0) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Listen State\n")); if(P2P_SKIP_SCAN_LOOP_CNT > 0) { BOOLEAN portConnected = FALSE; pLoopAdapter = GetDefaultAdapter(pAdapter); pP2PInfo->findPhaseSkipCnt = (pP2PInfo->findPhaseSkipCnt + 1) % (P2P_SKIP_SCAN_LOOP_CNT + 1); while(pLoopAdapter) { if(pLoopAdapter->MgntInfo.mAssoc) { portConnected = TRUE; break; } pLoopAdapter = GetNextExtAdapter(pLoopAdapter); } if(portConnected && P2P_SKIP_SCAN_LOOP_CNT == pP2PInfo->findPhaseSkipCnt) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("[P2P] Skip next P2P (%d) scan\n", pP2PInfo->findPhaseSkipCnt)); PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, P2P_SKIP_SCAN_DURATION_MS); bToFireTimer = FALSE; break; } } if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) break; probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_ProbeReq(probeReqBuf, pP2PInfo); P2PConstructScanList(pP2PInfo, req, P2P_LOWEST_RATE, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "listen state"); pP2PInfo->State = P2P_STATE_SEARCH; // enter Search State break; } else { pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; /*FALL THROUGH*/ } } case P2P_STATE_DEV_DISC_COMPLETE: { P2P_STATE NextState = pP2PInfo->StateBeforeScan; BOOLEAN bFailedToArriveCommonChannel = FALSE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Device Discovery Complete\n")); if(pP2PInfo->bPreGroupFormation) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Pre Group Formation Failed\n")); pP2PInfo->ConnectionContext.Status = P2P_STATUS_FAIL_COMMON_CHANNEL_NOT_ARRIVED; bFailedToArriveCommonChannel = TRUE; NextState = pP2PInfo->StateBeforeScan; pP2PInfo->bPreGroupFormation = FALSE; // // GO Nego failed, indicate to UI // pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); PlatformZeroMemory(&pP2PInfo->ConnectionContext, sizeof(pP2PInfo->ConnectionContext)); p2p_IndicateActionFrameSendComplete(pP2PInfo, P2P_EVENT_GO_NEGOTIATION_REQUEST_SEND_COMPLETE, RT_STATUS_FAILURE, NULL, 0); } else if(pP2PInfo->InvitationContext.bToSendInvitationReqOnProbe) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Failed to send InvitationReq to peer\n")); pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_COMMON_CHANNEL_NOT_ARRIVED; bFailedToArriveCommonChannel = TRUE; NextState = P2P_STATE_INVITATION_COMPLETE; // For Win8: OID_DOT11_WFD_SEND_INVITATION_REQUEST ----------------------------------------------------- if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { MEMORY_BUFFER mbObject = {NULL, 0}; P2P_EVENT_DATA eventData; PlatformZeroMemory(&eventData, sizeof(P2P_EVENT_DATA)); eventData.rtStatus = RT_STATUS_FAILURE; mbObject.Buffer = (pu1Byte) &eventData; mbObject.Length = sizeof(P2P_EVENT_DATA); PlatformIndicateP2PEvent(pP2PInfo, P2P_EVENT_INVITATION_REQUEST_SEND_COMPLETE, &mbObject); } //------------------------------------------------------------------------------------------------------ } else if(pP2PInfo->ProvisionDiscoveryContext.bDoingProvisionDiscovery) { P2P_DEV_LIST_ENTRY *pDev = NULL; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(pP2PInfo->bProvisionRequestUseGroupID) pDev = p2p_DevList_GetGo(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.devAddr); else pDev = p2p_DevList_Get(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.devAddr, P2P_DEV_TYPE_DEV); } else { if(NULL == (pDev = p2p_DevList_GetGo(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.devAddr))) pDev = p2p_DevList_Get(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.devAddr, P2P_DEV_TYPE_DEV); } if(pDev){ pDev->p2p->pdStatus = P2P_SC_FAIL_COMMON_CHANNEL_NOT_ARRIVED; } RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Failed to send ProvisionDiscReq to peer\n")); bFailedToArriveCommonChannel = TRUE; NextState = P2P_STATE_PROVISION_DISCOVERY_COMPLETE; p2p_IndicateActionFrameSendComplete(pP2PInfo, P2P_EVENT_PROVISION_DISCOVERY_REQUEST_SEND_COMPLETE, RT_STATUS_FAILURE, NULL, 0); } else if (pP2PInfo->SDContext.bDoingServiceDiscovery) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Failed to send ServiceDiscoveryReq to peer\n")); pP2PInfo->SDContext.Status = P2P_SD_STATUS_COMMON_CHANNEL_NOT_ARRIVED; bFailedToArriveCommonChannel = TRUE; NextState = P2P_STATE_SERVICE_DISCOVERY_COMPLETE; } else {// the loop between listen and find phase has been completed //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); } if(P2P_DOING_PURE_DEVICE_DISCOVERY(pP2PInfo)) { P2PIndicateDeviceDiscoveryComplete(pP2PInfo); } P2PDeviceDiscoveryComplete(pP2PInfo, TRUE); if(bFailedToArriveCommonChannel) { pP2PInfo->State = NextState; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } } break; case P2P_STATE_SPECIAL_PEER_SEARCH: { if(pP2PInfo->ScanDeviceIDs.uNumOfDeviceIDs > 0) { u1Byte i = 0; BOOLEAN bFound = FALSE; for(i = 0; i < pP2PInfo->DeviceListForQuery.uNumberOfDevices; i++) { if(pP2PInfo->DeviceListForQuery.DeviceEntry[i].DeviceAddress != NULL) { if( // Make sure the probe response is received eqMacAddr(pP2PInfo->ScanDeviceIDs.DeviceIDs[0], pP2PInfo->DeviceListForQuery.DeviceEntry[i].DeviceAddress) && pP2PInfo->DeviceListForQuery.DeviceEntry[i].ProbeResponseHostTimestamp != 0 ) { bFound = TRUE; } } } if(bFound == TRUE) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: DeviceID Found : Terminate Search State !\n", __FUNCTION__)); pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } } if(pP2PInfo->uNumberOfDiscoverRounds == 0) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: pP2PInfo->uNumberOfDiscoverRounds == 0: Terminate Search State!\n", __FUNCTION__)); pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } else { pP2PInfo->uNumberOfDiscoverRounds--; P2PDeviceDiscoverForSpecificChannels( pP2PInfo, pP2PInfo->DiscoverForSpecificChannels, pP2PInfo->uNumberOfDiscoverForSpecificChannels ); pP2PInfo->State = P2P_STATE_SPECIAL_PEER_SEARCH; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 50); bToFireTimer = FALSE; break; } } break; case P2P_STATE_SEARCH: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Search State\n")); // For Win 8: OID_DOT11_WFD_DISCOVER_REQUEST ------------------------------------------ if(!(pP2PInfo->DiscoverSequence & P2P_DISCOVERY_FIND_PHASE)&& P2PScanListAllFound(pP2PInfo)) { //Bypass the find phase RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Find device\n")); pP2PInfo->State = P2P_STATE_DEV_DISC_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; break; } // ------------------------------------------------------------------------------------ if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) break; probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_ProbeReq(probeReqBuf, pP2PInfo); P2PConstructScanList(pP2PInfo, req, P2P_LOWEST_RATE, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "search state"); pP2PInfo->State = P2P_STATE_LISTEN; // enter Listen State if(pP2PInfo->ConnectionContext.FindPhaseLoopTimes > 0) { if(pP2PInfo->ConnectionContext.FindPhaseLoopTimes == 0xFF || pP2PInfo->ConnectionContext.FindPhaseLoopTimes == 0xFC) // i can't set it to 0xff in d.exe {// will loop infinitely } else { pP2PInfo->ConnectionContext.FindPhaseLoopTimes--; } } } break; //====================================================================== // Provision Discovery //====================================================================== case P2P_STATE_PROVISION_DISCOVERY_REQ_SEND: p2p_DevList_Lock(&pP2PInfo->devList); { P2P_DEV_LIST_ENTRY *pDev = NULL; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Sending Provision Discovery Req\n")); pDev = p2p_DevList_Get(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.go ? pP2PInfo->ProvisionDiscoveryContext.goBssid : pP2PInfo->ProvisionDiscoveryContext.devAddr, pP2PInfo->ProvisionDiscoveryContext.go ? P2P_DEV_TYPE_GO : P2P_DEV_TYPE_DEV); if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) break; probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_PDReq(pP2PInfo, probeReqBuf, pDev->mac, pDev->p2p->dialogToken, pDev->p2p->pdConfigMethod); P2PConstructScanList(pP2PInfo, req, P2P_LOWEST_RATE, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "to send pd req"); pP2PInfo->State = P2P_STATE_PROVISION_DISCOVERY_RSP_WAIT; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter) ? P2P_PROVISION_DISCOVERY_SHORT_TIMEOUT : P2P_PROVISION_DISCOVERY_TIMEOUT); bToFireTimer = FALSE; } p2p_DevList_Unlock(&pP2PInfo->devList); break; case P2P_STATE_PROVISION_DISCOVERY_RSP_WAIT: p2p_DevList_Lock(&pP2PInfo->devList); { P2P_DEV_LIST_ENTRY *pDev = NULL; pDev = p2p_DevList_Get(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.go ? pP2PInfo->ProvisionDiscoveryContext.goBssid : pP2PInfo->ProvisionDiscoveryContext.devAddr, pP2PInfo->ProvisionDiscoveryContext.go ? P2P_DEV_TYPE_GO : P2P_DEV_TYPE_DEV); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Timeout waiting for Provision Discovery Rsp\n")); // Comment out because we use off chnl tx to do pd retry if OS support P2P natively if(0)//if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { pP2PInfo->ProvisionReqRetryCnt ++; if(pP2PInfo->ProvisionReqRetryCnt < P2P_PROVISION_DISCOVERY_RETRY_CNT) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Retry ProvisionReq!, retry = %d\n", pP2PInfo->ProvisionReqRetryCnt)); pP2PInfo->State = P2P_STATE_INITIALIZED; p2p_DevList_Unlock(&pP2PInfo->devList); if(P2PProvisionDiscovery( pP2PInfo, pP2PInfo->ProvisionDiscoveryContext.devAddr, pDev->p2p->pdConfigMethod) ) { PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter) ? P2P_PROVISION_DISCOVERY_SHORT_TIMEOUT : P2P_PROVISION_DISCOVERY_TIMEOUT); bToFireTimer = FALSE; p2p_DevList_Unlock(&pP2PInfo->devList); break; } } } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_PROVISION_DISCOVERY_RSP!, retry = 0\n")); pP2PInfo->ProvisionReqRetryCnt = 0; pP2PInfo->State = P2P_STATE_PROVISION_DISCOVERY_COMPLETE; pDev->p2p->pdStatus = P2P_SC_FAIL_TIMEOUT_WAITING_FOR_PROVISION_DISCOVERY_RSP; /* FALL THROUGH */ } p2p_DevList_Unlock(&pP2PInfo->devList); //break; case P2P_STATE_PROVISION_DISCOVERY_COMPLETE: { BOOLEAN bExtLsn = FALSE; p2p_DevList_Lock(&pP2PInfo->devList); { BOOLEAN bSucceed = FALSE; P2P_DEV_LIST_ENTRY *pDev = NULL; pDev = p2p_DevList_Get(&pP2PInfo->devList, pP2PInfo->ProvisionDiscoveryContext.go ? pP2PInfo->ProvisionDiscoveryContext.goBssid : pP2PInfo->ProvisionDiscoveryContext.devAddr, pP2PInfo->ProvisionDiscoveryContext.go ? P2P_DEV_TYPE_GO : P2P_DEV_TYPE_DEV); if(NULL == pDev) { RT_TRACE_F(COMP_P2P, DBG_SERIOUS, ("pDev = NULL\n")); RT_ASSERT(FALSE, ("pDev = NULL")); PlatformZeroMemory(&pP2PInfo->ProvisionDiscoveryContext, sizeof(pP2PInfo->ProvisionDiscoveryContext)); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; p2p_DevList_Unlock(&pP2PInfo->devList); break; } if(NULL == pDev->p2p) { RT_TRACE_F(COMP_P2P, DBG_SERIOUS, ("pDev->p2p = NULL\n")); RT_ASSERT(FALSE, ("pDev->p2p = NULL")); PlatformZeroMemory(&pP2PInfo->ProvisionDiscoveryContext, sizeof(pP2PInfo->ProvisionDiscoveryContext)); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; p2p_DevList_Unlock(&pP2PInfo->devList); break; } bSucceed = (P2P_SC_SUCCESS == pDev->p2p->pdStatus); pP2PInfo->ProvisionReqRetryCnt = 0; // // Retrieve specific P2P device info. from Win8 Specific Device Information Pool to initiate boost initial gain // 2014.03.23. // if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { u2Byte boostDelaySec = WPS_HANDSHAKE_TIMEOUT_SEC; McDynamicMachanismSet(pAdapter, MC_DM_INIT_GAIN_BOOST_END_DELAY_SEC, &boostDelaySec, sizeof(u2Byte)); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATE_PROVISION_DISCOVERY_COMPLETE:\n")); } if(bSucceed) { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Provision Discovery succeed: %u\n", pDev->p2p->pdStatus)); P2PIndicateOnProvisionDiscoveryRsp(pP2PInfo, pDev->p2p->pdConfigMethod, pDev->mac); // Set the ConfigMethod parameter to FFFF to indicate timeout P2PDeviceDiscoveryComplete(pP2PInfo, TRUE); bExtLsn = TRUE; if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { // this is now handled in the call back from OffChnlTx //p2p_IndicatePdReqSent(pDev, pP2PInfo); //p2p_IndicatePdRspReceived(pDev, pP2PInfo); }///if } else if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter) && pDev->txFrames[P2P_FID_PD_REQ]) {// Note if we use OffChnlTx to send PD, it won't get here pDev->p2p->pdStatus = P2P_SC_SUCCESS; p2p_IndicatePdReqSent(pDev, pP2PInfo); p2p_IndicateFakePdRspReceived(pDev, pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, TRUE); bExtLsn = TRUE; } else { if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { p2p_IndicateActionFrameSendComplete(pP2PInfo, P2P_EVENT_PROVISION_DISCOVERY_REQUEST_SEND_COMPLETE, RT_STATUS_FAILURE, NULL, 0 ); } RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Provision Discovery failed: %u\n", pDev->p2p->pdStatus)); if(pDev->p2p->pdStatus == P2P_SC_FAIL_COMMON_CHANNEL_NOT_ARRIVED) { pDev->p2p->pdConfigMethod = 0xFE; } else if(pDev->p2p->pdStatus == P2P_SC_FAIL_TIMEOUT_WAITING_FOR_PROVISION_DISCOVERY_RSP) { pDev->p2p->pdConfigMethod = 0xFF; } P2PSvc_OnSendPDReqFailure(pP2PInfo->pP2PSvcInfo, pDev->mac, pDev->p2p->pdStatus ); P2PIndicateOnProvisionDiscoveryRsp(pP2PInfo, pDev->p2p->pdConfigMethod, pDev->mac); // Set the ConfigMethod parameter to FFFF to indicate timeout if(pDev->p2p->pdStatus != P2P_STATUS_FAIL_COMMON_CHANNEL_NOT_ARRIVED) { P2PDeviceDiscoveryComplete(pP2PInfo, TRUE); // state is recovered } else { pP2PInfo->State = pP2PInfo->StateBeforeScan; } } PlatformZeroMemory(&pP2PInfo->ProvisionDiscoveryContext, sizeof(pP2PInfo->ProvisionDiscoveryContext)); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } p2p_DevList_Unlock(&pP2PInfo->devList); if(bExtLsn) { P2PExtendedListenStart(pP2PInfo); } } break; //====================================================================== // Group Formation //====================================================================== case P2P_STATE_GO_NEGO_REQ_SEND: p2p_DevList_Lock(&pP2PInfo->devList); { P2P_DEV_LIST_ENTRY *pDev = NULL; pDev = p2p_DevList_Get(&pP2PInfo->devList, pP2PInfo->ConnectionContext.ConnectingDevice.DeviceAddress, P2P_DEV_TYPE_DEV); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Group Formating\n")); // Pause default adapter's traffic if group formating MultichannelHandlePacketDuringScan(GetDefaultAdapter(pAdapter), TRUE); // // Retrieve specific P2P device info. from Win8 Specific Device Information Pool to initiate boost initial gain // 2014.04.03. // pP2PDeviceListEntry = P2PDeviceListFind(&pP2PInfo->DeviceList, pDev->mac); if(pP2PDeviceListEntry) { if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { BoostInitGainValue = TRUE; BoostInitGainValue = (BoostInitGainValue | ((pP2PDeviceListEntry->RecvSignalPower+110) << 8)); pP2PInfo->pAdapter->HalFunc.SetHwRegHandler(pP2PInfo->pAdapter, HW_VAR_BOOST_INIT_GAIN_OS, (pu1Byte)&BoostInitGainValue); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATE_GO_NEGO_REQ_SEND: SignalStrength(%#x)\n", pP2PDeviceListEntry->RecvSignalPower)); } } if(FALSE == P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) pP2PInfo->GOIntent = ((pP2PInfo->GOIntent & 0xFE) | !(pP2PInfo->GOIntent & 0x01)); p2p_Send_GoNegReq(pP2PInfo, pDev->mac, TRUE); pP2PInfo->State = P2P_STATE_GO_NEGO_RSP_WAIT; PlatformCancelTimer(pAdapter, &pP2PInfo->P2PMgntTimer); pP2PInfo->lastStateu8Time = PlatformGetCurrentTime(); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_GO_NEGO_FRAME_TIMEOUT); bToFireTimer = FALSE; } p2p_DevList_Unlock(&pP2PInfo->devList); break; case P2P_STATE_GO_NEGO_RSP_SEND: { pP2PInfo->State = P2P_STATE_GO_NEGO_CONFIRM_WAIT; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_GO_NEGO_FRAME_TIMEOUT); bToFireTimer = FALSE; } break; case P2P_STATE_GO_NEGO_RSP_WAIT: { if(PlatformGetCurrentTime() < (pP2PInfo->lastStateu8Time + (P2P_GO_NEGO_FRAME_TIMEOUT * 1000))) { //RT_TRACE_F(COMP_P2P, DBG_LOUD, ("CurTime=%"i64fmt"d < lastTime = %"i64fmt"d + %d, skip this timeout!\n", PlatformGetCurrentTime(), pP2PInfo->lastStateu8Time, (P2P_GO_NEGO_FRAME_TIMEOUT * 1000))); break; } RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Timeout waiting for GO Nego Rsp\n")); // // Retrieve specific P2P device info. from Win8 Specific Device Information Pool to initiate boost initial gain // 2014.04.03. // if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { BoostInitGainValue = FALSE; pAdapter->HalFunc.SetHwRegHandler(pAdapter, HW_VAR_BOOST_INIT_GAIN_OS, (pu1Byte)&BoostInitGainValue); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_GON_RSP:\n")); } pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; pP2PInfo->ConnectionContext.Status = P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_GON_RSP; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); } break; case P2P_STATE_GO_NEGO_CONFIRM_WAIT: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Timeout waiting for GO Nego Confirm\n")); pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; pP2PInfo->ConnectionContext.Status = P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_GON_CONFIRM; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); } break; case P2P_STATE_GO_NEGO_COMPLETE: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): GO Nego Complete: %u\n", pP2PInfo->ConnectionContext.Status)); // // Retrieve specific P2P device info. from Win8 Specific Device Information Pool to initiate boost initial gain // 2014.04.03. // if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { u2Byte boostDelaySec = WPS_HANDSHAKE_TIMEOUT_SEC; McDynamicMachanismSet(pAdapter, MC_DM_INIT_GAIN_BOOST_END_DELAY_SEC, &boostDelaySec, sizeof(u2Byte)); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATE_GO_NEGO_COMPLETE:\n")); } if(P2P_DOING_DEVICE_DISCOVERY(pP2PInfo)) { P2PScanListCeaseScan(pP2PInfo); P2PDeviceDiscoveryComplete(pP2PInfo, FALSE); } pP2PInfo->PreviousGONegoResult = (P2P_STATUS_CODE)pP2PInfo->ConnectionContext.Status; if(pP2PInfo->ConnectionContext.Status == P2P_STATUS_SUCCESS) { // // Indicate GO formated info to ask UI to start provisioning // if(pP2PInfo->ConnectionContext.bGoingToBeGO) { // Only copy the infomration in GO from our P2P info because these info shall be from ours but not the target (client). pP2PInfo->ConnectionContext.ConnectingDevice.OperatingChannel = pP2PInfo->OperatingChannel; CopySsid(pP2PInfo->ConnectionContext.ConnectingDevice.SsidBuf, pP2PInfo->ConnectionContext.ConnectingDevice.SsidLen, pP2PInfo->SSIDBuf, pP2PInfo->SSIDLen); } //P2PDumpScanList(pP2PInfo->ScanList, pP2PInfo->ScanListSize); P2PDumpGroupFormationResult(pP2PInfo); P2PIndicateGOFormatedInfo(pP2PInfo, pP2PInfo->ConnectionContext.Status, pP2PInfo->ConnectionContext.bGoingToBeGO, &pP2PInfo->ConnectionContext.ConnectingDevice); if(pP2PInfo->ConnectionContext.bGoingToBeGO) {// Indicate to the upper layer to start a P2P Role Port of type GO P2P_PROFILE P2PProfile; P2PProfile.OpChannel = pP2PInfo->OperatingChannel; // // GO SSID is determined when GONegoReq or GONegoRsp is received // and it is stored in pP2PInfo->SSIDBuf // CopySsid(P2PProfile.SsidBuf, P2PProfile.SsidBufLen, pP2PInfo->SSIDBuf, pP2PInfo->SSIDLen); // // We use this to modify the SSID of the SoftAP // P2PIndicateStartApRequest(pP2PInfo, &P2PProfile); } pP2PInfo->State = P2P_STATE_INITIALIZED; } else { // // GO Nego failed, indicate to UI // For the failure case, indicate earlier when we determine the negotiation is failed. // //P2PIndicateGOFormatedInfo(pP2PInfo, // pP2PInfo->ConnectionContext.Status, // pP2PInfo->ConnectionContext.bGoingToBeGO, // &pP2PInfo->ConnectionContext.ConnectingDevice); PlatformZeroMemory(&pP2PInfo->ConnectionContext, sizeof(pP2PInfo->ConnectionContext)); pP2PInfo->State = P2P_STATE_INITIALIZED; } PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; //====================================================================== // WPS //====================================================================== case P2P_STATE_PRE_PROVISIONING: { u4Byte ConfigurationTimeout; // in ms, note that the configuration time out in the P2P IE is defined as units of 10ms RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_PRE_PROVISIONING\n")); // Reset WPS related flags pP2PInfo->ConnectionContext.bDoingProvisioning = FALSE; // // Clause 3.1.4.3: // Group Formation bit in the P2P Group Cap shall be set to 1 until Provisioning succeeds. // pP2PInfo->GroupCapability |= gcGroupFormation; // set the bit if(pP2PInfo->ConnectionContext.bGoingToBeGO && !P2P_ACTING_AS_GO(pP2PInfo)) // for the case that we invite a Dev to join our group, we shall not change SSID or restart AP {// start AP mode P2PSetRole(pP2PInfo, P2P_GO); // // GO does not check if provisioning succeed. // pP2PInfo->ConnectionContext.bDoingProvisioning = TRUE; pP2PInfo->ConnectionContext.ProvisioningResult = P2P_PROVISIONING_RESULT_SUCCEED; } else {//P2P Client, will connect to the GO later pP2PInfo->ConnectionContext.bDoingProvisioning = TRUE; pP2PInfo->ConnectionContext.ProvisioningResult = P2P_PROVISIONING_RESULT_UNKNOWN; } // // Clause 3.1.3.4: // To allow for P2P Device configuration, P2P Devices may delay starting the Provisioning phase // until the expiration of the max of the P2P GO's GO Config Time and the Client's Client Config Time. // if(pP2PInfo->ConnectionContext.bGoingToBeGO) {// I'm going to be the GO => just enter provisioning state without waiting for configuration timeout ConfigurationTimeout = 0; //(10 * MAX(pP2PInfo->GOConfigurationTimeout, pP2PInfo->ConnectionContext.ConnectingDevice.ClientConfigurationTimeout)); } else {// I'm going to be the Client ConfigurationTimeout = (10 * MAX(pP2PInfo->ClientConfigurationTimeout, pP2PInfo->ConnectionContext.ConnectingDevice.GOConfigurationTimeout)); } if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { // For Win 8: Return back to the initialization state ----------------------------------------- PlatformZeroMemory(&pP2PInfo->ConnectionContext, sizeof(pP2PInfo->ConnectionContext)); pP2PInfo->Role = P2P_DEVICE; pP2PInfo->State = P2P_STATE_INITIALIZED; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; // ---------------------------------------------------------------------------------- } else { // // Wait for configuration before starting provisioning // pP2PInfo->State = P2P_STATE_PROVISIONING; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, ConfigurationTimeout); // wait for configuration bToFireTimer = FALSE; } } break; case P2P_STATE_PROVISIONING: { //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_PROVISIONING\n")); //if(pP2PInfo->ConnectionContext.bDoingProvisioning) {// doing provisioning // // During the time waiting for provisioning complete, we keep in P2P_STATE_PROVISIONING. // Once ProvisioningResult is set, we infer that provisioning completed. // if(pP2PInfo->ConnectionContext.ProvisioningResult == P2P_PROVISIONING_RESULT_SUCCEED) {// Provisioning succeed P2PSetOperatingState(pP2PInfo); if(pP2PInfo->ConnectionContext.bGoingToBeGO) { } else {// set client role P2PSetRole(pP2PInfo, P2P_CLIENT); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): provisioning succeed\n")); } PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } else if(pP2PInfo->ConnectionContext.ProvisioningResult == P2P_PROVISIONING_RESULT_FAILED) {// Provisioning failed => indicate Group Formation failed // // Clause 3.1.4.3: End the P2P Group session as described in Clause 3.2.9 // SendDeauthentication(pP2PInfo->pAdapter, BroadcastAddress, deauth_lv_ss); pP2PInfo->State = P2P_STATE_INITIALIZED; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEFAULT_MGNT_PERIOD); bToFireTimer = FALSE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): provisioning failed\n")); } else {// Provisioning in progress => keep waiting //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): wait for provisioning\n")); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEFAULT_MGNT_PERIOD); bToFireTimer = FALSE; break; } if(pP2PInfo->ConnectionContext.ProvisioningResult != P2P_PROVISIONING_RESULT_UNKNOWN) {// Provisioning has been done, either failed or succeed // // Clause 3.1.4.3: // Group Formation bit in the P2P Group Cap shall be set to 1 until Provisioning succeeds. // pP2PInfo->GroupCapability &= ~gcGroupFormation; // clear the bit RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): provisioning done\n")); // // Reset ConnectionContext since this connection session is completed // PlatformZeroMemory(&pP2PInfo->ConnectionContext, sizeof(pP2PInfo->ConnectionContext)); } } } break; //====================================================================== // Group Operation //====================================================================== case P2P_STATE_OPERATING: { if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { // Do nothing: Just Waiting for Win8 OID } else { //RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_OPERATING\n")); if(P2P_ACTING_AS_GO(pP2PInfo)) { if(P2PClientInfoGetCount(pP2PInfo) == 0 && !pP2PInfo->bGOStartedAutonomously) // not to check this if GO started autonomously {// no client pP2PInfo->P2PGONoClientSlotCount++; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): no client slot count: %d\n", pP2PInfo->P2PGONoClientSlotCount)); } else { pP2PInfo->ExtListenTimingPeriodSlotCount = 0; } if(pP2PInfo->P2PGONoClientSlotCount == P2P_NO_CLIENT_PERIOD_SC) { P2PDisconnect(pP2PInfo); // to stop the SoftAP and back to init state pP2PInfo->P2PGONoClientSlotCount = 0; // Comment out because these are handled in P2PDisconnect. //pP2PInfo->State = P2P_STATE_INITIALIZED; //pP2PInfo->Role = P2P_DEVICE; bToFireTimer = FALSE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Stop GO and back to P2P_STATE_INITIALIZED\n")); } } else if(P2P_ACTING_AS_CLIENT(pP2PInfo)) {// operating as a client, check if we are still connected if(!P2PDefaultPortConnected(pP2PInfo) && !P2PProvisioning(pP2PInfo)) { pP2PInfo->P2PClientDisconnectedSlotCount++; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P Client disconnected slot count: %d\n", pP2PInfo->P2PClientDisconnectedSlotCount)); } else {// def port connected or doing provisioning pP2PInfo->P2PClientDisconnectedSlotCount = 0; } if(pP2PInfo->P2PClientDisconnectedSlotCount == P2P_CLIENT_DISCONNECTED_PERIOD_SC) { P2PDisconnect(pP2PInfo); // will back to init state pP2PInfo->P2PClientDisconnectedSlotCount = 0; pP2PInfo->State = P2P_STATE_INITIALIZED; P2PSetRole(pP2PInfo, P2P_DEVICE); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): back to P2P_STATE_INITIALIZED because we are acting as Client but default port is disconnected\n")); } } } PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEFAULT_MGNT_PERIOD); bToFireTimer = FALSE; } break; //====================================================================== // Invitation //====================================================================== case P2P_STATE_INVITATION_REQ_SEND: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_INVITATION_REQ_SEND\n")); if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) break; probeReqBuf = CustomScan_GetProbeReqBuf(req); p2p_Construct_InvitationReq(pP2PInfo, probeReqBuf, pP2PInfo->InvitationContext.InvitedDevice.DeviceAddress, pP2PInfo->InvitationContext.DialogToken); P2PConstructScanList(pP2PInfo, req, P2P_LOWEST_RATE, probeReqBuf); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "to send inv req"); pP2PInfo->State = P2P_STATE_INVITATION_RSP_WAIT; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_INVITATION_FRAME_TIMEOUT); bToFireTimer = FALSE; } break; case P2P_STATE_INVITATION_RSP_WAIT: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Timeout waiting for InvitationRsp\n")); pP2PInfo->State = P2P_STATE_INVITATION_COMPLETE; pP2PInfo->InvitationContext.Status = P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_INVITATION_RSP; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter) && !pP2PInfo->pAdapter->bInHctTest) { if(P2PIndicateFakeInvitRsp(pP2PInfo)) { pP2PInfo->InvitationContext.Status = P2P_STATUS_SUCCESS; } } /*FALL THROUGH*/ } //break; case P2P_STATE_INVITATION_COMPLETE: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_INVITATION_COMPLETE, status: %u, persistent: %u, ch: %u\n", pP2PInfo->InvitationContext.Status, pP2PInfo->InvitationContext.bPersistentInvitation, pP2PInfo->InvitationContext.OpChannel)); // // Resume boost initial gain for P2P invitation response timeout or process completion. // 2013.10.15. // if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { u2Byte boostDelaySec = ASSOC_HANDSHAKE_DHCP_DELAY_SEC; McDynamicMachanismSet(pAdapter, MC_DM_INIT_GAIN_BOOST_END_DELAY_SEC, &boostDelaySec, sizeof(u2Byte)); RT_TRACE(COMP_P2P, DBG_LOUD, ("[BOOST_INIT_GAIN_OS] P2P_STATE_INVITATION_COMPLETE:\n")); } // // We use P2PDeviceDiscovery() to arrive common chnll before sendding InvitationReq, // In P2PDeviceDiscovery(), beacon is stopped, so we have to resume beaconning here. // // If P2P_STATUS_FAIL_COMMON_CHANNEL_NOT_ARRIVED, // P2PDeviceDiscoveryComplete() is called in P2P_STATE_DEV_DISC_COMPLETE case, // so we don' t have to call it again // if(pP2PInfo->InvitationContext.Status != P2P_STATUS_FAIL_COMMON_CHANNEL_NOT_ARRIVED) { P2PDeviceDiscoveryComplete(pP2PInfo, TRUE); } else { pP2PInfo->State = pP2PInfo->StateBeforeScan; } P2PInvitePeerComplete(pP2PInfo); P2PIndicateOnInvitationRsp(pP2PInfo, pP2PInfo->InvitationContext.Status, pP2PInfo->InvitationContext.bPersistentInvitation, pP2PInfo->InvitationContext.OpChannel, pP2PInfo->InvitationContext.InvitorRole, pP2PInfo->InvitationContext.SsidLen, pP2PInfo->InvitationContext.SsidBuf); // Indicating InvitationRsp may trigger a connect request which may further triger a reset request, // and reset request resets all timers including the P2P mgnt timer. // Indicate current state immediately so that upper layers will not show "inviting" for a long time. //P2PIndicateCurrentState(pP2PInfo, pP2PInfo->State); if(!pP2PInfo->InvitationContext.bWaitingBackwardInvite) { PlatformZeroMemory(&(pP2PInfo->InvitationContext), sizeof(P2P_INVITATION_CONTEXT)); } PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; //====================================================================== // Device Discoverability //====================================================================== case P2P_STATE_DEVICE_DISCOVERABILITY_WAIT_BEACON: {// timeout waiting for beacon from the GO pP2PInfo->DeviceDiscoverabilityContext.Status = P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_GO_BEACON; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_DEVICE_DISCOVERABILITY_WAIT_BEACON: Timeout waiting for GO Beacon\n")); pP2PInfo->State = P2P_STATE_DEVICE_DISCOVERABILITY_COMPLETE; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; case P2P_STATE_DEVICE_DISCOVERABILITY_REQ_SEND: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_INVITATION_REQ_SEND\n")); p2p_Send_DevDiscReq(pP2PInfo, pP2PInfo->DeviceDiscoverabilityContext.GoBssid, pP2PInfo->DeviceDiscoverabilityContext.ClientDeviceAddress, pP2PInfo->DeviceDiscoverabilityContext.DialogToken); pP2PInfo->State = P2P_STATE_DEVICE_DISCOVERABILITY_RSP_WAIT; PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEVICE_DISCOVERABILITY_FRAME_TIMEOUT); bToFireTimer = FALSE; } break; case P2P_STATE_DEVICE_DISCOVERABILITY_RSP_WAIT: {// timeout waithing for DeviceDiscoverabilityRsp pP2PInfo->DeviceDiscoverabilityContext.Status = P2P_STATUS_FAIL_TIMEOUT_WAITING_FOR_DEVICE_DISCOVERABILITY_RSP; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_DEVICE_DISCOVERABILITY_RSP_WAIT: Timeout waiting for DeviceDiscoverabilityRsp\n")); } /*FALL THROUGH*/ case P2P_STATE_DEVICE_DISCOVERABILITY_COMPLETE: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_DEVICE_DISCOVERABILITY_COMPLETE: Status(%u)\n", pP2PInfo->DeviceDiscoverabilityContext.Status)); pP2PInfo->DeviceDiscoverabilityContext.bWaitingBeaconFromGO = FALSE; if(!pP2PInfo->DeviceDiscoverabilityContext.bGoConnect) { pP2PInfo->State = P2P_STATE_INITIALIZED; P2PSetChannel(pP2PInfo, pP2PInfo->DeviceDiscoverabilityContext.OriginalChannel); } else { pP2PInfo->State = P2P_STATE_GO_NEGO_REQ_SEND; } PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; //====================================================================== // Service Discovery //====================================================================== case P2P_STATE_SERVICE_DISCOVERY_REQ_SEND: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): P2P_STATE_SERVICE_DISCOVERY_REQ_SEND\n")); /* we will never reach here, see P2PCommonChannelArrived */ } break; case P2P_STATE_SERVICE_DISCOVERY_COMEBACK_RSP_WAIT: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Timeout waiting for ComebackRsp\n")); pP2PInfo->SDContext.Status = P2P_SD_STATUS_COMEBACK_RSP_TIMEOUT; pP2PInfo->State = P2P_STATE_SERVICE_DISCOVERY_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; case P2P_STATE_SERVICE_DISCOVERY_RSP_WAIT: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): Timeout waiting for SDRsp\n")); pP2PInfo->SDContext.Status = P2P_SD_STATUS_SERVICE_RSP_TIMEOUT; pP2PInfo->State = P2P_STATE_SERVICE_DISCOVERY_COMPLETE; PlatformSetTimer(pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; case P2P_STATE_SERVICE_DISCOVERY_COMPLETE: { RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PMgntTimerCallback(): SD Complete: Status (%u)\n", pP2PInfo->SDContext.Status)); if(pP2PInfo->SDContext.Status != P2P_SD_STATUS_COMMON_CHANNEL_NOT_ARRIVED) { P2PDeviceDiscoveryComplete(pP2PInfo, TRUE); } else { pP2PInfo->State = pP2PInfo->StateBeforeScan; } if(!(pP2PInfo->SDContext.Status == P2P_SD_STATUS_SUCCESS)) // handled when status is determined to be success { // Notify the SDRsp P2PIndicateOnSDRsp(pP2PInfo, &pP2PInfo->SDContext); } // Clear SDContext PlatformZeroMemory(&pP2PInfo->SDContext, sizeof(P2P_SD_CONTEXT)); PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, 0); bToFireTimer = FALSE; } break; default: break; } if(pP2PInfo->Role == P2P_NONE) { bToFireTimer = FALSE; } if(bToFireTimer) { PlatformSetTimer( pAdapter, &pP2PInfo->P2PMgntTimer, P2P_DEFAULT_MGNT_PERIOD); } exit_P2PMgntTimerCallback: return; } VOID P2PMlmeAssociateRequest( PADAPTER Adapter, pu1Byte asocStaAddr, u4Byte asocTmot, u2Byte asCap, u2Byte asListenInterval, BOOLEAN Reassociate ) { PP2P_INFO pP2PInfo = GET_P2P_INFO(Adapter); PRT_WLAN_BSS pBssDesc ; if(!P2P_ENABLED(GET_P2P_INFO(Adapter))) { return; } pBssDesc = BssDescDupByBssid(pP2PInfo->pAdapter, asocStaAddr); if(pBssDesc) { if(!(pBssDesc->P2PManagedInfo & maP2PCrossConnectionPermitted) && (pP2PInfo->GroupCapability & gcCrossConnection)) {// we support cross conn but the connecting ap does not allow that RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PMlmeAssociateRequest(): Cross connection is not allowed by the AP => disable cross connection\n", asocStaAddr); pP2PInfo->GroupCapability &= ~gcCrossConnection; } } return; } // // Description: // Handle association response packet with status "suceess" for P2P function. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] pRfd - // The packet container including the information of packet. // [in] posMpdu - // The location address of full 802.11 frame. // // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // Remark: // This function updates the listen channel and operating channel if the client is assocating to // the legacy AP. // RT_STATUS P2P_OnAssocOK( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); pu1Byte DeviceAddress = NULL; pu1Byte InterfaceAddress = Frame_pSaddr(*posMpdu); PP2P_DEVICE_DISCRIPTOR pP2PDeviceDesc = NULL; PADAPTER pLoopAdapter = NULL; PP2P_INFO pLoopP2PInfo = NULL; P2P_MESSAGE msg; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("connected with Legacy AP\n")); FunctionIn(COMP_P2P); PlatformZeroMemory(&msg, sizeof(P2P_MESSAGE)); do { BOOLEAN bGo = FALSE; for(pLoopAdapter = GetDefaultAdapter(pAdapter), pLoopP2PInfo = (pLoopAdapter ? GET_P2P_INFO(pLoopAdapter) : NULL); pLoopAdapter && pLoopP2PInfo; pLoopAdapter = GetNextExtAdapter(pLoopAdapter), pLoopP2PInfo = (pLoopAdapter ? GET_P2P_INFO(pLoopAdapter) : NULL)) { if(!P2P_ENABLED(pLoopP2PInfo)) continue; if(P2P_CLIENT != pLoopP2PInfo->Role && P2P_GO != pLoopP2PInfo->Role) { pLoopP2PInfo->OperatingChannel = pMgntInfo->dot11CurrentChannelNumber; if(P2PIsSocialChannel(pLoopP2PInfo->OperatingChannel)) pLoopP2PInfo->ListenChannel = pLoopP2PInfo->OperatingChannel; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P op chnl changed to %u, listenChnl = %d for adapter (%p)\n", pLoopP2PInfo->OperatingChannel, pLoopP2PInfo->ListenChannel, pLoopAdapter)); } } // Prefast warning C28182: Dereferencing NULL pointer. '((pAdapter))->pPortCommonInfo->pDefaultAdapter' contains the same NULL value as 'pLoopAdapter' did. if(((pAdapter))->pPortCommonInfo->pDefaultAdapter != NULL && !P2P_ENABLED(GET_P2P_INFO(pAdapter))) { rtStatus = RT_STATUS_SUCCESS; break; } if(RT_STATUS_SUCCESS == (rtStatus = p2p_parse_Ies(posMpdu, DBG_LOUD, &msg))) if(!p2p_validate_AssocRsp(&msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // // Clause 4.2.5, At least 1 P2P IE is always included in the AssocRsp frame. // // osP2PIE = PacketGetElement(asocpdu, EID_Vendor, OUI_SUB_WIFI_DIRECT, OUI_SUB_DONT_CARE); bGo = (NULL != FrameBuf_Head(&msg.p2pAttributes)); // Update scan list for query so that upper layers can query the most up to date scan list to determine // whether the connecting AP is a GO. P2P_UpdateScanList(pAdapter); // // Check if the connecting AP is actually a GO // Note that the P2P IE may contain no P2P attributes, so we don't check osP2PIE.Length > 0 // if(bGo) {// the AssocRsp is from a P2P Device RT_TRACE_F(COMP_P2P, DBG_LOUD, ("connected with GO: Role is %d, State is %d\n", pP2PInfo->Role, pP2PInfo->State)); if(pP2PInfo->Role == P2P_DEVICE && pP2PInfo->State != P2P_STATE_PROVISIONING) { P2PSetRole(pP2PInfo, P2P_CLIENT); P2PSetOperatingState(pP2PInfo); PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); P2PIndicateCurrentState(pP2PInfo, pP2PInfo->State); // update op-state immediately } } else {// connect to a legacy AP if(P2PIsSocialChannel(pMgntInfo->dot11CurrentChannelNumber)) { pP2PInfo->OperatingChannel = MgntActQuery_802_11_CHANNEL_NUMBER(pP2PInfo->pAdapter); pP2PInfo->ListenChannel = MgntActQuery_802_11_CHANNEL_NUMBER(pP2PInfo->pAdapter); // Also adjust GO intent to 15 so that we won't become a P2P Client after negotiation. { pP2PInfo->GOIntent = ((15 << 1) | (pP2PInfo->GOIntent & 0x01)); } // // Readiness event: for 7.1.5 // if(pP2PInfo->Role == P2P_CLIENT) {// we are a P2P Client and now connecting to a legacy AP => back to device role P2PSetRole(pP2PInfo, P2P_DEVICE); pP2PInfo->State = P2P_STATE_INITIALIZED; PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P listen chnl changed to %u\n", pMgntInfo->dot11CurrentChannelNumber)); } } PlatformSetTimer(pAdapter, &(pP2PInfo->P2PMgntTimer), 0); }while(FALSE); p2p_parse_FreeMessage(&msg); return rtStatus; } // // Description: // Set P2P Power Save mode for GO. // Arguments: // [in] pP2PInfo - // The P2P context. // [in] pP2pPs - // The address of P2P power save setting. // [in] NoAIndex - // The NoA index, only applied to Client. // [in] psReason - // It't the reason why or who updates the power save configuration. // Return: // If success, return RT_STATUS_SUCCESS; Otherwise, return an error code. // Note: // The current setting is only applied to the PCI interface since we must get the TSF timer // directly from the NIC's register. // By Bruce, 2011-02-10. // u4Byte P2PSetPowerSaveMode( IN PP2P_INFO pP2PInfo, IN PP2P_POWERSAVE_SET pP2pPs, IN u1Byte NoAIndex, IN P2P_PS_UPDATE_REASON psReason ) { PADAPTER pAdapter = NULL; if(!P2P_ENABLED(pP2PInfo)) return RT_STATUS_FAILURE; if(!pP2pPs || !pP2PInfo) return RT_STATUS_FAILURE; pAdapter = pP2PInfo->pAdapter; // Clear the PS level first. RT_CLEAR_PS_LEVEL(pAdapter, RT_RF_LPS_P2P_PS); // Invalid role if((pP2PInfo->Role != P2P_GO) && (pP2PInfo->Role != P2P_CLIENT)) return RT_STATUS_FAILURE; P2PSetPsState(pP2PInfo, P2P_PS_CANCEL_ALL_PS, P2P_PS_AWAKE, 0); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PSetPowerSaveMode(): Reason = %d\n", psReason)); PlatformMoveMemory(&pP2PInfo->P2pPsConfgSet, pP2pPs, sizeof(P2P_POWERSAVE_SET)); if(psReason == P2P_PS_UPDATE_BY_USER && pP2PInfo->Role == P2P_CLIENT) { // This is a presence request in p2p client. return P2PPresenceReq(pP2PInfo, &pP2PInfo->P2pPsConfgSet); } if(pP2PInfo->Role == P2P_GO) pP2PInfo->NoAIEIndex = ((u2Byte)(pP2PInfo->NoAIEIndex + 1) > 0xFF) ? 0 : (pP2PInfo->NoAIEIndex + 1); else pP2PInfo->NoAIEIndex = NoAIndex; pP2PInfo->bUpdatePsParameter = TRUE; // For non-PCI interface, we always schedule workitem to update P2P PS mode. if(!PlatformIsWorkItemScheduled(&(pP2PInfo->P2PPSWorkItem))) PlatformScheduleWorkItem(&(pP2PInfo->P2PPSWorkItem)); return RT_STATUS_SUCCESS; P2PUpdatePowerSavePara(pP2PInfo); if(pP2PInfo->psExeType == RT_P2P_PS_EXE_BY_SW_HW_TIMER) { // Driver Timer P2PPsTimeout(pAdapter); } else if(pP2PInfo->psExeType == RT_P2P_PS_EXE_BY_HW && pAdapter->MgntInfo.bWiFiConfg) { // HW caculate P2PSetPsState(pP2PInfo, P2P_PS_CANCEL_ALL_PS, P2P_PS_AWAKE, 0); } else { // Not support. return RT_STATUS_FAILURE; } return RT_STATUS_SUCCESS; } // // Description: // Update the P2P power save setting from the configuration. // Arguments: // [in] pP2PInfo - // The P2P context. // Return: // If success, return RT_STATUS_SUCCESS; Otherwise, return an error code. // Assumption: // Before calling this function, make sure the bus interface so that we can directly access // the HW register, such as passive level. // By Bruce, 2011-02-11. // u4Byte P2PUpdatePowerSavePara( IN PP2P_INFO pP2PInfo ) { PADAPTER pAdapter = pP2PInfo->pAdapter; u8Byte curTsf = 0, u8StartTime = 0, nextAdvancedTsf = 0, usBeaconInterval = 0, usCtWindow = 0; u1Byte i = 0; if(!P2P_ENABLED(pP2PInfo)) return RT_STATUS_FAILURE; if(!pP2PInfo->bUpdatePsParameter) return RT_STATUS_FAILURE; usBeaconInterval = pP2PInfo->pAdapter->MgntInfo.dot11BeaconPeriod * sTU; pP2PInfo->bOppPS = pP2PInfo->P2pPsConfgSet.bOppPs; usCtWindow = pP2PInfo->P2pPsConfgSet.CTWindow * sTU; // Check if the CTWindow is not valid if(usCtWindow < (P2P_PS_MIN_CTWIN * sTU) || usCtWindow > usBeaconInterval) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("CTWindow is not valid (%d)\n", pP2PInfo->P2pPsConfgSet.CTWindow)); pP2PInfo->bOppPS = FALSE; pP2PInfo->CTWindow = 0; } else { pP2PInfo->CTWindow = pP2PInfo->P2pPsConfgSet.CTWindow; } // We don't accept both NoA with Count = 1 if(pP2PInfo->P2pPsConfgSet.NoASet[0].bNoAEn && pP2PInfo->P2pPsConfgSet.NoASet[1].bNoAEn && pP2PInfo->P2pPsConfgSet.NoASet[0].NoACnt == 1 && pP2PInfo->P2pPsConfgSet.NoASet[1].NoACnt == 1) { RT_TRACE(COMP_P2P, DBG_WARNING, ("Don't accept bith NoA with count = 1, mark NoA1 as disable\n")); pP2PInfo->P2pPsConfgSet.NoASet[1].bNoAEn = FALSE; } pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_TSF_TIMER, (pu1Byte)(&curTsf)); // Update NoA for(i = 0; i < P2P_MAX_NUM_NOA_DESC; i ++) { pP2PInfo->NoADescriptors[i].bValid = pP2PInfo->P2pPsConfgSet.NoASet[i].bNoAEn; // If the interval is not long enough to get into awake state, mark it as no NoA. if((pP2PInfo->P2pPsConfgSet.NoASet[i].NoADur < 4 * P2P_PS_TIMEOUT_TOLERANCE) || ((pP2PInfo->P2pPsConfgSet.NoASet[i].NoADur + 10000) > pP2PInfo->P2pPsConfgSet.NoASet[i].NoAInt && pP2PInfo->P2pPsConfgSet.NoASet[i].NoACnt != 1 && pP2PInfo->NoADescriptors[i].bValid)) { pP2PInfo->NoADescriptors[i].bValid = FALSE; RT_TRACE(COMP_P2P, DBG_WARNING, (" Setting Values are invalid: Duration (0x%08X), Interval (0x%08X) and count = %d\n", pP2PInfo->P2pPsConfgSet.NoASet[i].NoADur, pP2PInfo->P2pPsConfgSet.NoASet[i].NoAInt, pP2PInfo->P2pPsConfgSet.NoASet[i].NoACnt)); } pP2PInfo->NoADescriptors[i].CountOrType = (pP2PInfo->NoADescriptors[i].bValid) ? pP2PInfo->P2pPsConfgSet.NoASet[i].NoACnt : 0; pP2PInfo->NoADescriptors[i].Duration = (pP2PInfo->NoADescriptors[i].bValid) ? pP2PInfo->P2pPsConfgSet.NoASet[i].NoADur : 0; pP2PInfo->NoADescriptors[i].Interval = (pP2PInfo->NoADescriptors[i].bValid) ? pP2PInfo->P2pPsConfgSet.NoASet[i].NoAInt : 0; if(pP2PInfo->NoADescriptors[i].bValid) { // Modify the start time to be the mod of beacon interval. // If the user didn't specify the shift time, using the defualt value 500 ms. u8StartTime = (pP2PInfo->P2pPsConfgSet.NoASet[i].bUseStartTime) ? ((curTsf & UINT64_C(0xFFFFFFFF00000000)) | pP2PInfo->P2pPsConfgSet.NoASet[i].u4StartTime) : PlatformDivision64(curTsf, usBeaconInterval) * usBeaconInterval + 5 * usBeaconInterval; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("bUseStartTime = %d, u8StartTime = 0x%08X %08X, div = 0x%08X\n", pP2PInfo->P2pPsConfgSet.NoASet[i].bUseStartTime, (u4Byte)(u8StartTime >> 32), (u4Byte)u8StartTime, (u4Byte)PlatformDivision64(curTsf, usBeaconInterval))); // Store the exact TSF timer for timeout reference. pP2PInfo->NoADescriptors[i].u8StartTime = u8StartTime; // Extract the low 4 bytes. pP2PInfo->NoADescriptors[i].StartTime = (u4Byte)(u8StartTime & 0xFFFFFFFF); nextAdvancedTsf = (pP2PInfo->NoADescriptors[i].u8StartTime & UINT64_C(0xFFFFFFFF00000000)) + UINT64_C(0x0000000100000000); if(pP2PInfo->NoADescriptors[i].CountOrType == 0xFF) { // count is 255 pP2PInfo->NoADescriptors[i].u8EndTime = UINT64_C(0xFFFFFFFFFFFFFFFF); } else if(pP2PInfo->NoADescriptors[i].CountOrType == 1) { pP2PInfo->NoADescriptors[i].u8EndTime = (u8Byte)(pP2PInfo->NoADescriptors[i].u8StartTime + pP2PInfo->NoADescriptors[i].Duration); } else { pP2PInfo->NoADescriptors[i].u8EndTime = (u8Byte)(pP2PInfo->NoADescriptors[i].u8StartTime + (pP2PInfo->NoADescriptors[i].CountOrType * pP2PInfo->NoADescriptors[i].Interval) - (pP2PInfo->NoADescriptors[i].Interval - pP2PInfo->NoADescriptors[i].Duration)); } if(pP2PInfo->NoADescriptors[i].u8EndTime <= curTsf + 10 * sTU) // The end time is too closed to the current TSF, skip this NoA. { pP2PInfo->NoADescriptors[i].bValid = FALSE; } } // Reset all variables if this NoA is invalid. if(!pP2PInfo->NoADescriptors[i].bValid) { PlatformZeroMemory(&pP2PInfo->NoADescriptors[i], sizeof(P2P_NOA_DESCRIPTOR)); } } // Swap the two descriptors to let the 2nd NoA descriptor end always first. if(pP2PInfo->NoADescriptors[1].u8EndTime > pP2PInfo->NoADescriptors[0].u8EndTime) { P2P_NOA_DESCRIPTOR tmpP2pNoADesc; PlatformMoveMemory(&tmpP2pNoADesc, &pP2PInfo->NoADescriptors[1], sizeof(P2P_NOA_DESCRIPTOR)); PlatformMoveMemory(&pP2PInfo->NoADescriptors[1], &pP2PInfo->NoADescriptors[0], sizeof(P2P_NOA_DESCRIPTOR)); PlatformMoveMemory(&pP2PInfo->NoADescriptors[0], &tmpP2pNoADesc, sizeof(P2P_NOA_DESCRIPTOR)); } RT_TRACE(COMP_P2P, DBG_LOUD, ("bOppPs = %d, CTWin = %X\n", pP2PInfo->bOppPS, pP2PInfo->CTWindow)); for(i = 0; i < 2; i ++) { RT_TRACE(COMP_P2P, DBG_LOUD, ("-----NoA[%d]-----\nbValid = %d, Count = %X, Duration = 0x%08X (Dec = %d), Interval = 0x%08X (Dec = %d)\nu8StartTime = 0x%08X %08X (Low Dec = %d), \nu8EndTime = 0x%08X %08X (Low Dec = %d)\n------------\n", i, pP2PInfo->NoADescriptors[i].bValid, pP2PInfo->NoADescriptors[i].CountOrType, pP2PInfo->NoADescriptors[i].Duration, pP2PInfo->NoADescriptors[i].Duration, pP2PInfo->NoADescriptors[i].Interval, pP2PInfo->NoADescriptors[i].Interval, (u4Byte)(pP2PInfo->NoADescriptors[i].u8StartTime >> 32), (u4Byte)(pP2PInfo->NoADescriptors[i].u8StartTime), (u4Byte)(pP2PInfo->NoADescriptors[i].u8StartTime), (u4Byte)(pP2PInfo->NoADescriptors[i].u8EndTime >> 32), (u4Byte)(pP2PInfo->NoADescriptors[i].u8EndTime), (u4Byte)(pP2PInfo->NoADescriptors[i].u8EndTime))); } // Reset the timeout to pass this information to timeout function. pP2PInfo->NextTimeout = 0; pP2PInfo->bUpdatePsParameter = FALSE; if(pP2PInfo->bOppPS || pP2PInfo->NoADescriptors[0].bValid || pP2PInfo->NoADescriptors[1].bValid) { RT_SET_PS_LEVEL(pAdapter, RT_RF_LPS_P2P_PS); } return RT_STATUS_SUCCESS; } #define P2P_PS_TIME_STATE_NO_PS 0 // No State #define P2P_PS_TIME_STATE_IN_CTWIN BIT0 // In CTWin, we shall keep awake. #define P2P_PS_TIME_STATE_OUT_CTWIN BIT1 // Out of CTWin, we shall enter PS. #define P2P_PS_TIME_STATE_OUT_CTWIN_CLIENT_AWAKE BIT2 // Out of CTWin, but we must keep awake for the reason of GO with at least one acitve client or our client in active mode. #define P2P_PS_TIME_STATE_IN_1TIME_NOA0 BIT3 // In one time NoA in desc 0 #define P2P_PS_TIME_STATE_IN_1TIME_NOA1 BIT4 // In one time NoA in desc 1 #define P2P_PS_TIME_STATE_IN_NOA0 BIT5 // In periodic NoA in desc 0 of PS. (sleep) #define P2P_PS_TIME_STATE_IN_NOA1 BIT6 // In periodic NoA in desc 1 of PS. (sleep) #define P2P_PS_TIME_STATE_OUT_NOA0 BIT7 // Out of periodic NoA in desc 0 of PS. (awake) #define P2P_PS_TIME_STATE_OUT_NOA1 BIT8 // Out of periodic NoA in desc 1 of PS. (awake) #define P2P_PS_TIME_STATE_IN_TBTT BIT9 // In TBTT time, we shall keep active to send the Beacon // // Description: // This P2P PowerSave workitem is only scheudled for usb interface because the ps procedure // needs to read/write the register. When the P2P ps mode is periodically occurs, it needs the // while loop and to sleep for simulating the timeout and triggering the event to perform on/off. // When the P2P ps mode is disabled, this workitem function is closed and scheduled new one // at next time whenever the ps mode is set again. // Arguments: // [in] - pContext - // The P2P context address. // Return: // None // By Bruce, 2010-12-13. // VOID P2PPsWorkItemCallback( IN PVOID pContext ) { PP2P_INFO pP2PInfo = (PP2P_INFO)pContext; if(!pP2PInfo) return; if(!P2P_ENABLED(pP2PInfo)) return; do { if(RT_CANNOT_IO(pP2PInfo->pAdapter)) break; pP2PInfo->usSleepTime = 0; if(pP2PInfo->bUpdatePsParameter) { P2PUpdatePowerSavePara(pP2PInfo); } if(pP2PInfo->psExeType == RT_P2P_PS_EXE_BY_SW_TIMER) { // Driver Timer P2PPsTimeout(pP2PInfo->pAdapter); } else if(pP2PInfo->psExeType == RT_P2P_PS_EXE_BY_HW) { // HW caculate P2PSetPsState(pP2PInfo, 0, 0, 0); break; } else { // Unknown state break; } // We don't need work item any more. if(pP2PInfo->usSleepTime == 0) break; if(pP2PInfo->usSleepTime > P2P_PS_TIMEOUT_TOLERANCE) PlatformSleepUs((pP2PInfo->usSleepTime - P2P_PS_TIMEOUT_TOLERANCE)); }while(TRUE); } // // Description: // On receiving a P2P PS timeout event, review the TSF timer and check all the condition whether the state is going into. // Arguemtns: // [in] pP2PInfo - // The P2P context. // Return: // None. // By Bruce, 2010-03-18. // VOID P2PPsTimeout( IN PADAPTER pAdapter ) { PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); // should be the default mgnt info PP2P_INFO pP2PInfo = pMgntInfo->pP2PInfo; PADAPTER pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter) ? pAdapter : GetFirstExtAdapter(pAdapter); BOOLEAN bNoA0Valid = FALSE, bNoA1Valid = FALSE; BOOLEAN bUpdatePsMode = FALSE; u8Byte curTsf = 0, preTbtt = 0, nextTbtt = 0, timeDiff = 0; u8Byte nextNoA0Start = 0, nextNoA1Start = 0, nextNoA0End = 0, nextNoA1End = 0, next1TimeNoAStart = 0; u8Byte tmpNoAStartTime = 0, tmpNextDozeTime = 0; u4Byte tmpNoAIntvl = 0, tmpNoADur = 0; u8Byte usBeaconInterval = 0, usCTWindow = 0; P2P_POWERSAVE_SET P2pPsSet; u1Byte i = 0; u4Byte P2pPsTimeState = P2P_PS_TIME_STATE_NO_PS; u4Byte psStateToSet = P2P_PS_AWAKE; u4Byte psSourceToSet = P2P_PS_CANCEL_ALL_PS; u8Byte psTimeoutToSet = 0; FunctionIn(COMP_P2P); // The role is incorrect if(pP2PInfo->Role != P2P_GO && pP2PInfo->Role != P2P_CLIENT) return; if(P2P_CLIENT == pP2PInfo->Role && !pMgntInfo->mAssoc) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] P2P_CLIENT but not associated! Skip...\n")); return; } // No P2P PS mode and the power state is awake. if(pP2PInfo->PsFlag == P2P_PS_CANCEL_ALL_PS && pP2PInfo->P2pPsState == P2P_PS_AWAKE && pP2PInfo->CTWindow == 0 && pP2PInfo->NoADescriptors[0].u8StartTime == 0 && pP2PInfo->NoADescriptors[1].u8StartTime == 0) { return; } usBeaconInterval = pP2PInfo->pAdapter->MgntInfo.dot11BeaconPeriod * sTU; usCTWindow = pP2PInfo->CTWindow * sTU; if(usBeaconInterval < P2P_PS_TIMEOUT_TOLERANCE) { //RT_TRACE(COMP_P2P, DBG_WARNING, ("Error: usBeaconInterval(%"i64fmt"d) < %d\n", usBeaconInterval, P2P_PS_TIMEOUT_TOLERANCE)); return; } // If the interface is usb, we cannot do the p2p process directly, but schedule the workitem to // do it instead. // By Bruce, 2010-12-13. if(!PlatformIsWorkItemScheduled(&(pP2PInfo->P2PPSWorkItem))) { PlatformScheduleWorkItem(&(pP2PInfo->P2PPSWorkItem)); return; } // The workitem is scheduled, just wait the workitem to do it. if(pP2PInfo->usSleepTime != 0) return; // // Cleint is in the awake state, the CTWindow doen't apply now. // if(pP2PInfo->Role == P2P_CLIENT && // (pP2PInfo->pAdapter->MgntInfo.dot11PowerSaveMode == eActive)) //{ // usCTWindow = 0; //} pP2PInfo->pAdapter->HalFunc.GetHwRegHandler(pP2PInfo->pAdapter, HW_VAR_TSF_TIMER, (pu1Byte)(&curTsf)); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("TSF = 0x%08X %08X (Low Dec = %d)\n", (u4Byte)(curTsf >> 32), (u4Byte)curTsf, (u4Byte)curTsf)); if(pP2PInfo->NextTimeout != 0 && (curTsf + P2P_PS_TIMEOUT_TOLERANCE) < pP2PInfo->NextTimeout) { // Ahead of time psStateToSet = pP2PInfo->P2pPsState; psSourceToSet = pP2PInfo->PsFlag; psTimeoutToSet = pP2PInfo->NextTimeout; goto setPs; } // Evaluate the current TBTT and next TBTT. if(PlatformModular64(curTsf, usBeaconInterval) > (usBeaconInterval - P2P_PS_TIMEOUT_TOLERANCE)) { preTbtt = (PlatformDivision64(curTsf, usBeaconInterval) + 1) * usBeaconInterval; nextTbtt = (PlatformDivision64(curTsf, usBeaconInterval) + 2) * usBeaconInterval; } else { preTbtt = PlatformDivision64(curTsf, usBeaconInterval) * usBeaconInterval; nextTbtt = (PlatformDivision64(curTsf, usBeaconInterval) + 1) * usBeaconInterval; } PlatformZeroMemory(&P2pPsSet, sizeof(P2P_POWERSAVE_SET)); P2pPsSet.bOppPs = pP2PInfo->bOppPS; P2pPsSet.CTWindow = pP2PInfo->CTWindow; // We shall verify if the current NoA is valid now. for(i = 0; i < P2P_MAX_NUM_NOA_DESC; i ++) { P2pPsSet.NoASet[i].bNoAEn = pP2PInfo->NoADescriptors[i].bValid; P2pPsSet.NoASet[i].NoADur = pP2PInfo->NoADescriptors[i].Duration; P2pPsSet.NoASet[i].NoAInt = pP2PInfo->NoADescriptors[i].Interval; P2pPsSet.NoASet[i].NoACnt = pP2PInfo->NoADescriptors[i].CountOrType; P2pPsSet.NoASet[i].bUseStartTime = TRUE; P2pPsSet.NoASet[i].u4StartTime = pP2PInfo->NoADescriptors[i].StartTime; if(pP2PInfo->NoADescriptors[i].bValid) { // Time 's up if(curTsf >= pP2PInfo->NoADescriptors[i].u8EndTime - P2P_PS_TIMEOUT_TOLERANCE) { P2pPsSet.NoASet[i].bNoAEn = FALSE; bUpdatePsMode = TRUE; } // The upper 4 TSF timer changed. if((curTsf & UINT64_C(0xFFFFFFFF00000000)) != (pP2PInfo->NoADescriptors[i].u8StartTime & UINT64_C(0xFFFFFFFF00000000))) { if(pP2PInfo->NoADescriptors[i].CountOrType != 0xFF) { // In this case, disable this NoA no matter the end of NoA reaches. P2pPsSet.NoASet[i].bNoAEn = FALSE; } else { // It is continuous NoA, the start time can be set a new one. P2pPsSet.NoASet[i].u4StartTime = 0; } bUpdatePsMode = TRUE; } } } if(bUpdatePsMode) { P2PSetPowerSaveMode(pP2PInfo, &P2pPsSet, pP2PInfo->NoAIEIndex, FALSE); return; } //3 //==============Evaluate the Current Time State===============// //4 // (1) NoA count == 1 if(pP2PInfo->NoADescriptors[0].bValid && (pP2PInfo->NoADescriptors[0].u8StartTime <= (curTsf + P2P_PS_TIMEOUT_TOLERANCE))) { bNoA0Valid = TRUE; } if(pP2PInfo->NoADescriptors[1].bValid && (pP2PInfo->NoADescriptors[1].u8StartTime <= (curTsf + P2P_PS_TIMEOUT_TOLERANCE))) { bNoA1Valid = TRUE; } // Note: // We assum that no two 1 Time NoA can run concurrently. // 1 Time NoA if(pP2PInfo->NoADescriptors[0].CountOrType == 1) { if(bNoA0Valid) { // 1Time NoA had Started P2pPsTimeState |= P2P_PS_TIME_STATE_IN_1TIME_NOA0; } else if(P2pPsSet.NoASet[0].bNoAEn) { next1TimeNoAStart = pP2PInfo->NoADescriptors[0].u8StartTime; } } else if(pP2PInfo->NoADescriptors[1].CountOrType == 1) { if(bNoA0Valid) { // 1Time NoA had Started P2pPsTimeState |= P2P_PS_TIME_STATE_IN_1TIME_NOA1; } else if(P2pPsSet.NoASet[1].bNoAEn) { next1TimeNoAStart = pP2PInfo->NoADescriptors[1].u8StartTime; } } //4 // (2) TBTT // Under this case, the NIC just sends the Beacon Frame only, but no data frames. if((PlatformModular64(curTsf, usBeaconInterval) < P2P_PS_TIMEOUT_TOLERANCE) || (PlatformModular64(curTsf, usBeaconInterval) > usBeaconInterval - P2P_PS_TIMEOUT_TOLERANCE)) { P2pPsTimeState |= P2P_PS_TIME_STATE_IN_TBTT; } //4 // (3) CTWindow if(usCTWindow > 0) { // Caculate if we are out of CTWindow if((PlatformModular64(curTsf, usBeaconInterval) < (usCTWindow - P2P_PS_TIMEOUT_TOLERANCE)) || (PlatformModular64(curTsf, usBeaconInterval) > (usBeaconInterval - P2P_PS_TIMEOUT_TOLERANCE))) { P2pPsTimeState |= P2P_PS_TIME_STATE_IN_CTWIN; } else { // We are out of CTWin P2pPsTimeState |= P2P_PS_TIME_STATE_OUT_CTWIN; // We need to check if any client is in active mode (including ourself if we are client mode). if(pP2PInfo->Role == P2P_GO) { // Check if the GO shall keep awake. PRT_WLAN_STA pEntry = NULL; // Find out if any station is in active mode; for(i = 0; i < ASSOCIATE_ENTRY_NUM; i ++) { pEntry = AsocEntry_EnumStation(pExtAdapter, i); if(!pEntry) continue; if(!pEntry->bPowerSave) { // There is one client in active mode, don't enter PS. P2pPsTimeState |= P2P_PS_TIME_STATE_OUT_CTWIN_CLIENT_AWAKE; break; } } } else if(pP2PInfo->Role == P2P_CLIENT && (pP2PInfo->pAdapter->MgntInfo.dot11PowerSaveMode == eActive)) { // Cleint is in the awake state, the CTWindow doen't apply now. // If there exists periodic NoA, we shall follow the rule of NoA. P2pPsTimeState |= P2P_PS_TIME_STATE_OUT_CTWIN_CLIENT_AWAKE; } } } //4 // (4) NoA Count > 1 if(bNoA0Valid && (pP2PInfo->NoADescriptors[0].CountOrType > 1)) { tmpNoAStartTime = pP2PInfo->NoADescriptors[0].u8StartTime; tmpNoAIntvl = pP2PInfo->NoADescriptors[0].Interval; tmpNoADur = pP2PInfo->NoADescriptors[0].Duration; timeDiff = (curTsf < tmpNoAStartTime) ? 0: (curTsf - tmpNoAStartTime); if(PlatformModular64(timeDiff, tmpNoAIntvl) < (tmpNoADur - P2P_PS_TIMEOUT_TOLERANCE)) { P2pPsTimeState |= P2P_PS_TIME_STATE_IN_NOA0; nextNoA0End = tmpNoAStartTime + (PlatformDivision64(timeDiff, tmpNoAIntvl) * tmpNoAIntvl + tmpNoADur); } else if(PlatformModular64(timeDiff, tmpNoAIntvl) > (tmpNoAIntvl - P2P_PS_TIMEOUT_TOLERANCE)) { P2pPsTimeState |= P2P_PS_TIME_STATE_IN_NOA0; nextNoA0End = tmpNoAStartTime + ((PlatformDivision64(timeDiff, tmpNoAIntvl) + 1) * tmpNoAIntvl + tmpNoADur); } else { P2pPsTimeState |= P2P_PS_TIME_STATE_OUT_NOA0; nextNoA0Start = tmpNoAStartTime + ((PlatformDivision64(timeDiff, tmpNoAIntvl) + 1) * tmpNoAIntvl); } } if(bNoA1Valid && (pP2PInfo->NoADescriptors[1].CountOrType > 1)) { tmpNoAStartTime = pP2PInfo->NoADescriptors[1].u8StartTime; tmpNoAIntvl = pP2PInfo->NoADescriptors[1].Interval; tmpNoADur = pP2PInfo->NoADescriptors[1].Duration; timeDiff = (curTsf < tmpNoAStartTime) ? 0: (curTsf - tmpNoAStartTime); if(PlatformModular64(timeDiff, tmpNoAIntvl) < (tmpNoADur - P2P_PS_TIMEOUT_TOLERANCE)) { P2pPsTimeState |= P2P_PS_TIME_STATE_IN_NOA1; nextNoA1End = tmpNoAStartTime + (PlatformDivision64(timeDiff, tmpNoAIntvl) * tmpNoAIntvl + tmpNoADur); } else if(PlatformModular64(timeDiff, tmpNoAIntvl) > (tmpNoAIntvl - P2P_PS_TIMEOUT_TOLERANCE)) { P2pPsTimeState |= P2P_PS_TIME_STATE_IN_NOA1; nextNoA1End = tmpNoAStartTime + ((PlatformDivision64(timeDiff, tmpNoAIntvl) + 1) * tmpNoAIntvl + tmpNoADur); } else { P2pPsTimeState |= P2P_PS_TIME_STATE_OUT_NOA1; nextNoA1Start = tmpNoAStartTime + ((PlatformDivision64(timeDiff, tmpNoAIntvl) + 1) * tmpNoAIntvl); } } //3 //==============Evaluate the Ps State and Timeout value===============// //4 // 1-Time NoA if(P2pPsTimeState & P2P_PS_TIME_STATE_IN_1TIME_NOA0) { psTimeoutToSet = pP2PInfo->NoADescriptors[0].u8EndTime; psSourceToSet = P2P_PS_ENTER_PS_BY_1TIME_NOA; psStateToSet = P2P_PS_DOZE_SEND_MGNT; goto setPs; } if(P2pPsTimeState & P2P_PS_TIME_STATE_IN_1TIME_NOA1) { psTimeoutToSet = pP2PInfo->NoADescriptors[1].u8EndTime; psSourceToSet = P2P_PS_ENTER_PS_BY_1TIME_NOA; psStateToSet = P2P_PS_DOZE_SEND_MGNT; goto setPs; } //4 // CTWindow. if(P2pPsTimeState & P2P_PS_TIME_STATE_IN_CTWIN) { tmpNextDozeTime = preTbtt + usCTWindow; // Next 1 Time NoA is earlier than the End of CTWin. if(next1TimeNoAStart > 0 && next1TimeNoAStart < tmpNextDozeTime) tmpNextDozeTime = next1TimeNoAStart; psTimeoutToSet = tmpNextDozeTime; psSourceToSet = P2P_PS_LEAVE_PS_BY_CTWIN_TBTT; psStateToSet = P2P_PS_AWAKE; goto setPs; } else if(P2pPsTimeState & P2P_PS_TIME_STATE_OUT_CTWIN) { if(!(P2pPsTimeState & P2P_PS_TIME_STATE_OUT_CTWIN_CLIENT_AWAKE)) { // Out of CTWin (the priority is higher than periodic NoA), Next TBTT must wake up. psTimeoutToSet = nextTbtt; psSourceToSet = P2P_PS_ENTER_PS_BY_CTWIN; psStateToSet = P2P_PS_DOZE; goto setPs; } } //4 // Periodic NoA if(P2pPsTimeState & (P2P_PS_TIME_STATE_IN_NOA0 | P2P_PS_TIME_STATE_IN_NOA1)) { if(P2pPsTimeState & P2P_PS_TIME_STATE_IN_TBTT) { // After sending Beacon (Mgnt frame), go back dozed. if(PlatformModular64(curTsf, usBeaconInterval) < P2P_PS_TIMEOUT_TOLERANCE) { tmpNextDozeTime = (PlatformDivision64(curTsf, usBeaconInterval) * usBeaconInterval + 5000); } else { tmpNextDozeTime = ((PlatformDivision64(curTsf, usBeaconInterval) + 1) * usBeaconInterval + 5000); } psTimeoutToSet = tmpNextDozeTime; psSourceToSet = P2P_PS_LEAVE_PS_BY_TBTT; psStateToSet = P2P_PS_DOZE_SEND_MGNT; goto setPs; } else { // Enter dozed state and caculate the next awake time. u8Byte tmpNextAwakeTime = nextNoA0End; // If the NoA1 and NoA2 are overlapped, caculate the latest end time of NoA. if(tmpNextAwakeTime < nextNoA1End) tmpNextAwakeTime = nextNoA1End; // Do not cross the TBTT if(tmpNextAwakeTime > nextTbtt) tmpNextAwakeTime = nextTbtt; psTimeoutToSet = tmpNextAwakeTime; psSourceToSet = P2P_PS_ENTER_PS_BY_PERIODIC_NOA; psStateToSet = P2P_PS_DOZE; goto setPs; } } else if(P2pPsTimeState & (P2P_PS_TIME_STATE_OUT_NOA0 | P2P_PS_TIME_STATE_OUT_NOA1)) { // Enter Awake state and caculate the next doze time. if(pP2PInfo->Role == P2P_CLIENT) { // Retrigger if the previous SP is ended by the NoA. if(!IN_LEGACY_POWER_SAVE(pMgntInfo->pStaQos) && pP2PInfo->bEospByNoA) { u1Byte AC = 0; if(GET_VO_UAPSD(pMgntInfo->pStaQos->Curr4acUapsd)) AC = 7; else if(GET_VI_UAPSD(pMgntInfo->pStaQos->Curr4acUapsd)) AC = 5; else if(GET_BE_UAPSD(pMgntInfo->pStaQos->Curr4acUapsd)) AC = 3; else if(GET_BK_UAPSD(pMgntInfo->pStaQos->Curr4acUapsd)) AC = 2; SendQoSNullFunctionData(pP2PInfo->pAdapter, pMgntInfo->Bssid, AC, TRUE); pMgntInfo->pStaQos->bInServicePeriod = TRUE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PPSTimeout(): Re-trigger the SP!\n")); } } pP2PInfo->bEospByNoA = FALSE; tmpNextDozeTime = nextNoA0Start; // Find the earliet NoA start time if(nextNoA1Start > 0 && tmpNextDozeTime > nextNoA1Start) tmpNextDozeTime = nextNoA1Start; // If the next doze time cross TBTT, set the timeout to TBTT if(tmpNextDozeTime > 0 && tmpNextDozeTime > nextTbtt) tmpNextDozeTime = nextTbtt; psTimeoutToSet = tmpNextDozeTime; psSourceToSet = P2P_PS_LEAVE_PS_BY_NOA; psStateToSet = P2P_PS_AWAKE; goto setPs; } else { // No one Periodic NoA is valid, and this state shall be kept awake until next CTWin comes, or all clients enter dozed, or one NoA becomes valid. // If next CTWin exists, set the next doze time as next CTWin because we will keep awake cross the next TBTT until the end of CTWin. tmpNextDozeTime = (usCTWindow > 0 && pP2PInfo->bOppPS) ? (nextTbtt + usCTWindow) : 0; // Next NoA0 start time. if(pP2PInfo->NoADescriptors[0].bValid && pP2PInfo->NoADescriptors[0].u8StartTime > curTsf) { if(tmpNextDozeTime == 0 || pP2PInfo->NoADescriptors[0].u8StartTime < tmpNextDozeTime) tmpNextDozeTime = pP2PInfo->NoADescriptors[0].u8StartTime; } // Next NoA1 start time comes earlier than NoA1 if(pP2PInfo->NoADescriptors[1].bValid && pP2PInfo->NoADescriptors[1].u8StartTime > curTsf) { if(tmpNextDozeTime == 0 || pP2PInfo->NoADescriptors[1].u8StartTime < tmpNextDozeTime) tmpNextDozeTime = pP2PInfo->NoADescriptors[1].u8StartTime; } if(P2pPsTimeState & P2P_PS_TIME_STATE_OUT_CTWIN_CLIENT_AWAKE) { psTimeoutToSet = tmpNextDozeTime; psSourceToSet = P2P_PS_LEAVE_PS_BY_OUT_CTWIN_ClIENT_AWAKE; psStateToSet = P2P_PS_AWAKE; goto setPs; } else { psTimeoutToSet = tmpNextDozeTime; psSourceToSet = P2P_PS_CANCEL_ALL_PS; psStateToSet = P2P_PS_AWAKE; goto setPs; } } setPs: RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2pPsTimeState = 0x%X, TimeDiff = %d\n", P2pPsTimeState, (u4Byte)(psTimeoutToSet - curTsf))); pP2PInfo->usSleepTime = (u4Byte)(psTimeoutToSet - curTsf); if(psTimeoutToSet < (curTsf + P2P_PS_TIMEOUT_TOLERANCE) && psTimeoutToSet != 0) { RT_TRACE(COMP_P2P, DBG_WARNING, ("P2PPsTimeout(): psTimeoutToSet = Timeout is less than TSF\n")); } // Temp solution for P2P Test Plan 6.1.13 and 7.1.5. By Bruce, 2010-06-30. if(P2pPsTimeState & (P2P_PS_TIME_STATE_IN_NOA0 | P2P_PS_TIME_STATE_IN_NOA1) || psSourceToSet & P2P_PS_ENTER_PS_BY_PERIODIC_NOA) { // Check the WMM-PS SPs are ended by the NoAs. // Temp solution for P2P Test Plan 6.1.13 and 7.1.5. By Bruce, 2010-06-30. if(pP2PInfo->Role == P2P_GO) { PRT_WLAN_STA pEntry = NULL; // Find out if any station in active mode; // If any client of P2P client in WMM-PS mode, end its SP. if(P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter)) { while(pAdapter != NULL) { if(pAdapter->pNdis62Common->PortType == EXT_P2P_ROLE_PORT && pP2PInfo->Role == P2P_GO) break; pExtAdapter = GetNextExtAdapter(pAdapter); } if(pExtAdapter == NULL) return; } for(i = 0; i < ASSOCIATE_ENTRY_NUM; i ++) { pEntry = AsocEntry_EnumStation(pExtAdapter, i); if(!pEntry) break; if(pEntry->bPowerSave && ((pEntry->WmmStaQosInfo & 0xF) != 0)) { pEntry->WmmEosp = RT_STA_EOSP_STATE_ENDED; RT_PRINT_ADDR(COMP_P2P, DBG_LOUD, "P2PPsTimeout(): End SP for the client: ", pEntry->MacAddr); // if(RTIsListNotEmpty(&(pEntry->WmmPsQueue))) // { // RT_TRACE(COMP_P2P, DBG_LOUD, ("Some WMM packets for this client, need trigger frame!\n")); // } } } } else if(pP2PInfo->Role == P2P_CLIENT) { // End the SP, and mark the SP is ended by the NoA, and we shall re-trigger if the NoA is in presence period. if(!IN_LEGACY_POWER_SAVE(pMgntInfo->pStaQos) && IS_WIFI_POWER_SAVE(pMgntInfo) && pMgntInfo->pStaQos->bInServicePeriod && pMgntInfo->pStaQos->bWmmMoreData) { pMgntInfo->pStaQos->bInServicePeriod = FALSE; pP2PInfo->bEospByNoA = TRUE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PPsTimeout(): Cleint SP is ended by the NoA\n")); } } } P2PSetPsState(pP2PInfo, psSourceToSet, (P2P_PS_STATE)psStateToSet, psTimeoutToSet); RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PPsTimeout(): <=====\n")); return; } VOID P2PInitializeTimer( PADAPTER pAdapter ) { PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo; PP2P_INFO pP2PInfo = (PP2P_INFO)pMgntInfo->pP2PInfo; PlatformInitializeTimer(pAdapter, &(pP2PInfo->P2PMgntTimer), (RT_TIMER_CALL_BACK)P2PMgntTimerCallback, NULL, "P2PMgntTimer"); PlatformInitializeTimer(pAdapter, &(pP2PInfo->ClientJoinGroupContext.P2PWaitForWpsReadyTimer), (RT_TIMER_CALL_BACK)P2PWaitForWpsReadyTimerCallback, NULL, "P2PWaitForWpsReadyTimer"); PlatformInitializeTimer(pAdapter, &(pP2PInfo->P2POidPostProcessTimer), (RT_TIMER_CALL_BACK)P2POidPostProcessTimerCallback, NULL, "P2POidPostProcessTimer"); pP2PInfo->P2PActionTimer = ActionTimerAllocate( pAdapter, "P2PActionTimer", HW_TSF_CLOCK, HW_TSF_CLOCK_PS_TIMER ); } VOID P2PCancelTimer( PADAPTER pAdapter ) { PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo; PP2P_INFO pP2PInfo = (PP2P_INFO)pMgntInfo->pP2PInfo; PlatformCancelTimer(pAdapter, &(pP2PInfo->P2PMgntTimer)); PlatformCancelTimer(pAdapter, &(pP2PInfo->ClientJoinGroupContext.P2PWaitForWpsReadyTimer)); PlatformCancelTimer(pAdapter, &(pP2PInfo->P2POidPostProcessTimer)); } VOID P2PReleaseTimer( PADAPTER pAdapter ) { PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo; PP2P_INFO pP2PInfo = (PP2P_INFO)pMgntInfo->pP2PInfo; PlatformReleaseTimer(pAdapter, &(pP2PInfo->P2PMgntTimer)); PlatformReleaseTimer(pAdapter, &(pP2PInfo->ClientJoinGroupContext.P2PWaitForWpsReadyTimer)); PlatformReleaseTimer(pAdapter, &(pP2PInfo->P2POidPostProcessTimer)); ActionTimerRelease(pAdapter, pP2PInfo->P2PActionTimer); } static VOID P2PActionTimerCallback( const ACTION_TIMER_ITEM * const pOneShotActionItem ) { PADAPTER pAdapter = (PADAPTER) pOneShotActionItem->pContext; P2PPsTimeout(pAdapter); } // // Description: // Save the P2P PS state and time value and configure the HW setting. // Arguments: // [in] pP2PInfo - // The P2P context. // [in] Source - // Identify the reason why the PS state is going. // [in] P2pState - // The P2P power save state to set. // [in] Timeout - // The next timeout value. // Return: // None. // VOID P2PSetPsState( IN PP2P_INFO pP2PInfo, IN u4Byte Source, IN P2P_PS_STATE P2pState, IN u8Byte Timeout ) { PADAPTER pAdapter = NULL; ACTION_TIMER_ITEM ActionItem; PMGNT_INFO pMgntInfo = NULL; if(!P2P_ENABLED(pP2PInfo)) return; pAdapter = pP2PInfo->pAdapter; pMgntInfo = &pAdapter->MgntInfo; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Source = 0x%X, P2pState = 0x%X, Timeout = 0x%08X %08X (Low Dec = %d)\n", Source, P2pState, (u4Byte)(Timeout >> 32), (u4Byte)Timeout, (u4Byte)Timeout)); pP2PInfo->P2pPsState = P2pState; pP2PInfo->PsFlag = Source; pP2PInfo->NextTimeout = Timeout; if(pMgntInfo->bWiFiConfg) { pAdapter->HalFunc.SetHwRegHandler(pAdapter, HW_VAR_P2P_PS_MODE, (pu1Byte)pP2PInfo); } else { pAdapter->HalFunc.SetHwRegHandler(pAdapter, HW_VAR_FCS_NOA, (pu1Byte)pP2PInfo); } // Set up the HW timer if(RT_P2P_PS_EXE_BY_SW_HW_TIMER == pP2PInfo->psExeType) { // + Flush the previous Action Item ActionTimerFlushActionItem(pAdapter, pP2PInfo->P2PActionTimer, ACTION_TYPE_P2P_POWERSAVE); PlatformZeroMemory(&ActionItem, sizeof(ActionItem)); ActionItem.ActionType = ACTION_TYPE_P2P_POWERSAVE; ActionItem.CallbackFunc = P2PActionTimerCallback; ActionItem.pContext = pP2PInfo->pAdapter; ActionItem.usTimeout = pP2PInfo->NextTimeout; ActionTimerRegisterActionItem(pAdapter, &ActionItem, pP2PInfo->P2PActionTimer); } } // // Description: // When the TSD BIT32 toggled (which means this bit changed), call this function to reset the // P2P NoA power save parameter. // Arguments: // [in] pP2PInfo - // The P2P context. // Return: // None. // By Bruce, 2011-03-03. // VOID P2PPsTsf_Bit32_Toggle( IN PP2P_INFO pP2PInfo ) { P2P_POWERSAVE_SET P2pPsSet; u1Byte i = 0; BOOLEAN bUpdatePsMode = FALSE; if(!P2P_ENABLED(pP2PInfo)) return; if((P2P_GO != pP2PInfo->Role) && (P2P_CLIENT != pP2PInfo->Role)) return; PlatformZeroMemory(&P2pPsSet, sizeof(P2P_POWERSAVE_SET)); P2pPsSet.bOppPs = pP2PInfo->bOppPS; P2pPsSet.CTWindow = pP2PInfo->CTWindow; // We shall verify if the current NoA is valid now. for(i = 0; i < P2P_MAX_NUM_NOA_DESC; i ++) { if(P2P_GO == pP2PInfo->Role) { // Re-enable the NoA. // If the role is client, no need to set noa parameters. P2pPsSet.NoASet[i].bNoAEn = pP2PInfo->NoADescriptors[i].bValid; P2pPsSet.NoASet[i].NoADur = pP2PInfo->NoADescriptors[i].Duration; P2pPsSet.NoASet[i].NoAInt = pP2PInfo->NoADescriptors[i].Interval; P2pPsSet.NoASet[i].NoACnt = pP2PInfo->NoADescriptors[i].CountOrType; if(MultiChannel_IsFCSInProgress(pP2PInfo->pAdapter)) { // Re-calculate NoAStartTime for FCS u1Byte NoAStart = 0; u8Byte uCurrentTsf = 0; u8Byte uNoAStartTsf = 0; PMGNT_INFO pMgntInfo = &(pP2PInfo->pAdapter->MgntInfo); pP2PInfo->pAdapter->HalFunc.GetHwRegHandler(pP2PInfo->pAdapter, HW_VAR_TSF_TIMER, (pu1Byte)(&uCurrentTsf)); MultiChannelGetFcsCommonInfo(pP2PInfo->pAdapter, MULTICHANNEL_FCS_COMMON_NOA_STARTTIME, &NoAStart); uNoAStartTsf = uCurrentTsf - PlatformModular64(uCurrentTsf, pMgntInfo->dot11BeaconPeriod*sTU); uNoAStartTsf += NoAStart*sTU; uNoAStartTsf += (pMgntInfo->dot11BeaconPeriod)*sTU; // next beacon RT_TRACE(COMP_MULTICHANNEL, DBG_LOUD, ("Start NoA TSF 0x%08X %08X modular %d\n", (u4Byte)(uNoAStartTsf>>32), (u4Byte)uNoAStartTsf, (u4Byte)PlatformModular64(uNoAStartTsf, pMgntInfo->dot11BeaconPeriod*sTU))); P2pPsSet.NoASet[i].bUseStartTime = TRUE; P2pPsSet.NoASet[i].u4StartTime = (u4Byte)uNoAStartTsf & 0xffffffff; } else { P2pPsSet.NoASet[i].bUseStartTime = FALSE; P2pPsSet.NoASet[i].u4StartTime = pP2PInfo->NoADescriptors[i].StartTime; } } if(pP2PInfo->NoADescriptors[i].bValid) { bUpdatePsMode = TRUE; } } if(bUpdatePsMode) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Reset the P2P PS for NoA\n")); if(MultiChannel_IsFCSInProgress(pP2PInfo->pAdapter)) { P2PSetPowerSaveMode(pP2PInfo, &P2pPsSet, 0, 0); pP2PInfo->pAdapter->HalFunc.SetHwRegHandler(pP2PInfo->pAdapter, HW_VAR_FCS_NOA, (pu1Byte)pP2PInfo); } else { P2PSetPowerSaveMode(pP2PInfo, &P2pPsSet, pP2PInfo->NoAIEIndex, FALSE); } } return; } // // Description: // Notify the client has changed its power save state and we shall update it so that the // P2P GO can enter PS or leave PS for CTWin. VOID P2PNotifyClientPSChange( IN PP2P_INFO pP2PInfo ) { PADAPTER pAdapter = NULL, pExtAdapter = NULL; u1Byte i = 0; PRT_WLAN_STA pEntry = NULL; BOOLEAN bAllClientSleep = TRUE; if(!P2P_ENABLED(pP2PInfo)) return; pAdapter = pP2PInfo->pAdapter; pExtAdapter = P2P_ADAPTER_OS_SUPPORT_P2P(pAdapter) ? pP2PInfo->pAdapter : GetFirstExtAdapter(pP2PInfo->pAdapter); if(pP2PInfo->Role != P2P_GO) return; if(!pP2PInfo->bOppPS) return; if(pP2PInfo->psExeType == RT_P2P_PS_EXE_BY_HW) { // Find out if any station is in active mode; for(i = 0; i < ASSOCIATE_ENTRY_NUM; i ++) { pEntry = AsocEntry_EnumStation(pExtAdapter, i); if(!pEntry) continue; if(!pEntry->bAssociated) continue; if(!pEntry->bPowerSave) { // There is one client in active mode, don't enter PS. bAllClientSleep = FALSE; break; } } pAdapter->HalFunc.SetHwRegHandler(pAdapter, HW_VAR_P2P_CLIENT_PS_STATE, (pu1Byte)&bAllClientSleep); } } // // Description: // The P2P watch dog for monitoring the status on P2P. // Arguments: // [in] pP2PInfo - // The P2P context. // Return: // None. // By Bruce, 2010-03-20. // VOID P2POnLinkStatusWatchdog( IN PADAPTER Adapter ) { PP2P_INFO pP2PInfo = GET_P2P_INFO(Adapter); u8Byte CurrentTime = 0; BOOLEAN bFirstDevicePortEnabled = FALSE; PADAPTER pDevAadpter = NULL; if(!pP2PInfo) return; else if(!P2P_ENABLED(pP2PInfo)) return; P2PSvc_OnWatchdog(pP2PInfo->pP2PSvcInfo); pDevAadpter = GetFirstDevicePort(Adapter); if(!pDevAadpter) return; else { PP2P_INFO pP2PDevInfo = GET_P2P_INFO(pDevAadpter); bFirstDevicePortEnabled = (pP2PDevInfo->uListenStateDiscoverability == 0)?FALSE:TRUE; } if(P2P_ADAPTER_OS_SUPPORT_P2P(Adapter) && GetFirstGOPort(Adapter) == NULL && GetFirstClientPort(Adapter) == NULL && bFirstDevicePortEnabled == FALSE) { return; } if(pP2PInfo->Role == P2P_GO && pP2PInfo->pAdapter->MgntInfo.mAssoc) { //if(pP2PInfo->ManagedUpdateCnt == 0) { // Update the P2P managed info PRT_WLAN_BSS pBssDesc = NULL; PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_SCAN_SPINLOCK); pBssDesc = BssDescDupByBssid(pP2PInfo->pAdapter, pP2PInfo->pAdapter->MgntInfo.Bssid); if(pBssDesc) { if(pBssDesc->P2PManagedInfo & maP2PDeviceManagement) P2PUpdateWlanApManagedInfo(pP2PInfo, pBssDesc); } PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_SCAN_SPINLOCK); pP2PInfo->ManagedUpdateCnt = P2P_UPDATE_MANAGED_INFO_PERIOD; } //else // pP2PInfo->ManagedUpdateCnt --; } CurrentTime = PlatformGetCurrentTime(); if(CurrentTime - pP2PInfo->LastTimerFired > 2000000) // 2sec {// the timer callback has not been executed for more than 2 sec RT_TRACE(COMP_P2P, DBG_LOUD, ("P2POnLinkStatusWatchdog(): re-fire timer\n")); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } if(pP2PInfo->bOppPS || pP2PInfo->NoADescriptors[0].bValid || pP2PInfo->NoADescriptors[1].bValid) { if(RT_P2P_PS_EXE_BY_SW_HW_TIMER == pP2PInfo->psExeType) P2PPsTimeout(Adapter); } } // // Description: // Issue a client's presence request to the AP for the specified NoA. // Arguments: // [in] pP2PInfo - // The P2P context. // [in] pP2pPs - // The address of P2P power save setting. // Return: // If success, return RT_STATUS_SUCCESS; Otherwise, return an error code. // By Bruce, 2010-05-06. // u4Byte P2PPresenceReq( IN PP2P_INFO pP2PInfo, IN PP2P_POWERSAVE_SET pP2pPs ) { if(pP2PInfo == NULL || pP2pPs == NULL) return RT_STATUS_FAILURE; // Only sent by p2p client. if(pP2PInfo->Role != P2P_CLIENT) return RT_STATUS_FAILURE; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PPresenceReq()=====>\n")); p2p_Send_PresenceReq(pP2PInfo, pP2pPs, pP2PInfo->pAdapter->MgntInfo.Bssid, 1); return RT_STATUS_SUCCESS; } // // Description: // Handle the P2P presence request from the client in the GO. If the GO accept the NoA, it will change its NoA attribute // and broadcast this info in the Beacon frame. The GO then sends the Presence Response with status which determines // the GO accept the client's request or not. // Arguments: // See P2P_OnBeacon() // Return: // Return RT_STATUS_SUCCESS if the parsing succeeds. // By Bruce, 2010-05-07. // RT_STATUS P2P_OnPresenceReq( IN PADAPTER pAdapter, IN PRT_RFD pRfd, IN POCTET_STRING posMpdu ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); P2P_POWERSAVE_SET tmpP2PPsSet; u1Byte Status = P2P_STATUS_SUCCESS; u1Byte NoADesc = 0, PreType, DiagToken, i; u4Byte PreNoADuration, PreNoAInterval; BOOLEAN bMyClient = TRUE; pu1Byte pSaAddr = Frame_pTaddr(*posMpdu); P2P_MESSAGE msg; if(!P2P_ENABLED(GET_P2P_INFO(pAdapter))) return RT_STATUS_SUCCESS; FunctionIn(COMP_P2P); if(pP2PInfo->Role != P2P_GO) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] The role is not Go!\n")); return RT_STATUS_INVALID_STATE; } RT_PRINT_DATA(COMP_P2P, DBG_TRACE, "P2P_OnDeviceDiscoverabilityRsp():\n", posMpdu->Octet, posMpdu->Length); do { if(RT_STATUS_SUCCESS == (rtStatus = p2p_parse_Action(posMpdu, DBG_LOUD, &msg))) if(!p2p_validate_PresenceReq(&msg)) { rtStatus = RT_STATUS_MALFORMED_PKT; break; } // Check if this is our client's request. if(P2PClientInfoFindByInterfaceAddress(pP2PInfo, pSaAddr) == NULL) { bMyClient = FALSE; RT_PRINT_ADDR(COMP_P2P, DBG_WARNING, "P2P_OnPresenceReq():[WARNING] not my client: ", pSaAddr); // return; } PlatformZeroMemory(&tmpP2PPsSet, sizeof(P2P_POWERSAVE_SET)); // Fill the CTWin. The Presence request does not apply in this field. tmpP2PPsSet.bOppPs = pP2PInfo->bOppPS; tmpP2PPsSet.CTWindow = pP2PInfo->CTWindow; NoADesc = (msg.noaLen == (13 + 2)) ? 1 : (msg.noaLen == (2 * 13 + 2)) ? 2 : 0; // Invalid Length if(msg.noaLen != 2 && NoADesc == 0) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Invalid Length!!\n")); rtStatus = RT_STATUS_INVALID_DATA; break; } DiagToken = GET_P2P_VENDOR_ACT_FRAME_DIALOG_TOKEN(posMpdu->Octet); for(i = 0; i < NoADesc; i ++) { PreType = ReadEF1Byte(msg._noa + (13 * i) + 2); PreNoADuration = ReadEF4Byte(msg._noa + (13 * i) + 3); PreNoAInterval = ReadEF4Byte(msg._noa + (13 * i) + 7); if(PreType < 1 || PreType > 2) { // NoA Type is invalid. Status = P2P_STATUS_FAIL_INVALID_PARAMETERS; break; } // The duration or interval is not acceptable. if(PreNoADuration < 1024 || PreNoADuration > PreNoAInterval) { // NoA count is invalid. Status = P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST; break; } tmpP2PPsSet.NoASet[i].bNoAEn = ((PreNoAInterval - PreNoADuration) > 0) ? TRUE : FALSE; // If the PreNoAInterval equals to duration, that means the client needs always be awake. tmpP2PPsSet.NoASet[i].NoACnt = 0xFF; tmpP2PPsSet.NoASet[i].NoADur = (PreNoAInterval - PreNoADuration); tmpP2PPsSet.NoASet[i].NoAInt = PreNoAInterval; } // We don't accpet the presence request for any client, because we do not support NoA/Opps in all ICs. // By Bruce, 2010-12-15. Status = P2P_STATUS_FAIL_UNABLE_TO_ACCOMODATE_REQUEST; if(Status == P2P_STATUS_SUCCESS) P2PSetPowerSaveMode(pP2PInfo, &tmpP2PPsSet, 0, TRUE); p2p_Send_PresenceRsp(pP2PInfo, pSaAddr, DiagToken, Status); }while(FALSE); p2p_parse_FreeMessage(&msg); return rtStatus; } // // Description: // Update the managed information from the AP which supports P2P managed device. // Arguments: // [in] pP2PInfo - // The P2P context. // [in] pBssDesc - // The BSS descriptor from the scan list. // Return: // None. // By Bruce, 2010-05-14. // VOID P2PUpdateWlanApManagedInfo( IN PP2P_INFO pP2PInfo, IN PRT_WLAN_BSS pBssDesc ) { PRT_AP_INFO pApInfo = NULL; // We need check if the BSS support P2P device management, but now the WLAN AP may not have this info in Beacon, // and it just disassociates us with the P2P deauth reason. Check this bit if the test plan has modified. By Bruce, 2010-05-14. // if(!(pBssDesc->P2PManagedInfo & maP2PDeviceManagement)) // return; PADAPTER pDefaultAdapter = GetDefaultAdapter(pP2PInfo->pAdapter); PADAPTER pAdapter = pDefaultAdapter; if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { while(pAdapter!=NULL) { if(pAdapter->pNdis62Common->PortType == EXT_P2P_ROLE_PORT && pP2PInfo->Role == P2P_GO) break; pAdapter = GetNextExtAdapter(pAdapter); } if(pAdapter == NULL) return; } pApInfo = (PRT_AP_INFO)(pAdapter->MgntInfo.pApModeInfo); if(pBssDesc->osWmmAcParaIE.Length == WMM_PARAM_ELEMENT_SIZE) { CopyMemOS(&pApInfo->osWmmAcParaIE, pBssDesc->osWmmAcParaIE, WMM_PARAM_ELEMENT_SIZE) pApInfo->bSupportWmm = TRUE; RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2PUpdateWlanApManagedInfo() osWmmAcParaIE:\n", pApInfo->osWmmAcParaIE.Octet, pApInfo->osWmmAcParaIE.Length); } if(pBssDesc->bdCountryIE.Length > 0) { CopyMemOS(&pApInfo->osCountryIe, pBssDesc->bdCountryIE, pBssDesc->bdCountryIE.Length); pApInfo->bSupportCountryIe = TRUE; RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2PUpdateWlanApManagedInfo() osCountryIe:\n", pApInfo->osCountryIe.Octet, pApInfo->osCountryIe.Length); } if(pBssDesc->osPowerConstraintIe.Length == MAX_DOT11_POWER_CONSTRAINT_IE_LEN) { CopyMemOS(&pApInfo->osPowerConstraintIe, pBssDesc->osPowerConstraintIe, MAX_DOT11_POWER_CONSTRAINT_IE_LEN); pApInfo->bSupportPowerConstraint= TRUE; RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2PUpdateWlanApManagedInfo() osCountryIe:\n", pApInfo->osPowerConstraintIe.Octet, pApInfo->osPowerConstraintIe.Length); } } // // Description: // Disable the P2P mode and clear the related variables. // Arguments: // Return: // None. // By Bruce, 2010-05-14. // VOID P2PDisable( IN PADAPTER Adapter ) { BOOLEAN bBoostIgi = FALSE; PP2P_INFO pP2PInfo = GET_P2P_INFO(Adapter); RT_TRACE(COMP_P2P, DBG_LOUD, ("======>P2PDisable()\n")); P2PSetRole(pP2PInfo, P2P_NONE); p2p_DevList_Free(&pP2PInfo->devList); PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); pP2PInfo->State = P2P_STATE_DISABLED; pP2PInfo->bUpdateFromBeacon = FALSE; pP2PInfo->bUpdatePsParameter = FALSE; pP2PInfo->PsFlag = 0; pP2PInfo->NextTimeout = 0; pP2PInfo->usSleepTime = 0; pP2PInfo->P2pPsState = P2P_PS_AWAKE; pP2PInfo->NoAIEIndex = 0; pP2PInfo->bOppPS = FALSE; pP2PInfo->CTWindow = 0; PlatformZeroMemory(pP2PInfo->NoADescriptors, sizeof(P2P_NOA_DESCRIPTOR) * P2P_MAX_NUM_NOA_DESC); pP2PInfo->bEospByNoA = FALSE; if(pP2PInfo->pProfileList) { PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Freeing previous profile list: %u profiles\n", pP2PInfo->pProfileList->nProfiles)); PlatformFreeMemory(pP2PInfo->pProfileList, pP2PInfo->profileListLen); pP2PInfo->profileListLen = 0; pP2PInfo->pProfileList = NULL; PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); } // Make sure the PS related HW configuration is cleared. Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_P2P_PS_MODE, (pu1Byte)pP2PInfo); if(P2P_ADAPTER_RTK_SUPPORT_P2P(Adapter)) { P2PIndicateCurrentState(pP2PInfo, pP2PInfo->State); } // Free allocated memory --------------------- P2PFreeAllocatedMemory(pP2PInfo->pAdapter); // ----------------------------------------- if(P2P_ADAPTER_RTK_SUPPORT_P2P(Adapter)) { bBoostIgi = FALSE; Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_BOOST_INIT_GAIN, &bBoostIgi); } RT_TRACE(COMP_P2P, DBG_LOUD, ("<======P2PDisable()\n")); } VOID P2PTranslateP2PInfoToDevDescV0( IN PP2P_INFO pP2PInfo, OUT PP2P_DEVICE_DESCRIPTOR_V0 pDevDesc ) { u1Byte i = 0, j = 0; PlatformFillMemory(pDevDesc, sizeof(PP2P_DEVICE_DESCRIPTOR_V0), 0); pDevDesc->Role = pP2PInfo->Role; pDevDesc->DeviceCapability = pP2PInfo->DeviceCapability; pDevDesc->GroupCapability = pP2PInfo->GroupCapability; cpMacAddr(pDevDesc->DeviceAddress, pP2PInfo->DeviceAddress); PlatformMoveMemory(&pDevDesc->WpsAttributes, &pP2PInfo->WpsAttributes, sizeof(P2P_WPS_ATTRIBUTES)); pDevDesc->RegulatoryClass = pP2PInfo->RegulatoryClass; pDevDesc->ListenChannel = pP2PInfo->ListenChannel; pDevDesc->OperatingChannel = pP2PInfo->OperatingChannel; PlatformMoveMemory(pDevDesc->CountryString, pP2PInfo->CountryString, 3); if(RT_STATUS_SUCCESS != MgntActQuery_P2PChannelList(pP2PInfo->pAdapter, sizeof(pDevDesc->ChannelPlanChannel), &pDevDesc->ChannelPlanLength, pDevDesc->ChannelPlanChannel)) { RT_TRACE(COMP_P2P, DBG_WARNING, ("P2PTranslateP2PInfoToDevDesc(): MgntActQuery_P2PChannelList returns error\n")); } { u1Byte StartIndex = 0; u1Byte CurrentIndex = 0; PP2P_CLIENT_INFO_DISCRIPTOR pClientInfoDesc = NULL; pDevDesc->P2PClientDescriptorListLength = 0; while((pClientInfoDesc = P2PClientInfoEnumClients(pP2PInfo, StartIndex, &CurrentIndex)) != NULL) { PlatformMoveMemory(&(pDevDesc->P2PClientDescriptorList[pDevDesc->P2PClientDescriptorListLength]), pClientInfoDesc, sizeof(P2P_CLIENT_INFO_DISCRIPTOR)); pDevDesc->P2PClientDescriptorListLength++; StartIndex = CurrentIndex + 1; pClientInfoDesc = NULL; } RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PTranslateP2PInfoToDevDesc(): %u clients enumerated\n", pDevDesc->P2PClientDescriptorListLength)); } PlatformMoveMemory(pDevDesc->SsidBuf, pP2PInfo->SSIDBuf, pP2PInfo->SSIDLen); pDevDesc->SsidLen = pP2PInfo->SSIDLen; pDevDesc->GOIntent = pP2PInfo->GOIntent; pDevDesc->GOConfigurationTimeout = pP2PInfo->GOConfigurationTimeout; pDevDesc->ClientConfigurationTimeout = pP2PInfo->ClientConfigurationTimeout; pDevDesc->DialogToken = pP2PInfo->DialogToken; //cpMacAddr(pDevDesc->GroupBssid, pP2PInfo->GroupBssid); cpMacAddr(pDevDesc->IntendedP2PInterfaceAddress, pP2PInfo->InterfaceAddress); pDevDesc->Status = pP2PInfo->Status; pDevDesc->MinorReasonCode = pP2PInfo->MinorReasonCode; pDevDesc->ExtendedListenTimingPeriod = pP2PInfo->ExtListenTimingPeriod; pDevDesc->ExtendedListenTimingDuration = pP2PInfo->ExtListenTimingDuration; } VOID P2PTranslateP2PInfoToDevDescV1( IN PP2P_INFO pP2PInfo, OUT PP2P_DEVICE_DESCRIPTOR_V1 pDevDesc ) { P2PTranslateP2PInfoToDevDescV0(pP2PInfo, (PP2P_DEVICE_DESCRIPTOR_V0)pDevDesc); pDevDesc->SignalStrength = 0; } u4Byte P2PTranslateP2PInfoToDevDesc( IN PP2P_INFO pP2PInfo, OUT PVOID pvDevDesc ) { u4Byte BytesWritten = 0; if(0x00000000 == pP2PInfo->P2PVersion) {// v0 P2PTranslateP2PInfoToDevDescV0(pP2PInfo, (PP2P_DEVICE_DESCRIPTOR_V0)pvDevDesc); BytesWritten = sizeof(P2P_DEVICE_DESCRIPTOR_V0); } else if(0x00000001 == pP2PInfo->P2PVersion) {// v1 P2PTranslateP2PInfoToDevDescV1(pP2PInfo, (PP2P_DEVICE_DESCRIPTOR_V1)pvDevDesc); BytesWritten = sizeof(P2P_DEVICE_DESCRIPTOR_V1); } else {// v2/v3 PP2P_DEVICE_DESCRIPTOR_V2 pLatestDevDesc = pvDevDesc; P2PTranslateP2PInfoToDevDescV1(pP2PInfo, (PP2P_DEVICE_DESCRIPTOR_V1)pvDevDesc); pLatestDevDesc->version = pP2PInfo->P2PVersion; PlatformFillMemory(pLatestDevDesc->manufacturerName, 65, 0); BytesWritten = sizeof(P2P_DEVICE_DESCRIPTOR_V2); } return BytesWritten; } VOID P2P_StartApRequest( IN PADAPTER Adapter ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) {//DbgPrint("AP_StartApRequest: fire timer again\n"); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Fire P2PMgntTimer!\n")); PlatformSetTimer( Adapter, &((GET_P2P_INFO(Adapter))->P2PMgntTimer), 0); } } VOID P2P_APRemoveKey( IN PADAPTER Adapter, IN PRT_WLAN_STA pSTA ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) { if(/*pSTA->bAssociated && bAssociated has been cleared*/ pSTA->perSTAKeyInfo.SecLvl == RT_SEC_LVL_WPA2 && pSTA->perSTAKeyInfo.PairwiseCipherSuite[0] == RT_ENC_ALG_AESCCMP) {// P2P Clients are always WPA2AES P2PIndicateClientDisconnected(GET_P2P_INFO(Adapter), pSTA->MacAddr); } } } VOID P2P_APSetkey( IN PADAPTER Adapter, IN u1Byte *pucMacAddr, IN u4Byte ulEncAlg ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) { if(ulEncAlg == CAM_AES) { P2PIndicateClientConnected(GET_P2P_INFO(Adapter), pucMacAddr); } } } VOID P2P_FilerCck( IN PADAPTER Adapter, IN OUT BOOLEAN *pbFilterCck ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) { *pbFilterCck = TRUE; } } VOID P2P_ConstructAssociateReqFilterCck( IN PADAPTER Adapter, IN OCTET_STRING AsocReq, IN OUT BOOLEAN *pbFilterCck ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) { if(P2PScanListIsGo(GET_P2P_INFO(Adapter), Frame_pDaddr(AsocReq))) {// to P2P GO *pbFilterCck = TRUE; } else {// to wlan AP *pbFilterCck = FALSE; } } } // // Description: // Determine if we shall accept this probe request when the current state is P2P GO mode. // Arguments: // [in] pAdapter - // The location of target adapter. // [in] posMpdu - // The location address of full 802.11 frame. // [in] posSsidToScan - // The SSID in this probe request. // Return: // Return TRUE if // a. we shall send probe response for this probe reqeust in P2P GO mode, or // b. this action is ignored if P2P is not enabled. // Return FALSE if the P2P inforamtion in this packet is mismatch and we shall not send probe response. // Remark: // When this function returns FALSE, it means the probe requst is a P2P probe request but the check information // is not match for our P2P GO. So this probe request must be dropped and not be responsed. // if the SSID is P2P Wildcard SSID (DIRECT-), this function changes the length of SSID to 0 so that our // AP can response this request by passing SSID check. // BOOLEAN P2P_IsGoAcceptProbeReq( IN PADAPTER pAdapter, IN POCTET_STRING posMpdu, IN POCTET_STRING posSsidToScan ) { BOOLEAN bAccept = TRUE; if(P2P_ENABLED(GET_P2P_INFO(pAdapter))) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; P2P_MESSAGE msg; if((GetDefaultAdapter(pAdapter)->MgntInfo.RegMultiChannelFcsMode >= MULTICHANNEL_FCS_SUPPORT_GO) && (MultiChannelSwitchNeeded(pAdapter))) { RT_TRACE(COMP_P2P, DBG_LOUD, ("Reject p2p probe request because fw switching is running!\n")); bAccept = FALSE; return bAccept; } if(RT_STATUS_SUCCESS != (rtStatus = p2p_parse_Ies(posMpdu, DBG_TRACE, &msg))) { return bAccept; } GET_P2P_INFO(pAdapter)->bProbeReqByLegacyClient = (msg.p2pAttributes.os.Length) ? (FALSE) : (TRUE); if(!GET_P2P_INFO(pAdapter)->bProbeReqByLegacyClient) { OCTET_STRING osWpsIE = PacketGetElement(*posMpdu, EID_Vendor, OUI_SUB_SimpleConfig, OUI_SUB_DONT_CARE); if(P2PIsWildcardSsid(*posSsidToScan)) {// Clause 3.2.2: P2P Wildcard SSID shall be treated the same as the Wildcard SSID posSsidToScan->Length = 0; // so that it does not return false when SSID is neither any nor our SSID } if(!P2PAcceptProbeReq(GET_P2P_INFO(pAdapter), posMpdu, &msg)) { bAccept = FALSE; } } p2p_parse_FreeMessage(&msg); } return bAccept; } VOID P2P_UpdateScanList( IN PADAPTER Adapter ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) { PP2P_INFO pP2PInfo = GET_P2P_INFO(Adapter); if(P2P_ADAPTER_OS_SUPPORT_P2P(Adapter)) { // Update the device list for the OS query ------------------ P2PDeviceListActionInterface( pP2PInfo, P2P_DEVICE_LIST_ACTION_COPY_TO_QUERY_LIST, NULL, NULL, NULL ); //P2PDeviceListActionInterface( // pP2PInfo, // P2P_DEVICE_LIST_ACTION_DUMP, // &pP2PInfo->DeviceList, // NULL, NULL // ); P2PDeviceListActionInterface( pP2PInfo, P2P_DEVICE_LIST_ACTION_DUMP, &pP2PInfo->DeviceListForQuery, NULL, NULL ); //---------------------------------------------------- } if(P2PScanListEqual(pP2PInfo->ScanList, pP2PInfo->ScanListSize, pP2PInfo->ScanList4Query, pP2PInfo->ScanList4QuerySize)) { //RT_TRACE(COMP_P2P, DBG_LOUD, // ("ScanComplete(): scan list the same, not to update ScanList4Query\n")); } else { P2PScanListCopy(pP2PInfo->ScanList4Query, &pP2PInfo->ScanList4QuerySize, pP2PInfo->ScanList, pP2PInfo->ScanListSize); P2PIndicateScanList(pP2PInfo); } P2PSvc_OnP2PScanComplete(pP2PInfo->pP2PSvcInfo); } } BOOLEAN P2P_ScanCallback( IN PADAPTER Adapter ) { if(P2P_ENABLED(GET_P2P_INFO(Adapter))) { PP2P_INFO pP2PInfo = GET_P2P_INFO(Adapter); // // Send 2 ProbeReq only when we are in Search State or Scan Phase. // This is to prevent the case, for example, when we are using customized // scan to send a ProvisionDiscReq to a P2P Device, we don't send two // ProvisionDiscReq. // if(pP2PInfo->State != P2P_STATE_SEARCH && pP2PInfo->State != P2P_STATE_SCAN) { //break; return FALSE; } } return TRUE; } VOID P2P_InactivePsCallback( IN PADAPTER pAdapter, IN u1Byte InactievPsState ) { if(P2P_ENABLED(GET_P2P_INFO(pAdapter))) { // // This workitem cancels all timer (including P2P Mgnt Timer), // and this has an effect on our Extended Listening Counter, // so we have to re set the timer here. // PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); // TODO: Should not set timer in workitem if(!GetDefaultAdapter(pAdapter)->bDriverIsGoingToUnload) { //if(pPSC->eInactivePowerState == eRfOff) if(InactievPsState == eRfOff) PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } } } // // Description: // Set the service response fragment threshold. // Arguments: // [in] pAdapter - // The NIC context pointer. // [in] serviceThreshold - // The fragment threshold for the service threshold. // Return: // RT_STATUS_SUCCESS if success. Otherwise return the RT_STATUS error code. // By Bruce, 2011-05-31. // RT_STATUS P2PSetServiceFragThreshold( IN PADAPTER pAdapter, IN u2Byte serviceThreshold ) { PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); if(!pP2PInfo) return RT_STATUS_INVALID_CONTEXT; if(serviceThreshold < P2P_SERVICE_MIN_RSP_FRG_THRESHOLD || serviceThreshold > P2P_SERVICE_MAX_RSP_FRAG_THRESHOLD) return RT_STATUS_INVALID_PARAMETER; pP2PInfo->SDRspFragmtntThreshold = serviceThreshold; RT_TRACE(COMP_P2P, DBG_LOUD, ("P2PSetServiceFragThreshold(): Set threshold = %d\n", pP2PInfo->SDRspFragmtntThreshold)); return RT_STATUS_SUCCESS; } RT_STATUS P2PSetProfileList( IN PADAPTER pAdapter, IN PP2P_PROFILE_LIST pProfileList ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); u4Byte allocSize = FIELD_OFFSET(P2P_PROFILE_LIST, profileList) + pProfileList->nProfiles * sizeof(P2P_PROFILE_LIST_ENTRY); if(!pP2PInfo) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("RT_STATUS_INVALID_CONTEXT\n")); return RT_STATUS_INVALID_CONTEXT; } PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); do { if(pP2PInfo->pProfileList) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Freeing previous profile list: %u profiles\n", pP2PInfo->pProfileList->nProfiles)); PlatformFreeMemory(pP2PInfo->pProfileList, pP2PInfo->profileListLen); pP2PInfo->profileListLen = 0; pP2PInfo->pProfileList = NULL; } if(RT_STATUS_SUCCESS != (rtStatus = PlatformAllocateMemory(pAdapter, &pP2PInfo->pProfileList, allocSize))) { break; } pP2PInfo->profileListLen = allocSize; PlatformMoveMemory(pP2PInfo->pProfileList, pProfileList, allocSize); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Set profile list: %u profiles\n", pP2PInfo->pProfileList->nProfiles)); }while(FALSE); PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); return rtStatus; } // // Description: // Get the service response fragment threshold. // Arguments: // [in] pAdapter - // The NIC context pointer. // [in] pServiceThreshold - // The fragment threshold pointer for the service threshold. // Return: // RT_STATUS_SUCCESS if success. Otherwise return the RT_STATUS error code. // By Bruce, 2011-05-31. // RT_STATUS P2PGetServiceFragThreshold( IN PADAPTER pAdapter, IN pu2Byte pServiceThreshold ) { PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); if(!pP2PInfo || !pServiceThreshold) return RT_STATUS_INVALID_CONTEXT; *pServiceThreshold = pP2PInfo->SDRspFragmtntThreshold; return RT_STATUS_SUCCESS; } #if 1 //------------------------------------------------------------------------------- // For delaying sending the peer response packet from the OID command //------------------------------------------------------------------------------- VOID P2POidPostProcessTimerCallback( IN PRT_TIMER pTimer ) { PADAPTER pAdapter = (PADAPTER)pTimer->Adapter; PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); u1Byte i = 0; // For IRQL Maintaince ------------------------------ // BOOLEAN bIrqlRestoreRequired = FALSE; // KIRQL BackupIrql = PASSIVE_LEVEL; // ----------------------------------------------- FunctionIn(COMP_P2P); if(RT_DRIVER_STOP(pAdapter)) { PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); return; } // ---------------------------------------------------------------------- RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: P2PGetChannel: %d\n", __FUNCTION__, P2PGetChannel(pP2PInfo))); RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: KeGetCurrentIrql(): %d\n", __FUNCTION__, KeGetCurrentIrql())); switch(pP2PInfo->OidOperation) { case OID_OPERATION_INDICATE_DISCOVERY_COMPLETE: { #if 0 RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Delay 10 ms to avoid too fast indication for WlanSvc!\n")); delay_ms(10); #endif RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: P2P_EVENT_DEVICE_DISCOVERY_COMPLETE\n", __FUNCTION__)); PlatformIndicateP2PEvent(pP2PInfo, P2P_EVENT_DEVICE_DISCOVERY_COMPLETE, NULL); } break; case OID_OPERATION_SEND_PACKET: { p2p_DevList_Lock(&pP2PInfo->devList); if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_PROVISION_DISCOVERY_RSP) { // Start sending provision discovery response --------------------------------------------------- CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_PDRsp( pP2PInfo, pP2PInfo->ProvisionResponseReceiverDeviceAddress, pP2PInfo->ProvisionResponseDialogToken, NULL, 0, // It is no use in Win8 since WPS IEs are generated by the OS NULL ); delay_ms(10); } else if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_INVITATION_RSP) { P2P_STATE StateBackup = pP2PInfo->State; pP2PInfo->State = P2P_STATE_INVITATION_REQ_RECVD; // Start sending invitation response ----------------------------------------------------------- //CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_InvitationRsp( pP2PInfo, pP2PInfo->InvitationResponseReceiverDeviceAddress, pP2PInfo->InvitationResponseDialogToken ); pP2PInfo->State = StateBackup; // Postpone the extended listening P2PExtendedListenResetCounter(pP2PInfo); // Update the state machine immediately PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } else if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_GO_NEGO_RSP) { // Start sending GO negotiation response --------------------------------------------------- CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_GoNegRsp( pP2PInfo, pP2PInfo->NegotiationResponsePeerDeviceAddress, pP2PInfo->NegotiationResponseDialogToken ); // Sync the status between Win8 and Win7 pP2PInfo->ConnectionContext.Status = pP2PInfo->NegotiationResponseStatus; // + Update the state machine if(pP2PInfo->ConnectionContext.Status == P2P_STATUS_SUCCESS) { pP2PInfo->State = P2P_STATE_GO_NEGO_RSP_SEND; } else if(pP2PInfo->Role != P2P_CLIENT) { pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; } RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P state 0x%x\n", pP2PInfo->State)); // Update the state machine immediately PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } else if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_GO_NEGO_CONFIRM) { // Start sending GO negotiation confirmation ---------------------------------------------------- //CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel BOOLEAN bSupportTxReport = FALSE; p2p_Send_GoNegConfirm( pP2PInfo, pP2PInfo->NegotiationConfirmPeerDeviceAddress, pP2PInfo->NegotiationConfirmDialogToken, &bSupportTxReport ); // + Update the state machine pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; // Update the state machine immediately PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 100); // In order not to switch channel delay_ms(10); } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Illegal Packet Type!\n", __FUNCTION__)); } // Reset the packet type ------------------------------------------------- pP2PInfo->PacketSentInWorkItemCallback = (P2P_PUBLIC_ACTION_TYPE) 0xFF; // -------------------------------------------------------------------- p2p_DevList_Unlock(&pP2PInfo->devList); } break; default: RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Wrong Operation Mode in WorkItem!\n", __FUNCTION__)); break; } #if 0 // Restore the IRQL Back --------------------- if(bIrqlRestoreRequired) KeLowerIrql(BackupIrql); // ---------------------------------------- #endif FunctionOut(COMP_P2P); } #else //------------------------------------------------------------------------------- // For delaying sending the peer response packet from the OID command //------------------------------------------------------------------------------- VOID P2POidPostProcessWorkItemCallback( IN PVOID pContext ) { PP2P_INFO pP2PInfo = (PP2P_INFO) pContext; u1Byte i = 0; // For IRQL Maintaince ------------------------------ BOOLEAN bIrqlRestoreRequired = FALSE; KIRQL BackupIrql = PASSIVE_LEVEL; // ----------------------------------------------- FunctionIn(COMP_P2P); for(i = 0; i < 10; i++) { if(pP2PInfo->bPostoneP2POidPostProcessWorkItem) { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: delay_ms(5) for other PASSIVE_LEVEL thread running~\n", __FUNCTION__)); delay_ms(5); } else break; } // Let this OID routine run faster than the P2POidPostProcessWorkItemCallback ------ if(KeGetCurrentIrql() == PASSIVE_LEVEL) { bIrqlRestoreRequired = TRUE; KeRaiseIrql(DISPATCH_LEVEL, &BackupIrql); } // ---------------------------------------------------------------------- RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: P2PGetChannel: %d\n", __FUNCTION__, P2PGetChannel(pP2PInfo))); RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: KeGetCurrentIrql(): %d\n", __FUNCTION__, KeGetCurrentIrql())); switch(pP2PInfo->OidOperation) { case OID_OPERATION_INDICATE_DISCOVERY_COMPLETE: { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Delay 10 ms to avoid too fast indication for WlanSvc!\n")); delay_ms(10); RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: P2P_EVENT_DEVICE_DISCOVERY_COMPLETE\n", __FUNCTION__)); if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) PlatformIndicateP2PEvent(pP2PInfo, P2P_EVENT_DEVICE_DISCOVERY_COMPLETE, NULL); } break; case OID_OPERATION_SEND_PACKET: { if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_PROVISION_DISCOVERY_RSP) { // Start sending provision discovery response --------------------------------------------------- CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_PDRsp( pP2PInfo, pP2PInfo->ProvisionResponseReceiverDeviceAddress, pP2PInfo->ProvisionResponseDialogToken, 0 // It is no use in Win8 since WPS IEs are generated by the OS ); } else if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_INVITATION_RSP) { P2P_STATE StateBackup = pP2PInfo->State; pP2PInfo->State = P2P_STATE_INVITATION_REQ_RECVD; // Start sending invitation response ----------------------------------------------------------- //CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_InvitationReq( pP2PInfo, pP2PInfo->InvitationResponseReceiverDeviceAddress, pP2PInfo->InvitationResponseDialogToken ); pP2PInfo->State = StateBackup; // Postpone the extended listening P2PExtendedListenResetCounter(pP2PInfo); // Update the state machine immediately PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } else if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_GO_NEGO_RSP) { // Start sending GO negotiation response --------------------------------------------------- CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_GoNegRsp( pP2PInfo, pP2PInfo->NegotiationResponsePeerDeviceAddress, pP2PInfo->NegotiationResponseDialogToken ); // Sync the status between Win8 and Win7 pP2PInfo->ConnectionContext.Status = pP2PInfo->NegotiationResponseStatus; // + Update the state machine if(pP2PInfo->ConnectionContext.Status == P2P_STATUS_SUCCESS) { pP2PInfo->State = P2P_STATE_GO_NEGO_RSP_SEND; } else if(pP2PInfo->Role != P2P_CLIENT) { pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; } // Update the state machine immediately PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 0); } else if(pP2PInfo->PacketSentInWorkItemCallback == P2P_PUB_ACT_GO_NEGO_CONFIRM) { BOOLEAN bSupportTxReport = FALSE; // Start sending GO negotiation confirmation ---------------------------------------------------- //CustomScan_ExtendDwellTime(GET_CUSTOM_SCAN_INFO(pAdapter), 100); // In order not to switch channel p2p_Send_GoNegConfirm( pP2PInfo, pP2PInfo->NegotiationConfirmPeerDeviceAddress, pP2PInfo->NegotiationConfirmDialogToken, &bSupportTxReport ); // + Update the state machine pP2PInfo->State = P2P_STATE_GO_NEGO_COMPLETE; // Update the state machine immediately PlatformCancelTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer); PlatformSetTimer(pP2PInfo->pAdapter, &pP2PInfo->P2PMgntTimer, 100); // In order not to switch channel } else { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Illegal Packet Type!\n", __FUNCTION__)); } // Reset the packet type ------------------------------------------------- pP2PInfo->PacketSentInWorkItemCallback = (P2P_PUBLIC_ACTION_TYPE) 0xFF; // -------------------------------------------------------------------- } break; default: RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Wrong Operation Mode in WorkItem!\n", __FUNCTION__)); break; } // Restore the IRQL Back --------------------- if(bIrqlRestoreRequired) KeLowerIrql(BackupIrql); // ---------------------------------------- FunctionOut(COMP_P2P); } #endif // ----------------------------------------- // Reset the Client Join Group Context // ----------------------------------------- VOID P2PResetClientJoinGroupContext( PP2P_INFO pP2PInfo ) { pP2PInfo->ClientJoinGroupContext.bInGroupFormation = FALSE; pP2PInfo->ClientJoinGroupContext.WpsState = P2P_CLIETN_JOIN_GROUP_WPS_STATE_NONE; pP2PInfo->ClientJoinGroupContext.uWaitForWpsSlotCount = 0; // 100 ms per slot PlatformCancelTimer( pP2PInfo->pAdapter, &pP2PInfo->ClientJoinGroupContext.P2PWaitForWpsReadyTimer ); } //------------------------------------------------------------------------------- // For delaying connection to wait for GO WPS ready //------------------------------------------------------------------------------- static VOID p2pWaitForWpsReady_CustomScanCb( IN CUSTOM_SCAN_STATE state, IN VOID *pCtx ) { P2P_INFO *info = (P2P_INFO *)pCtx; MGNT_INFO *mgnt = &info->pAdapter->MgntInfo; u4Byte it = 0; if(!P2P_ENABLED(info)) return; if(CUSTOM_SCAN_STATE_COMPLETED == state) { if(P2P_CLIETN_JOIN_GROUP_WPS_STATE_NONE != info->ClientJoinGroupContext.WpsState) { PlatformSetTimer(info->pAdapter, &info->ClientJoinGroupContext.P2PWaitForWpsReadyTimer, 1); } mgnt->NumBssDesc4Query = mgnt->NumBssDesc; for(it = 0; it < mgnt->NumBssDesc4Query; it++) { CopyWlanBss(mgnt->bssDesc4Query + it, mgnt->bssDesc + it); } } return; } VOID P2PWaitForWpsReadyTimerCallback( IN PRT_TIMER pTimer ) { PADAPTER pAdapter = (PADAPTER) pTimer->Adapter; PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; VOID *customScanInfo = GET_CUSTOM_SCAN_INFO(pAdapter); VOID *req = NULL; FRAME_BUF *probeReqBuf = NULL; FunctionIn(COMP_P2P); if(P2P_ADAPTER_OS_SUPPORT_P2P(pP2PInfo->pAdapter)) { if(MgntScanInProgress(pMgntInfo)) { PlatformSetTimer(pAdapter, &pP2PInfo->ClientJoinGroupContext.P2PWaitForWpsReadyTimer, 16); return; } switch(pP2PInfo->ClientJoinGroupContext.WpsState) { default: // Reset the variable in OID_DOT11_WFD_GROUP_START_PARAMETERS ------------------ RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Unknown wps state = %d\n", pP2PInfo->ClientJoinGroupContext.WpsState)); P2PResetClientJoinGroupContext(pP2PInfo); break; case P2P_CLIETN_JOIN_GROUP_WPS_STATE_SCANNING: { if(0 == pP2PInfo->ClientJoinGroupContext.uWaitForWpsSlotCount) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("WPS slot count is 0, stop scan!\n")); // Reset the variable in OID_DOT11_WFD_GROUP_START_PARAMETERS ------------------ P2PResetClientJoinGroupContext(pP2PInfo); break; } pP2PInfo->ClientJoinGroupContext.uWaitForWpsSlotCount --; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Call Customzied Scan to find out WPS Group!\n")); if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) return; // Call customized scan to scan the WPS group. if(pP2PInfo->uGroupTargetSSIDLength > 0 && pP2PInfo->uGroupTargetSSIDLength <= 32) { u4Byte bufLen = 0; PlatformMoveMemory(pMgntInfo->Ssid.Octet, pP2PInfo->GroupTargetSSID, pP2PInfo->uGroupTargetSSIDLength); pMgntInfo->Ssid.Length = (u2Byte)(pP2PInfo->uGroupTargetSSIDLength); // Send probe req with the interface address as the SA and we shall append P2P IE in this case, // otherwise the ProbeRsp would be regarded as from a legacy device and would not be processed. probeReqBuf = CustomScan_GetProbeReqBuf(req); ConstructProbeRequest(pAdapter, FrameBuf_MHead(probeReqBuf), &bufLen, TRUE, FALSE, FALSE); FrameBuf_Add(probeReqBuf, (u2Byte)bufLen); } CustomScan_AddScanChnl(req, pP2PInfo->OperatingChannel, 1, SCAN_ACTIVE, P2P_SCAN_WPS_GROUP_PERIOD, MGN_6M, probeReqBuf); CustomScan_AddScanChnl(req, pP2PInfo->ListenChannel, 1, SCAN_ACTIVE, 100, MGN_6M, probeReqBuf); CustomScan_SetRepeatCount(req, 16); CustomScan_SetupCbCtx(req, p2pWaitForWpsReady_CustomScanCb, pP2PInfo); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "cli join grp wps scanning"); } break; case P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY: { OCTET_STRING ssidStr = {NULL, 0}; PRT_WLAN_BSS pRtBss = NULL; RT_JOIN_ACTION joinAction = RT_NO_ACTION; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY\n")); //Sinda: temporarily mark. If OS care bForceScanLegacyNetworks flag //and un-mark the flag checking at case P2P_STATE_DEV_DISC_START of P2PMgntTimerCallback function. //We need to do legacy scan to update scan list to avoid to get out-of-date information of GO. #if 0 RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Target WPS info is ready but the BSS maybe out-of-date in the scan list, try to customized scan...\n")); // Call customized scan to scan the WPS group. if(pP2PInfo->uGroupTargetSSIDLength > 0 && pP2PInfo->uGroupTargetSSIDLength <= 32) { u4Byte bufLen = 0; PlatformMoveMemory(pMgntInfo->Ssid.Octet, pP2PInfo->GroupTargetSSID, pP2PInfo->uGroupTargetSSIDLength); pMgntInfo->Ssid.Length = (u2Byte)(pP2PInfo->uGroupTargetSSIDLength); ConstructProbeRequest(pAdapter, &(pScanReq->ProbeReqBuf[0]), (pu4Byte)&bufLen, TRUE, FALSE, FALSE); pScanReq->ProbeReqLen = (u2Byte)bufLen; } RT_TRACE_F(COMP_MLME, DBG_LOUD, ("P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY: MgntActSet_802_11_CustomizedScanRequest\n")); MgntActSet_802_11_CustomizedScanRequest(pAdapter, pScanReq); #endif if(PlatformAllocateMemory(pAdapter, (PVOID*)&pRtBss, sizeof(RT_WLAN_BSS)) != RT_STATUS_SUCCESS) return; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY: try to connect selected network by SSID(%s)\n", pP2PInfo->GroupTargetSSID)); FillOctetString(ssidStr, pP2PInfo->GroupTargetSSID, (u2Byte)(pP2PInfo->uGroupTargetSSIDLength)); joinAction = SelectNetworkBySSID(pAdapter, &ssidStr, FALSE, pRtBss); if(pRtBss) PlatformFreeMemory(pRtBss, sizeof(RT_WLAN_BSS)); if(RT_JOIN_INFRA == joinAction) { // The target is in the scan list, try to join it. pP2PInfo->ClientJoinGroupContext.WpsState = P2P_CLIETN_JOIN_GROUP_WPS_STATE_ASSOCIATING; PlatformSetTimer(pAdapter, &pP2PInfo->ClientJoinGroupContext.P2PWaitForWpsReadyTimer, 0); return; } if(NULL == (req = CustomScan_AllocReq(customScanInfo, NULL, NULL))) return; RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Target WPS info is ready but the BSS is not in the scan list, try to customized scan...\n")); // Call customized scan to scan the WPS group. if(pP2PInfo->uGroupTargetSSIDLength > 0 && pP2PInfo->uGroupTargetSSIDLength <= 32) { u4Byte bufLen = 0; PlatformMoveMemory(pMgntInfo->Ssid.Octet, pP2PInfo->GroupTargetSSID, pP2PInfo->uGroupTargetSSIDLength); pMgntInfo->Ssid.Length = (u2Byte)(pP2PInfo->uGroupTargetSSIDLength); probeReqBuf = CustomScan_GetProbeReqBuf(req); ConstructProbeRequest(pAdapter, FrameBuf_MHead(probeReqBuf), &bufLen, TRUE, FALSE, FALSE); FrameBuf_Add(probeReqBuf, (u2Byte)bufLen); } RT_TRACE_F(COMP_MLME, DBG_LOUD, ("P2P_CLIENT_JOIN_GROUP_WPS_STATE_GO_READY: CustomScan_IssueReq\n")); CustomScan_AddScanChnl(req, pP2PInfo->OperatingChannel, 2, SCAN_ACTIVE, P2P_SCAN_WPS_GROUP_PERIOD, MGN_6M, probeReqBuf); CustomScan_AddScanChnl(req, pP2PInfo->ListenChannel, 2, SCAN_ACTIVE, P2P_SCAN_WPS_GROUP_PERIOD, MGN_6M, probeReqBuf); CustomScan_SetupCbCtx(req, p2pWaitForWpsReady_CustomScanCb, pP2PInfo); CustomScan_IssueReq(customScanInfo, req, CUSTOM_SCAN_SRC_TYPE_P2P, "cli join grp wps go ready"); } break; case P2P_CLIETN_JOIN_GROUP_WPS_STATE_ASSOCIATING: { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P_CLIETN_JOIN_GROUP_WPS_STATE_ASSOCIATING\n")); pAdapter->pNdis62Common->CurrentOpState = OP_STATE; ndisStatus = N6CSet_DOT11_CONNECT_REQUEST( pAdapter, NULL, 0, 0, 0 // Don't Care ); pP2PInfo->ClientJoinGroupContext.WpsState = P2P_CLIETN_JOIN_GROUP_WPS_STATE_HANDSHAKING; } break; case P2P_CLIETN_JOIN_GROUP_WPS_STATE_HANDSHAKING: { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("P2P_CLIETN_JOIN_GROUP_WPS_STATE_HANDSHAKING\n")); } break; } } } //------------------------------------------------------------------------------- // Public P2P Utility Functions //------------------------------------------------------------------------------- // The public interface for operating the device lists outside this file BOOLEAN P2PDeviceListActionInterface( PP2P_INFO pP2PInfo, IN u1Byte uAction, IN PP2P_DEVICE_LIST pDeviceList, IN PMEMORY_BUFFER pInputBuffer, OUT PMEMORY_BUFFER pOutputBuffer ) { BOOLEAN bStatus = FALSE; switch(uAction) { case P2P_DEVICE_LIST_ACTION_COPY_TO_QUERY_LIST: { PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); P2PDeviceListCopyWithTimeStamp( pP2PInfo, &pP2PInfo->DeviceListForQuery, &pP2PInfo->DeviceList ); PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); bStatus = TRUE; } break; case P2P_DEVICE_LIST_ACTION_CLEAR: { PlatformAcquireSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); P2PDeviceListClear(pDeviceList); PlatformReleaseSpinLock(pP2PInfo->pAdapter, RT_P2P_SPIN_LOCK); bStatus = TRUE; } break; case P2P_DEVICE_LIST_ACTION_DUMP: { P2PDeviceListDump(pDeviceList); bStatus = TRUE; } break; default: { RT_TRACE(COMP_P2P, DBG_LOUD, ("%s: Illegal Action Failure!\n", __FUNCTION__)); } break; } return bStatus; } BOOLEAN P2PAddScanDeviceID( PP2P_DEVICE_ID_TO_SCAN pScanDeviceIDs, pu1Byte pDeviceID ) { BOOLEAN bStatus = FALSE; ULONG i; BOOLEAN bDuplicate; do { if(pScanDeviceIDs->uNumOfDeviceIDs > P2P_MAX_DEVICE_ID_TO_SCAN) break; bDuplicate = FALSE; for(i = 0; i < pScanDeviceIDs->uNumOfDeviceIDs; i++) { if(eqMacAddr(pDeviceID, pScanDeviceIDs->DeviceIDs[i])) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Found the MAC. Index: %d\n", i)); bDuplicate = TRUE; } } if(bDuplicate == FALSE) { cpMacAddr( pScanDeviceIDs->DeviceIDs[pScanDeviceIDs->uNumOfDeviceIDs], pDeviceID ); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Add MAC to Device list. Index: %d\n", pScanDeviceIDs->uNumOfDeviceIDs)); pScanDeviceIDs->uNumOfDeviceIDs++; } bStatus = TRUE; }while (FALSE); return bStatus; } VOID P2PClearScanDeviceID( PP2P_DEVICE_ID_TO_SCAN pScanDeviceIDs ) { FunctionIn(COMP_P2P); PlatformZeroMemory(pScanDeviceIDs, sizeof(P2P_DEVICE_ID_TO_SCAN)); FunctionOut(COMP_P2P); } // Free all allocated memory: PVOID or MEMORY_BUFFER VOID P2PFreeAllocatedMemory( IN PADAPTER pAdapter ) { PP2P_INFO pP2PInfo = pAdapter->MgntInfo.pP2PInfo; P2P_AddIe_Free(&pP2PInfo->AdditionalIEs); // Free the allocated memory of the device list ----------------------------------------------------------------- P2PDeviceListClear(&pP2PInfo->DeviceList); P2PDeviceListClear(&pP2PInfo->DeviceListForQuery); // ------------------------------------------------------------------------------------------------------ } // // Description: // Free P2P information memory allocated by P2P_AllocP2PInfo(). // Arguments: // [in] pAdapter - // The adapter context which the P2P info belongs to. // Return: // None. // VOID P2P_FreeP2PInfo( IN PADAPTER pAdapter ) { PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); PP2P_INFO pP2PInfo = NULL; FunctionIn(COMP_P2P); if(NULL == pMgntInfo->pP2PInfo) return; pP2PInfo = (PP2P_INFO)pMgntInfo->pP2PInfo; if(pP2PInfo->pProfileList) { RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Freeing previous profile list: %u profiles\n", pP2PInfo->pProfileList->nProfiles)); PlatformFreeMemory(pP2PInfo->pProfileList, pP2PInfo->profileListLen); pP2PInfo->profileListLen = 0; pP2PInfo->pProfileList = NULL; } P2PSvc_Free_P2PSvcInfo(pMgntInfo->pP2PInfo); PlatformFreeMemory(pP2PInfo, sizeof(P2P_INFO)); pMgntInfo->pP2PInfo = NULL; FunctionOut(COMP_P2P); } // // Description: // Allocate the P2P information memory which contains all P2P variables. // Arguments: // [in] pAdapter - // The adapter context which the P2P info belongs to. // Return: // If allocation process succeeded, return RT_STATUS_SUCESS. If the system cannot allocate enough memory // the context, return RT_STATUS_RESOURCE. Otherwise, return the RT_STATUS error code. // Remark: // This function allocates memory by structure "P2P_INFO" and initialize the default context. The caller must call // P2P_FreeP2PInfo() to free the allocated memory. // RT_STATUS P2P_AllocP2PInfo( IN PADAPTER pAdapter ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); PP2P_INFO pP2pInfo = NULL; FunctionIn(COMP_P2P); do { pMgntInfo->pP2PInfo = NULL; if(RT_STATUS_SUCCESS != (rtStatus = PlatformAllocateMemory(pAdapter, &(pMgntInfo->pP2PInfo), sizeof(P2P_INFO)))) break; PlatformZeroMemory(pMgntInfo->pP2PInfo, sizeof(P2P_INFO)); pAdapter->P2PSupport = P2P_SUPPORT_STATE_UNINITIALIZED; pP2pInfo = (PP2P_INFO)(pMgntInfo->pP2PInfo); // Pointer to the default adapter, then after OS/RTL initialized the info, the adapter pointer will be // asigned to the corresponding context. pP2pInfo->pAdapter = GetDefaultAdapter(pAdapter); pP2pInfo->pP2PSvcInfo = NULL; if(RT_STATUS_SUCCESS != (rtStatus = P2PSvc_AllocP2PSvcInfo(pMgntInfo->pP2PInfo))) break; }while(FALSE); if(RT_STATUS_SUCCESS != rtStatus) { RT_TRACE_F(COMP_WFD, DBG_SERIOUS, ("[ERROR] Allocation failed with error (%d)!!!\n", rtStatus)); P2PSvc_Free_P2PSvcInfo(pMgntInfo->pP2PInfo); P2P_FreeP2PInfo(pAdapter); } FunctionOut(COMP_P2P); return rtStatus; } // // Description: // Set the SSID which will be the GO SSID used in the auto GO or Go negotiation. // Arguments: // [in] pAdapter - // The adapter context which the P2P info belongs to. // [in] pSsidBuf - // The location points the SSID buffer. // [in] ssidLen - // The length for the SSID in pSsidBuf. // Return: // If set process succeeds, return RT_STATUS_SUCESS. // Remark: // This function does NOT check the valid SSID as defined in P2P spec (such as DIRECT-xxx). // If the ssidLen is 0, the SSID will be set as random. // RT_STATUS P2P_SetP2PGoFullSSID( IN PADAPTER pAdapter, IN pu1Byte pSsidBuf, IN u4Byte ssidLen ) { PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); if(ssidLen > MAX_SSID_LEN) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] Invalid SSID length = %d\n", ssidLen)); return RT_STATUS_INVALID_DATA; } pP2PInfo->regSSIDLen = (u1Byte)ssidLen; if(pP2PInfo->regSSIDLen > 0) { PlatformMoveMemory(pP2PInfo->regSSIDBuf, pSsidBuf, pP2PInfo->regSSIDLen); } RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2P_SetP2PGoFullSSID(): SSID =\n", pP2PInfo->regSSIDBuf, pP2PInfo->regSSIDLen); return RT_STATUS_SUCCESS; } // // Description: // Get the SSID which will be the GO SSID used in the auto GO or Go negotiation. // Arguments: // [in] pAdapter - // The adapter context which the P2P info belongs to. // [in] maxSsidBufLen - // The max length in pSsidBuf. // [out] pSsidBuf - // The location points the SSID buffer. // [out] pSsidLen - // The length for the SSID in pSsidBuf. // Return: // If set process succeeds, return RT_STATUS_SUCESS. // Remark: // This function does NOT check the valid SSID as defined in P2P spec (such as DIRECT-xxx). // If the ssidLen is 0, the SSID will be set as random. // RT_STATUS P2P_GetP2PGoFullSSID( IN PADAPTER pAdapter, IN u4Byte maxSsidBufLen, IN pu1Byte pSsidBuf, IN pu4Byte pSsidLen ) { PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); if(maxSsidBufLen < (u4Byte)pP2PInfo->regSSIDLen) { RT_TRACE_F(COMP_P2P, DBG_WARNING, ("[WARNING] maxSsidBufLen = %d < SSID Len (%d)\n", maxSsidBufLen, pP2PInfo->regSSIDLen)); return RT_STATUS_BUFFER_TOO_SHORT; } *pSsidLen = (u4Byte)pP2PInfo->regSSIDLen; if(pP2PInfo->regSSIDLen > 0) { PlatformMoveMemory(pSsidBuf, pP2PInfo->regSSIDBuf, pP2PInfo->regSSIDLen); } RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2P_GetP2PGoFullSSID(): SSID =\n", pSsidBuf, *pSsidLen); return RT_STATUS_SUCCESS; } // // Description: // Check if any p2p device exists. // [in] pAdapter - // The adapter context for any port. // Return: // Return TRUE if any p2p port is found. // Remark: // The input adapter can be from any port and this function checks each port adapter. // BOOLEAN IsP2PDeviceExisting( IN PADAPTER pAdapter ) { PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); PADAPTER pDevicePort = NULL; pDevicePort = pDefaultAdapter; while(pDevicePort != NULL) { if(P2P_ENABLED(GET_P2P_INFO(pDevicePort))) { return TRUE; } pDevicePort = GetNextExtAdapter(pDevicePort); } return FALSE; } // // Description: // Check if the RTK P2P device exists. // [in] pAdapter - // The adapter context for any port. // Return: // Return TRUE if any RTK p2p port is found. // Remark: // The input adapter can be from any port and this function checks each port adapter. // BOOLEAN IsRTKP2PDeviceExisting( IN PADAPTER pAdapter ) { PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); PADAPTER pDevicePort = NULL; pDevicePort = pDefaultAdapter; while(pDevicePort != NULL) { // If any RTK P2P exists, return FALSE. if(P2P_ENABLED(GET_P2P_INFO(pDevicePort)) && P2P_ADAPTER_RTK_SUPPORT_P2P(pDevicePort)) { return TRUE; } // ToDo, check other P2P conditions. pDevicePort = GetNextExtAdapter(pDevicePort); } return FALSE; } // // Description: // Check if the IPS is accessible. // [in] pAdapter - // The adapter context for any port. // Return: // Return TRUE if IPS is accessible for P2P mode. // Remark: // The input adapter can be from any port and this function checks each port adapter. // BOOLEAN P2P_IPS_Accessible( IN PADAPTER pAdapter ) { if(IsRTKP2PDeviceExisting(pAdapter)) { return FALSE; } return TRUE; } VOID P2P_Construct_ProbeReqEx( IN FRAME_BUF *pBuf, IN P2P_INFO *pP2PInfo, IN const u1Byte *da, IN u1Byte ssidLen, IN const u1Byte *ssidBuf ) { p2p_Construct_ProbeReqEx(pBuf, pP2PInfo, da, ssidLen, ssidBuf); return; } VOID P2P_Construct_ProbeReq( IN FRAME_BUF *pBuf, IN P2P_INFO *pP2PInfo ) { p2p_Construct_ProbeReq(pBuf, pP2PInfo); } // // Description: // Change the primary (and sub) device category if the setting in P2P info is unknown. // Sometimes the OS may just set the primary category as 0 (reserved in WPS spec) if // there is one application applying P2P or miracast sink function, // and we shall change the device category. // Arguments: // [in] pAdapter - // The adapter context for any port. // Return: // If setting process succeeds, return RT_STATUS_SUCESS. // RT_STATUS P2P_CorrectDeviceCategory( IN PADAPTER pAdapter ) { RT_STATUS rtStatus = RT_STATUS_SUCCESS; PP2P_INFO pP2PInfo = GET_P2P_INFO(pAdapter); WFD_DEV_TYPE devType = WFD_DEV_TYPE_SOURCE; const FRAME_BUF *pAddIeBuf = NULL; u4Byte wfdInfoLen = 0; u2Byte priCategory = WPS_PRI_DEV_TYPE_CATEGORY_PC; if(!P2P_ENABLED(pP2PInfo)) return RT_STATUS_INVALID_STATE; do { if(WPS_PRI_DEV_TYPE_CATEGORY_UNKNOWN == pP2PInfo->WpsAttributes.PrimaryDeviceType.CategoryId || WPS_PRI_DEV_TYPE_CATEGORY_PC == pP2PInfo->WpsAttributes.PrimaryDeviceType.CategoryId) { // Change it when the category is unknown or PC } else { // Do nothing break; } if(NULL != (pAddIeBuf = P2P_AddIe_Get(&pP2PInfo->AdditionalIEs, P2P_ADD_IE_PROBE_RESPONSE))) { OCTET_STRING osTemp = pAddIeBuf->os; wfdInfoLen = sizeof(WFD_DEV_TYPE); if(RT_STATUS_SUCCESS == (rtStatus = WFD_GetInfoOnIEs(pAdapter, WFD_INFO_DEVICE_TYPE, &osTemp, (pu1Byte)&devType, &wfdInfoLen))) { if(WFD_DEV_TYPE_SOURCE == devType) { priCategory = WPS_PRI_DEV_TYPE_CATEGORY_PC; } else { priCategory = WPS_PRI_DEV_TYPE_CATEGORY_DISPLAY; } } } pP2PInfo->WpsAttributes.PrimaryDeviceType.CategoryId = priCategory; pP2PInfo->WpsAttributes.PrimaryDeviceType.SubCategoryId = WPS_PRI_DEV_TYPE_SUB_CATEGORY_NO_SUB; PlatformMoveMemory(pP2PInfo->WpsAttributes.PrimaryDeviceType.Oui, WPS_NO_SUB_CAT_OUI, 4); RT_TRACE_F(COMP_P2P, DBG_LOUD, ("Changed WPS Category = 0x%04X, SubCategory = 0x%04X\n", pP2PInfo->WpsAttributes.PrimaryDeviceType.CategoryId, pP2PInfo->WpsAttributes.PrimaryDeviceType.SubCategoryId)); RT_PRINT_DATA(COMP_P2P, DBG_LOUD, "P2P_CorrectDeviceCategory(): OUI =\n", pP2PInfo->WpsAttributes.PrimaryDeviceType.Oui, 4); }while(FALSE); return rtStatus; } //====================================================================== // Wi-Fi Direct End //====================================================================== #endif // #if (P2P_SUPPORT == 1)