/* *************************************************************************** * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2009, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. *************************************************************************** Module Name: auto_provision Abstract: */ #include "rt_config.h" extern UCHAR WPS_OUI[]; #ifdef EASY_CONFIG_SETUP #ifdef CONFIG_AP_SUPPORT VOID AutoProvisionBuildAssocRespIE( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN UCHAR Reason, OUT PUCHAR pOutBuf, OUT PUCHAR pIeLen) { WSC_IE_HEADER ieHdr; UCHAR Data[512] = {0}; PUCHAR pData; INT Len = 0, templen = 0; UINT8 tempVal = 0; #ifdef EASY_CONFIG_SETUP UCHAR ExtData[4] = {0}; #endif /* EASY_CONFIG_SETUP */ UCHAR Version = 0x10; USHORT Tag = 0, TlvLen = 0; DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildAssocRespIE\n")); /* WSC IE Header */ ieHdr.elemId = 221; ieHdr.length = 4; ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; ieHdr.oui[2] = 0xF2; ieHdr.oui[3] = 0x04; pData = (PUCHAR) &Data[0]; Len = 0; /* Version, 1 byte */ Tag = cpu2be16(0x104A); TlvLen = cpu2be16(1); NdisMoveMemory(pData, &Tag, 2); NdisMoveMemory(pData+2, &TlvLen, 2); NdisMoveMemory(pData+4, &Version, 1); templen = 5; pData += templen; Len += templen; /* Request Type */ tempVal = 0x03; Tag = cpu2be16(0x103B); TlvLen = cpu2be16(1); NdisMoveMemory(pData, &Tag, 2); NdisMoveMemory(pData+2, &TlvLen, 2); NdisMoveMemory(pData+4, &tempVal, 1); templen = 5; pData += templen; Len += templen; /* Only main bssid supports auto provision. */ if ((pAd->ApCfg.MBSSID[MAIN_MBSSID].EasyConfigInfo.bEnable == TRUE) && (ApIdx == MAIN_MBSSID)) { /* WPS Vendor Extension */ NdisMoveMemory(ExtData, RALINK_OUI, 3); ExtData[3] = Reason; Tag = cpu2be16(0x1049); TlvLen = cpu2be16(4); NdisMoveMemory(pData, &Tag, 2); NdisMoveMemory(pData+2, &TlvLen, 2); NdisMoveMemory(pData+4, &ExtData[0], 4); templen = 8; pData += templen; Len += templen; } ieHdr.length = ieHdr.length + Len; NdisMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); NdisMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); *pIeLen = sizeof(WSC_IE_HEADER) + Len; DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildAssocRespIE\n")); } VOID AutoProvisionBuildAssocRspIE( IN PRTMP_ADAPTER pAd, IN PMLME_QUEUE_ELEM Elem, IN PMAC_TABLE_ENTRY pEntry, OUT PUCHAR pOutBuffer, OUT PULONG pFrameLen) { if (pEntry && pEntry->bRaAutoWpsCapable) { UCHAR *pWscBuf = NULL, WscIeLen = 0; ULONG WscTmpLen = 0; PEASY_CONFIG_INFO pEasyConfig = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo; os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); if (pWscBuf != NULL) { CHAR Rssi = -80; Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); NdisZeroMemory(pWscBuf, 512); #ifdef WSC_AP_SUPPORT if ((pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.WscConfMode != WSC_DISABLE) && (MAC_ADDR_EQUAL(pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.EntryAddr, pEntry->Addr))) { if (Rssi > pEasyConfig->RssiThreshold) WscBuildAssocRespIE(pAd, pEntry->func_tb_idx, 0, pWscBuf, &WscIeLen); else { pEntry->bRaAutoWpsCapable = FALSE; WscBuildAssocRespIE(pAd, pEntry->func_tb_idx, 1, pWscBuf, &WscIeLen); } } else #endif /* WSC_AP_SUPPORT */ if (pEasyConfig->bEnable == TRUE) { if (Rssi > pEasyConfig->RssiThreshold) AutoProvisionBuildAssocRespIE(pAd, pEntry->func_tb_idx, 0, pWscBuf, &WscIeLen); else { pEntry->bRaAutoWpsCapable = FALSE; AutoProvisionBuildAssocRespIE(pAd, pEntry->func_tb_idx, 1, pWscBuf, &WscIeLen); } } MakeOutgoingFrame(pOutBuffer + (*pFrameLen), &WscTmpLen, WscIeLen, pWscBuf, END_OF_ARGS); (*pFrameLen) += WscTmpLen; os_free_mem(NULL, pWscBuf); } else DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); } } VOID AutoProvisionCheckEntry( IN RTMP_ADAPTER *pAd, IN PMAC_TABLE_ENTRY pEntry, IN PEID_STRUCT eid_ptr) { #ifdef WAC_SUPPORT if (pEntry && pEntry->bSamsungAutoWpsCapable) return; #endif // WAC_SUPPORT // if (pAd->ApCfg.MBSSID[MAIN_MBSSID].EasyConfigInfo.bEnable==TRUE) { if (pEntry && eid_ptr) { pEntry->bRaAutoWpsCapable = FALSE; if (pEntry->func_tb_idx == MAIN_MBSSID) { if (WpsMICIntegrity(pAd, eid_ptr->Octet, (INT)eid_ptr->Len, pEntry->Addr, pEntry->func_tb_idx)) { pEntry->bRaAutoWpsCapable = TRUE; } } } } } VOID AutoProvisionAssignSSID( IN PRTMP_ADAPTER pAd, IN PUCHAR eid_data, IN INT eid_len, IN PUCHAR pAddr2, IN UCHAR apidx, OUT PUCHAR SsidLen, OUT PUCHAR Ssid) { if (pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.bEnable == FALSE) { DBGPRINT(RT_DEBUG_ERROR, ("MBSSID[%d] do not support Easy Config, skip the checking EC OUI\n",apidx)); return; } if (WpsMICIntegrity(pAd, eid_data, eid_len, pAddr2, apidx)) { *SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; NdisMoveMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, *SsidLen); } } BOOLEAN AutoProvisionCheckWscMsg( IN PRTMP_ADAPTER pAd, IN PFRAME_802_11 pFrame, INOUT PUSHORT pDataSize) { /*int HeaderLen = LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME);*/ RTMP_STRING *pData; PEAP_FRAME pEapFrame; /* Skip the EAP LLC header */ pData = (RTMP_STRING *) (pFrame + LENGTH_802_1_H); if (pData) pEapFrame = (PEAP_FRAME)(pData + sizeof(IEEE8021X_FRAME)); pData += sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME); if ((pData != NULL) && (pEapFrame->Code == EAP_CODE_RSP) && (pEapFrame->Type == EAP_TYPE_WSC)) { if (WscCheckWSCHeader((PUCHAR) pData)) { /* EAP-Rsp (Messages) */ pData += sizeof(WSC_FRAME); if (pData && (pData + 9)) { UCHAR MsgType = *(pData + 9); if (MsgType == 0x04) /* M1 */ { *pDataSize -= 19; } } } } return FALSE; } #endif /* CONFIG_AP_SUPPORT */ VOID AutoProvisionGenWpsPTK( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx) { UCHAR temp1[64]; CHAR temp2[6] = {'r', 'a', 'l', 'i', 'n', 'k'}; PEASY_CONFIG_INFO pEasyConfigInfo; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { pEasyConfigInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { pEasyConfigInfo = &pAd->StaCfg.EasyConfigInfo; } #endif /* CONFIG_STA_SUPPORT */ /* use proprietary WPS PTK */ NdisZeroMemory(temp1, 64); NdisMoveMemory(temp1, "ralink_auto_provision", strlen("ralink_auto_provision")); NdisZeroMemory(pEasyConfigInfo->WpsPTK, 64); /* use proprietary PTK */ WpaDerivePTK(pAd, temp1, temp1, temp2, temp1, temp2, pEasyConfigInfo->WpsPTK, LEN_PTK); } VOID AutoProvisionDecodeExtData( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN PUCHAR pEntryAddr, IN PUCHAR pData) { #ifdef WSC_INCLUDED PWSC_CTRL pWpsCtrl = NULL; #endif /* WSC_INCLUDED */ PMAC_TABLE_ENTRY pEntry = NULL; PEASY_CONFIG_INFO pEasyConfigInfo = NULL; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { pEasyConfigInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; #ifdef WSC_INCLUDED pWpsCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; #endif /* WSC_INCLUDED */ } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { pEasyConfigInfo = &pAd->StaCfg.EasyConfigInfo; #ifdef WSC_INCLUDED pWpsCtrl = &pAd->StaCfg.WscControl; #endif /* WSC_INCLUDED */ } #endif /* CONFIG_STA_SUPPORT */ pEntry = MacTableLookup(pAd, pEntryAddr); if (pEntry && (pEntry->bRaAutoWpsCapable && !pEntry->bSamsungAutoWpsCapable)) { CIPHER_KEY CipherKey; CHAR EncryptedPIN[16] = {0}, PinStr[9] = {0}; UINT16 PinLen = 12; UCHAR iv_hdr[4]; NdisZeroMemory(&CipherKey, sizeof(CIPHER_KEY)); NdisMoveMemory(&CipherKey, pEasyConfigInfo->WpsPTK, 64); CipherKey.CipherAlg = CIPHER_WEP128; CipherKey.KeyLen = 13; NdisMoveMemory(&EncryptedPIN[4], pData+3, 12); /* Construct the 4-bytes WEP IV header */ RTMPConstructWEPIVHdr(1, CipherKey.TxTsc, iv_hdr); NdisMoveMemory(&EncryptedPIN[0], &iv_hdr, 4); PinLen = 16; if (RTMPSoftDecryptWEP(pAd, &CipherKey, EncryptedPIN, &PinLen)) { NdisMoveMemory(PinStr, &EncryptedPIN[0], 8); NdisMoveMemory(&(pEasyConfigInfo->WpsPinCode[0]), &EncryptedPIN[0], 8); #ifdef WSC_INCLUDED if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && (pEasyConfigInfo->bEnable)) { pWpsCtrl->WscPinCode = simple_strtol(PinStr, 0, 10); pWpsCtrl->WscPinCodeLen = 8; /* To make sure of doing WPS process with WPS Client by PIN method */ pWpsCtrl->WscMode = WSC_PIN_MODE; WscGetRegDataPIN(pAd, pWpsCtrl->WscPinCode, pWpsCtrl); } #endif /* WSC_INCLUDED */ } } } BOOLEAN WpsMICIntegrity( IN PRTMP_ADAPTER pAd, IN PUCHAR pData, IN INT DataLen, IN PUCHAR pMacAddr, IN UCHAR ApIdx) { BOOLEAN bStatus = FALSE; PUCHAR pBuf = NULL; INT BufLen = 0, Length = DataLen; UCHAR *Ptr = pData + 4, *pWpsMIC = NULL, *pPeerWpsMIC = NULL; WSC_IE *pWscIE; EASY_CONFIG_INFO *pEasyConfigInfo = NULL; if (DataLen > 255) { DBGPRINT(RT_DEBUG_WARN, ("%s: DataLen > 255\n", __FUNCTION__)); return FALSE; } os_alloc_mem(NULL, (UCHAR **)&pBuf, 256); if (pBuf == NULL) { DBGPRINT(RT_DEBUG_WARN, ("%s: pBuf alloc fail !!\n", __FUNCTION__)); return FALSE; } pWpsMIC = pBuf + 200; pPeerWpsMIC = pBuf + 216; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { pEasyConfigInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { pEasyConfigInfo = &pAd->StaCfg.EasyConfigInfo; } #endif /* CONFIG_STA_SUPPORT */ NdisZeroMemory(pBuf, 256); while (Length > 0) { WSC_IE WscIE; NdisMoveMemory(&WscIE, Ptr, sizeof(WSC_IE)); /* Check for WSC IEs */ pWscIE = &WscIE; /* Check for device password ID, PBC = 0x0004 */ if (be2cpu16(pWscIE->Type) == 0x1049) { /* 4: 0x00 0x50 0xF2 0x04 4: 0x10 0x49 0x00 0x0x */ BufLen = DataLen - 4 - 4 - (INT)be2cpu16(pWscIE->Length); NdisMoveMemory(pBuf, pData + 4, BufLen); /* 7: 0x10 0x49 0x00 0x0x 0x00 0x0c 0x43 */ NdisMoveMemory(pPeerWpsMIC, Ptr + 7, LEN_KEY_DESC_MIC); WpsCalculateMIC(pAd, pBuf, BufLen, pEasyConfigInfo, pMacAddr, pWpsMIC); if (NdisEqualMemory(pPeerWpsMIC, pWpsMIC, LEN_KEY_DESC_MIC)) bStatus = TRUE; break; } /* Set the offset and look for PBC information */ /* Since Type and Length are both short type, we need to offset 4, not 2 */ Ptr += (be2cpu16(pWscIE->Length) + 4); Length -= (be2cpu16(pWscIE->Length) + 4); } os_free_mem(NULL, pBuf); return bStatus; } VOID WpsCalculateMIC( IN PRTMP_ADAPTER pAd, IN PUCHAR pBuf, IN INT BufLen, IN PEASY_CONFIG_INFO pEasyConfig, IN PUCHAR pMacAddr, OUT PUCHAR pMIC) { PUCHAR pDigest = NULL, pTemp = NULL; os_alloc_mem(NULL, &pTemp, 256); if(pTemp == NULL) { DBGPRINT(RT_DEBUG_WARN, ("%s: pTemp alloc fail !!\n", __FUNCTION__)); return; } os_alloc_mem(NULL, &pDigest, 80); if(pDigest == NULL) { os_free_mem(pAd, pTemp); DBGPRINT(RT_DEBUG_WARN, ("%s: pDigest alloc fail !!\n", __FUNCTION__)); return; } NdisZeroMemory(pTemp, 256); NdisMoveMemory(pTemp, pBuf, BufLen); NdisMoveMemory(pTemp + BufLen, pMacAddr, MAC_ADDR_LEN); RT_HMAC_SHA1(pEasyConfig->WpsPTK, LEN_PTK_KCK, pTemp, BufLen + MAC_ADDR_LEN, pDigest, SHA1_DIGEST_SIZE); NdisMoveMemory(pMIC, pDigest, LEN_KEY_DESC_MIC); os_free_mem(pAd, pTemp); os_free_mem(pAd, pDigest); } #endif /* EASY_CONFIG_SETUP */ #ifdef WAC_SUPPORT #if 0 This new auto provision proposal is from Samsung. WAC: Wi-Fi Auto Configuation #endif /* SAMSUNG DMC WAC Attribute IDs */ #define WAC_DEVICE_ADVERTISE_ID 0x00 #define WAC_AUTO_PROVISION_ID 0x01 #define WAC_STATUS_ID 0x02 #define WAC_DEVICE_INFORMATION_ID 0x03 /* Length of WAC Attributes */ #define SAMSUNG_OUI_LEN 4 #define DEVICE_ADVERTISE_ATTRIBUTE_LEN 3 #define DEVICE_INFORMATION_ATTRIBUTE_LEN 7 #define STATUS_ATTRIBUTE_LEN 3 #define AUTO_PROVISIONING_ATTRIBUTE_LEN 10 /* Setting of Device Information Fields */ #define THRESHOLD_OFFSET1 0 /* In current, not used */ #define THRESHOLD_OFFSET2 0 /* In current, not used */ #define INTERNAL_ANTENNA 0 #define EXTERNAL_ANTENNA 1 /* Device Types */ #define DEVICE_TYPE_TV 0 #define DEVICE_TYPE_TC 6 #define DEVICE_TYPE_BD 9 /* Device Models */ #define DEVICE_MODEL_TV 0 /* In current, not used */ /* RSSI Threshold */ #define RSSI_THRESHOLD -70 /* The Format of Device Information Attribute --------------------------------------------------------------------------------------------------------------------- | Field | Size(Octets) | Value | Description --------------------------------------------------------------------------------------------------------------------- | Attribute ID | 1 | 0x03 | Indicate Device Information attribute | Length | 1 | variable | Length of Device Type, Year of Production, and Device Model field in octets | Threshold Offset1 | 1 | variable | Offset for AP Tx Power, Signed value [dB] (-128 ~ + 127) | Threshold Offset2 | 1 | variable | Offset Antenna, etc., Signed value [dB] (-128 ~ +127) | Antenna Type | 1 | 0x00 / 0x01 | 0x00 = Internal, 0x01 = External | Device Type | 1 | variable | Device Type Code | Device Model | variable | variable | Model name of a device --------------------------------------------------------------------------------------------------------------------- The example of TV --------------------------------------------------------------------------------------------------------------------- | Field | Size(Octets) | Value | Description --------------------------------------------------------------------------------------------------------------------- | Attribute ID | 1 | 0x03 | Indicate Device Information attribute | Length | 1 | 0x05 | | Threshold Offset1 | 1 | 0x00 | | Threshold Offset2 | 1 | 0x00 | | Antenna Type | 1 | 0x01 | External | Device Type | 1 | 0x00 | | Device Model | 1 | 0x00 | Not used --------------------------------------------------------------------------------------------------------------------- */ UCHAR SAMSUNG_OUI[] = {0x00, 0x12, 0xFB}; UCHAR SAMSUNG_OUI_TYPE = 0x01; /* Device Advertise Attribute Field Size(Octets) Value ID 1 0 Length 1 1 WAC On/Off 1 0x01/0x00 WAC On(0x01), WAC Off(0x00) */ VOID WAC_GenDeviceAdvertiseAttr( IN BOOLEAN bEnableWAC, OUT PUCHAR pData, OUT PUCHAR pDataLen) { PUCHAR pIE_Data = NULL; os_alloc_mem(NULL, &pIE_Data, 128); if (pIE_Data == NULL) { DBGPRINT(RT_DEBUG_WARN, ("%s pIE_Data alloc fail !!\n", __FUNCTION__)); return; } if (pIE_Data) { /* Ralink Original NdisZeroMemory(pIE_Data, 128); pIE_Data[0] = 0xDD; pIE_Data[1] = 7; NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); pIE_Data[5] = SAMSUNG_OUI_TYPE; pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; pIE_Data[7] = 1; if (bEnableWAC) pIE_Data[8] = 1; else pIE_Data[8] = 0; *pDataLen = 9; NdisMoveMemory(pData, pIE_Data, *pDataLen); os_free_mem(NULL, pIE_Data); */ /* SAMSUNG DMC */ NdisZeroMemory(pIE_Data, 128); pIE_Data[0] = 0xDD; /* 14 = Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); pIE_Data[5] = SAMSUNG_OUI_TYPE; pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; pIE_Data[7] = 1; if (bEnableWAC) pIE_Data[8] = 1; else pIE_Data[8] = 0; pIE_Data[9] = WAC_DEVICE_INFORMATION_ID; /* 3 */ pIE_Data[10] = DEVICE_INFORMATION_ATTRIBUTE_LEN - 2; /* 5 */ pIE_Data[11] = THRESHOLD_OFFSET1; /* 0, Threshold Offset1 */ pIE_Data[12] = THRESHOLD_OFFSET2; /* 0, Threshold Offset2 */ pIE_Data[13] = EXTERNAL_ANTENNA; /* 1, Antenna Type => External */ pIE_Data[14] = DEVICE_TYPE_TV; /* 0, Device Type */ pIE_Data[15] = DEVICE_MODEL_TV; /* 0, Device Model */ /* 2 + Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; NdisMoveMemory(pData, pIE_Data, *pDataLen); os_free_mem(NULL, pIE_Data); } } BOOLEAN WAC_ParseAttr( IN UCHAR AttrID, IN PUCHAR pInData, IN UCHAR InDataLen, OUT PUCHAR pOutData, IN UCHAR OutDataLen) { UCHAR eid =0, eid_len = 0, *eid_data; UINT total_ie_len = 0; hex_dump("WAC_ParseAttr", pInData, InDataLen); eid = pInData[0]; eid_len = pInData[1]; total_ie_len = eid_len + 2; eid_data = pInData+2; /* get variable fields from payload and advance the pointer */ while((eid_data + eid_len) <= ((UCHAR*)pInData + InDataLen)) { if (eid == AttrID) { if (eid_len <= OutDataLen) { NdisMoveMemory(pOutData, eid_data, eid_len); } else { DBGPRINT(RT_DEBUG_WARN, ("%s: OutData is not enough to record data, eid_len = %d\n", __FUNCTION__, eid_len)); return FALSE; } return TRUE; } eid = pInData[total_ie_len]; eid_len = pInData[total_ie_len + 1]; eid_data = pInData + total_ie_len + 2; total_ie_len += (eid_len + 2); } return FALSE; } VOID WAC_AddDevAdvAttrIE( IN PRTMP_ADAPTER pAd, IN UCHAR apidx, INOUT PUCHAR pBuf, INOUT ULONG *pFrameLen) { PUCHAR pWAC_IE = NULL; UCHAR WAC_IELen = 0; ULONG TmpWACLen = 0; BOOLEAN bWAC_Enable = FALSE; #ifdef CONFIG_AP_SUPPORT if (pAd->OpMode == OPMODE_AP) bWAC_Enable = pAd->ApCfg.MBSSID[apidx].EasyConfigInfo.bEnableWAC; #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT if (pAd->OpMode == OPMODE_STA) bWAC_Enable = pAd->StaCfg.EasyConfigInfo.bEnableWAC; #endif /* CONFIG_STA_SUPPORT */ os_alloc_mem(NULL, &pWAC_IE, 128); if (pWAC_IE) { WAC_GenDeviceAdvertiseAttr(bWAC_Enable, pWAC_IE, &WAC_IELen); MakeOutgoingFrame(pBuf+(*pFrameLen), &TmpWACLen, WAC_IELen, pWAC_IE, END_OF_ARGS); (*pFrameLen) += TmpWACLen; os_free_mem(NULL, pWAC_IE); } } #define WAC_COPY_VENDOR_INFO(__p, __len, __psrc, __src_len, __rv) \ {\ if (__p)\ {\ os_free_mem(NULL, __p);\ (*__len) = 0;\ }\ os_alloc_mem(NULL, (UCHAR **) &__p, (__src_len + 2));\ if (__p)\ {\ (*__len) = (__src_len + 2);\ NdisMoveMemory((__p+2), __psrc, __src_len);\ *(__p) = 0xdd;\ *(__p+1) = __src_len;\ }\ else\ (*__rv) = FALSE;\ } VOID WAC_CopyVendorInfo( IN PRTMP_ADAPTER pAd, IN PWAC_REQUEST pWAC_Req, IN PEASY_CONFIG_INFO pEasyInfo) { switch(pWAC_Req->FrameType) { #ifdef CONFIG_STA_SUPPORT case WAC_CMD_FOR_PROBE_REQ: WAC_COPY_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeReq, &pEasyInfo->VendorInfoForProbeReqLen, pWAC_Req->pVendorInfo, pWAC_Req->VendorInfoLen, &pWAC_Req->RV); break; #endif /* CONFIG_STA_SUPPORT */ #ifdef CONFIG_AP_SUPPORT case WAC_CMD_FOR_PROBE_RSP: WAC_COPY_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeRsp, &pEasyInfo->VendorInfoForProbeRspLen, pWAC_Req->pVendorInfo, pWAC_Req->VendorInfoLen, &pWAC_Req->RV); break; case WAC_CMD_FOR_BEACON: WAC_COPY_VENDOR_INFO(pEasyInfo->pVendorInfoForBeacon, &pEasyInfo->VendorInfoForBeaconLen, pWAC_Req->pVendorInfo, pWAC_Req->VendorInfoLen, &pWAC_Req->RV); if (pWAC_Req->RV) { APMakeAllBssBeacon(pAd); APUpdateAllBeaconFrame(pAd); } break; #endif /* CONFIG_AP_SUPPORT */ default: pWAC_Req->RV = FALSE; DBGPRINT(RT_DEBUG_WARN, ("%s: Unknow FrameType = 0x%x\n", __FUNCTION__, pWAC_Req->FrameType)); break; } } #define WAC_FREE_VENDOR_INFO(__p, __len) \ {\ if (__p)\ { \ os_free_mem(NULL, __p);\ __p = NULL;\ (*__len) = 0;\ } \ } INT WAC_IoctlReq( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN RTMP_IOCTL_INPUT_STRUCT *wrq) { PWAC_REQUEST pWAC_Req = NULL; INT Status = NDIS_STATUS_SUCCESS; PEASY_CONFIG_INFO pEasyInfo = NULL; #ifdef CONFIG_AP_SUPPORT if (pAd->OpMode == OPMODE_AP) pEasyInfo = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo; #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT if (pAd->OpMode == OPMODE_STA) pEasyInfo = &pAd->StaCfg.EasyConfigInfo; #endif /* CONFIG_STA_SUPPORT */ os_alloc_mem(NULL, (UCHAR **)&pWAC_Req, sizeof(WAC_REQUEST)); if (pWAC_Req == NULL) { DBGPRINT(RT_DEBUG_WARN, ("%s: pWAC_Req alloc fail !!\n", __FUNCTION__)); return -ENOMEM; } if (pWAC_Req) { Status = copy_from_user(pWAC_Req, wrq->u.data.pointer, wrq->u.data.length); if (Status == NDIS_STATUS_SUCCESS) { pWAC_Req->RV = TRUE; if (pWAC_Req->bReqType) { /* set command */ switch (pWAC_Req->Command) { case WAC_CMD_ADD: WAC_CopyVendorInfo(pAd, pWAC_Req, pEasyInfo); break; case WAC_CMD_DEL: #ifdef CONFIG_STA_SUPPORT if (pWAC_Req->FrameType == WAC_CMD_FOR_PROBE_REQ) { WAC_FREE_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeReq, &pEasyInfo->VendorInfoForProbeReqLen); } #endif /* CONFIG_STA_SUPPORT */ #ifdef CONFIG_AP_SUPPORT if (pWAC_Req->FrameType == WAC_CMD_FOR_PROBE_RSP) { WAC_FREE_VENDOR_INFO(pEasyInfo->pVendorInfoForProbeRsp, &pEasyInfo->VendorInfoForProbeRspLen); } if (pWAC_Req->FrameType == WAC_CMD_FOR_BEACON) { WAC_FREE_VENDOR_INFO(pEasyInfo->pVendorInfoForBeacon, &pEasyInfo->VendorInfoForBeaconLen); APMakeAllBssBeacon(pAd); APUpdateAllBeaconFrame(pAd); } #endif /* CONFIG_AP_SUPPORT */ break; default: pWAC_Req->RV = FALSE; DBGPRINT(RT_DEBUG_WARN, ("%s: Unknow command = 0x%x\n", __FUNCTION__, pWAC_Req->Command)); break; } if (pWAC_Req->RV) { Status = copy_to_user(wrq->u.data.pointer, pWAC_Req, wrq->u.data.length); } else Status = -EFAULT; } else { /* get command */ pWAC_Req->CurrentStatus = pEasyInfo->CurrentStatus; Status = copy_to_user(wrq->u.data.pointer, pWAC_Req, wrq->u.data.length); } } os_free_mem(NULL, pWAC_Req); } return Status; } #ifdef CONFIG_AP_SUPPORT /* Device Advertise Attribute Field Size(Octets) Value ID 1 0 Length 1 1 Status Code 1 0 Accepted 1 Rejected because of invalid parameters 2 Rejected because a WAC AP is unable to accommodate request 3 Rejected because the RSS is not stronger than -25 dBm 4 ~ 255 Reserved */ /* Ralink Original VOID WAC_GenStatusAttr( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN CHAR PeerRssi, IN BOOLEAN bInvalidData, OUT PUCHAR pData, OUT PUCHAR pDataLen) */ /* SAMSUNG DMC */ VOID WAC_GenStatusAttr( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN CHAR PeerRssi, IN BOOLEAN bInvalidData, IN CHAR ThresholdOffset1, OUT PUCHAR pData, OUT PUCHAR pDataLen) { PUCHAR pIE_Data = NULL; if (pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC) { os_alloc_mem(NULL, &pIE_Data, 128); if (pIE_Data) { #if 0 /* Ralink Original */ NdisZeroMemory(pIE_Data, 128); pIE_Data[0] = 0xDD; pIE_Data[1] = 10; NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); pIE_Data[5] = SAMSUNG_OUI_TYPE; pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; pIE_Data[7] = 1; if (pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC) pIE_Data[8] = 1; else pIE_Data[8] = 0; pIE_Data[9] = WAC_STATUS_ID; pIE_Data[10] = 1; if (bInvalidData) { pIE_Data[11] = 1; pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_INVALID_PARAM; } else { #ifdef WSC_AP_SUPPORT PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; if (pWscCtrl->EapMsgRunning || (pWscCtrl->WscConfMode & WSC_REGISTRAR) == FALSE || pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC == FALSE) { DBGPRINT(RT_DEBUG_WARN, ("%s: EapMsgRunning = %d\n", __FUNCTION__, pWscCtrl->EapMsgRunning)); pIE_Data[11] = 2; pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_REJECT; } else #endif /* WSC_AP_SUPPORT */ { if (PeerRssi < -25) { DBGPRINT(RT_DEBUG_WARN, ("%s: PeerRssi = %d\n", __FUNCTION__, PeerRssi)); pIE_Data[11] = 3; pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_LOW_RSSI; } else pIE_Data[11] = 0; } } *pDataLen = 12; NdisMoveMemory(pData, pIE_Data, *pDataLen); os_free_mem(NULL, pIE_Data); #endif /* SAMSUNG DMC*/ NdisZeroMemory(pIE_Data, 128); pIE_Data[0] = 0xDD; /* 17 = Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr. & Status Attr. */ pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + STATUS_ATTRIBUTE_LEN; NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); pIE_Data[5] = SAMSUNG_OUI_TYPE; pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; pIE_Data[7] = 1; if (pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC) pIE_Data[8] = 1; else pIE_Data[8] = 0; pIE_Data[9] = WAC_DEVICE_INFORMATION_ID; /* 3 */ pIE_Data[10] = DEVICE_INFORMATION_ATTRIBUTE_LEN - 2; /* 5 */ pIE_Data[11] = THRESHOLD_OFFSET1; /* 0, Threshold Offset1 */ pIE_Data[12] = THRESHOLD_OFFSET2; /* 0, Threshold Offset2 */ pIE_Data[13] = EXTERNAL_ANTENNA; /* 1, Antenna Type => External */ pIE_Data[14] = DEVICE_TYPE_TV; /* 0, Device Type */ pIE_Data[15] = DEVICE_MODEL_TV; /* 0, Device Model */ pIE_Data[16] = WAC_STATUS_ID; pIE_Data[17] = 1; if (bInvalidData) { pIE_Data[18] = 1; pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_INVALID_PARAM; } else { #ifdef WSC_AP_SUPPORT PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; if (pWscCtrl->EapMsgRunning || (pWscCtrl->WscConfMode & WSC_REGISTRAR) == FALSE || pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC == FALSE) { DBGPRINT(RT_DEBUG_WARN, ("%s: EapMsgRunning = %d\n", __FUNCTION__, pWscCtrl->EapMsgRunning)); pIE_Data[18] = 2; pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_REJECT; } else #endif // WSC_AP_SUPPORT // { /* Ralink Original if (PeerRssi < -25) */ /* SAMSUNG DMC */ if (PeerRssi + ThresholdOffset1 < RSSI_THRESHOLD) { DBGPRINT(RT_DEBUG_WARN, ("%s: PeerRssi = %d\n", __FUNCTION__, PeerRssi)); pIE_Data[18] = 3; pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.CurrentStatus = OFC_FAILED_LOW_RSSI; } else pIE_Data[18] = 0; } } /* 19 = 2 + Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr., & Status Attr. */ *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + STATUS_ATTRIBUTE_LEN; NdisMoveMemory(pData, pIE_Data, *pDataLen); os_free_mem(NULL, pIE_Data); } } } /* Ralink Original BOOLEAN WAC_PeerProbeReqSanity( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN VOID *Msg, IN ULONG MsgLen, OUT BOOLEAN *pPeerWAC, OUT UCHAR *pParseResult) */ /* SAMSUNG DMC */ BOOLEAN WAC_PeerProbeReqSanity( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN VOID *Msg, IN ULONG MsgLen, OUT BOOLEAN *pPeerWAC, OUT CHAR *pThresholdOffset1, OUT UCHAR *pPeerDeviceType, OUT UCHAR *pParseResult) { PFRAME_802_11 Fr = (PFRAME_802_11)Msg; UCHAR *Ptr; UCHAR eid =0, eid_len = 0, *eid_data; UCHAR oui_type = 0; UINT total_ie_len = 0; BOOLEAN bWAC_Enable= FALSE; BOOLEAN bFoundSamsungWAC_OUI = FALSE; Ptr = Fr->Octet; eid = Ptr[0]; eid_len = Ptr[1]; total_ie_len = eid_len + 2; eid_data = Ptr+2; /* get variable fields from payload and advance the pointer */ while((eid_data + eid_len) <= ((UCHAR*)Fr + MsgLen)) { switch(eid) { case IE_VENDOR_SPECIFIC: if (eid_len <= 4) break; if (NdisEqualMemory(eid_data, SAMSUNG_OUI, 3)) { oui_type = eid_data[3]; DBGPRINT(RT_DEBUG_TRACE, ("%s: Samsung OUI Type = 0x%02X\n", __FUNCTION__, oui_type)); if (oui_type == SAMSUNG_OUI_TYPE) { CHAR device_info[5]; bFoundSamsungWAC_OUI = TRUE; if (WAC_ParseAttr(WAC_DEVICE_ADVERTISE_ID, eid_data+4, eid_len-4, &bWAC_Enable, 1)) { *pParseResult |= 0x01; if (bWAC_Enable) *pPeerWAC = TRUE; } if (bWAC_Enable) { /* SAMSUNG DMC */ DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC_DEVICE_INFO_ID Parsing...\n", __FUNCTION__)); if (WAC_ParseAttr(WAC_DEVICE_INFORMATION_ID, eid_data+4, eid_len-4, &device_info[0], 5)) { DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC Device Information: %d, %d, %d, %d, %d\n", __FUNCTION__, device_info[0], device_info[1], device_info[2], device_info[3], device_info[4])); *pThresholdOffset1 = (CHAR) device_info[0]; *pPeerDeviceType = (CHAR) device_info[3]; } else { DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC Device Information Parsing Error \n", __FUNCTION__)); } if (WAC_ParseAttr(WAC_AUTO_PROVISION_ID, eid_data+4, eid_len-4, pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WpsPinCode, 8)) { #ifdef WSC_INCLUDED PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; UCHAR PinStr[9]; #endif /* WSC_INCLUDED */ *pParseResult |= 0x02; #ifdef WSC_INCLUDED NdisMoveMemory(&PinStr[0], &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WpsPinCode[0], 8); PinStr[8] = '\0'; /* To make sure of doing WPS process with WPS Client by PIN method */ pWpsCtrl->WscMode = WSC_PIN_MODE; WscGetRegDataPIN(pAd, simple_strtol(PinStr, 0, 10), pWpsCtrl); DBGPRINT(RT_DEBUG_TRACE, ("%s: WscPinCode = %08u\n", __FUNCTION__, pWpsCtrl->WscPinCode)); #endif /* WSC_INCLUDED */ } } else *pPeerWAC = FALSE; } break; } } eid = Ptr[total_ie_len]; eid_len = Ptr[total_ie_len + 1]; eid_data = Ptr + total_ie_len + 2; total_ie_len += (eid_len + 2); } return bFoundSamsungWAC_OUI; } VOID WAC_MaintainPeerList( IN PLIST_HEADER pWscEnList) { PWSC_PEER_ENTRY pPeerEntry = NULL; RT_LIST_ENTRY *pListEntry = NULL, *pTempListEntry = NULL; ULONG now_time = 0; NdisGetSystemUpTime(&now_time); pListEntry = pWscEnList->pHead; pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; while (pPeerEntry != NULL) { if (RTMP_TIME_AFTER(now_time, pPeerEntry->receive_time + (5 * OS_HZ))) { pTempListEntry = pListEntry->pNext; delEntryList(pWscEnList, pListEntry); os_free_mem(NULL, pPeerEntry); pListEntry = pTempListEntry; } else pListEntry = pListEntry->pNext; pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; } return; } VOID WAC_CheckWACEntry( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry) { if (pEntry == NULL) { DBGPRINT(RT_DEBUG_TRACE, ("%s: pEntry is NULL!!\n", __FUNCTION__)); return; } if (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.bEnableWAC) { #ifdef WAC_QOS_PRIORITY PWSC_PEER_ENTRY pWACPeerEntry = NULL; PLIST_HEADER pWacFroceEnList = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.WAC_ForcePriorityList; #endif /* WAC_QOS_PRIORITY */ PLIST_HEADER pWscEnList = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.WAC_PeerList; RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.WAC_PeerListSemLock); WAC_MaintainPeerList(pWscEnList); if (WscFindPeerEntry(pWscEnList, pEntry->Addr)) { pEntry->bRaAutoWpsCapable = TRUE; pEntry->bSamsungAutoWpsCapable = TRUE; } RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.WAC_PeerListSemLock); #ifdef WAC_QOS_PRIORITY RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.WAC_ForcePriorityListSemLock); pWACPeerEntry = WscFindPeerEntry(pWacFroceEnList, pEntry->Addr); if (pWACPeerEntry) { STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; if ((pWACPeerEntry->device_type == WAC_DEVICE_TYPE_TV) || (pWACPeerEntry->device_type == WAC_DEVICE_TYPE_BD)) { tr_entry->bSamsungForcePriority = TRUE; } } RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].EasyConfigInfo.WAC_ForcePriorityListSemLock); #endif /* WAC_QOS_PRIORITY */ } } VOID WAC_PeerProbeReq( IN PRTMP_ADAPTER pAd, IN UCHAR ApIdx, IN MLME_QUEUE_ELEM *Elem, IN UCHAR *Addr2, INOUT UCHAR *pBuf, INOUT ULONG *pFrameLen) { PUCHAR pWAC_IE = NULL; UCHAR WAC_IELen = 0; ULONG TmpWACLen = 0; BOOLEAN bPeerWAC = FALSE; /* SAMSUNG DMC */ CHAR Threshold_Offset1 = 0; UCHAR ParseResult = 0; UCHAR PeerDeviceType = 0xff; if (WAC_PeerProbeReqSanity(pAd, ApIdx, Elem->Msg, Elem->MsgLen, &bPeerWAC, &Threshold_Offset1, &PeerDeviceType, &ParseResult)) { DBGPRINT(RT_DEBUG_TRACE, ("%s: Found Samsung WAC OUI - bPeerWAC = %d, ParseResult = 0x%x\n", __FUNCTION__, bPeerWAC, ParseResult)); os_alloc_mem(NULL, &pWAC_IE, 128); if (pWAC_IE) { ULONG WACTmpLen = 0; /* Peer is WAC enable */ if (((ParseResult & 0x01) == TRUE) && (bPeerWAC == TRUE)) { #ifdef WAC_QOS_PRIORITY PLIST_HEADER pWacForceList = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_ForcePriorityList; #endif /* WAC_QOS_PRIORITY */ PFRAME_802_11 p80211Frame = (PFRAME_802_11)Elem->Msg; CHAR PeerRssi = 0; PeerRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); if (MAC_ADDR_EQUAL(p80211Frame->Hdr.Addr3, pAd->ApCfg.MBSSID[ApIdx].Bssid) && (ParseResult & 0x02)) { #ifdef WSC_AP_SUPPORT PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; if (NdisEqualMemory(pWscCtrl->EntryAddr, ZERO_MAC_ADDR, MAC_ADDR_LEN) || NdisEqualMemory(pWscCtrl->EntryAddr, p80211Frame->Hdr.Addr2, MAC_ADDR_LEN)) { pWscCtrl->EapMsgRunning = FALSE; } #endif /* WSC_AP_SUPPORT */ /* Ralink Original WAC_GenStatusAttr(pAd, ApIdx, PeerRssi, FALSE, pWAC_IE, &WAC_IELen); */ /* SAMSUNG DMC */ WAC_GenStatusAttr(pAd, ApIdx, PeerRssi, FALSE, Threshold_Offset1, pWAC_IE, &WAC_IELen); if ((ParseResult & 0x02) && (pWAC_IE[11] == 0)) { PLIST_HEADER pWscEnList = &pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_PeerList; RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_PeerListSemLock); WscInsertPeerEntryByMAC(pWscEnList, Addr2); RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_PeerListSemLock); } } else WAC_GenDeviceAdvertiseAttr(pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC, pWAC_IE, &WAC_IELen); #ifdef WAC_QOS_PRIORITY RTMP_SEM_LOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_ForcePriorityListSemLock); WAC_InsertForcePriorityEntryByMAC(pWacForceList, Addr2, PeerDeviceType); RTMP_SEM_UNLOCK(&pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.WAC_ForcePriorityListSemLock); #endif /* WAC_QOS_PRIORITY */ } else WAC_GenDeviceAdvertiseAttr(pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC, pWAC_IE, &WAC_IELen); MakeOutgoingFrame(pBuf+(*pFrameLen), &WACTmpLen, WAC_IELen, pWAC_IE, END_OF_ARGS); (*pFrameLen) += WACTmpLen; os_free_mem(NULL, pWAC_IE); } } else { os_alloc_mem(NULL, &pWAC_IE, 128); if (pWAC_IE) { WAC_GenDeviceAdvertiseAttr(pAd->ApCfg.MBSSID[ApIdx].EasyConfigInfo.bEnableWAC, pWAC_IE, &WAC_IELen); MakeOutgoingFrame(pBuf+(*pFrameLen), &TmpWACLen, WAC_IELen, pWAC_IE, END_OF_ARGS); (*pFrameLen) += TmpWACLen; os_free_mem(NULL, pWAC_IE); } } } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT /* Device Advertise Attribute Field Size(Octets) Value ID 1 0 Length 1 1 WAC On/Off 1 0x01/0x00 WAC On(0x01), WAC Off(0x00) */ VOID WAC_GenUicastProbeReqAttr( IN BOOLEAN bEnableWAC, IN PUCHAR pPIN, OUT PUCHAR pData, OUT PUCHAR pDataLen) { PUCHAR pIE_Data = NULL; os_alloc_mem(NULL, &pIE_Data, 128); if (pIE_Data == NULL) { DBGPRINT(RT_DEBUG_WARN, ("%s: pIE_Data alloc fail !!\n", __FUNCTION__)); return; } if (pIE_Data) { /* Ralink Original NdisZeroMemory(pIE_Data, 128); pIE_Data[0] = 0xDD; if (bEnableWAC) pIE_Data[1] = 17; else pIE_Data[1] = 7; NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); pIE_Data[5] = SAMSUNG_OUI_TYPE; pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; pIE_Data[7] = 1; if (bEnableWAC) pIE_Data[8] = 1; else pIE_Data[8] = 0; if (bEnableWAC) { pIE_Data[9] = WAC_AUTO_PROVISION_ID; pIE_Data[10] = 8; NdisMoveMemory(pIE_Data+11, pPIN, 8); *pDataLen = 19; } else *pDataLen = 9; NdisMoveMemory(pData, pIE_Data, *pDataLen); os_free_mem(NULL, pIE_Data); */ /* SAMSUNG DMC */ NdisZeroMemory(pIE_Data, 128); pIE_Data[0] = 0xDD; if (bEnableWAC) /* 24 = Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr. & Auto Provisioning Attr. */ pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + AUTO_PROVISIONING_ATTRIBUTE_LEN; else /* 14 = Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ pIE_Data[1] = SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; NdisMoveMemory(pIE_Data+2, SAMSUNG_OUI, 3); pIE_Data[5] = SAMSUNG_OUI_TYPE; pIE_Data[6] = WAC_DEVICE_ADVERTISE_ID; pIE_Data[7] = 1; if (bEnableWAC) pIE_Data[8] = 1; else pIE_Data[8] = 0; pIE_Data[9] = WAC_DEVICE_INFORMATION_ID; /* 3 */ pIE_Data[10] = DEVICE_INFORMATION_ATTRIBUTE_LEN - 2; /* 5 */ pIE_Data[11] = THRESHOLD_OFFSET1; /* 0, Threshold Offset1 */ pIE_Data[12] = THRESHOLD_OFFSET2; /* 0, Threshold Offset2 */ pIE_Data[13] = EXTERNAL_ANTENNA; /* 1, Antenna Type => External */ pIE_Data[14] = DEVICE_TYPE_TV; /* 0, Device Type */ pIE_Data[15] = DEVICE_MODEL_TV; /* 0, Device Model */ if (bEnableWAC) { pIE_Data[16] = WAC_AUTO_PROVISION_ID; pIE_Data[17] = 8; NdisMoveMemory(pIE_Data+18, pPIN, 8); /* 26 = 2 + Leng. of Samsung OUI, Device Advertise Attr., Device Information Attr. & Auto Provisioning Attr. */ *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN + AUTO_PROVISIONING_ATTRIBUTE_LEN; } else { /* 16 = 2 + Leng. of Samsung OUI, Device Advertise Attr. & Device Information Attr. */ *pDataLen = 2 + SAMSUNG_OUI_LEN + DEVICE_ADVERTISE_ATTRIBUTE_LEN + DEVICE_INFORMATION_ATTRIBUTE_LEN; } NdisMoveMemory(pData, pIE_Data, *pDataLen); os_free_mem(NULL, pIE_Data); } } UCHAR WAC_SearchSamsungWACAP( IN PRTMP_ADAPTER pAd) { INT i = 0, Len = 0; BSS_ENTRY *pInBss; UCHAR Count = 0; PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; PBEACON_EID_STRUCT pEid = NULL; UCHAR *pData; UUID_BSSID_CH_INFO apCandiList[8]; UUID_BSSID_CH_INFO *pApCandEntry; /* Ralink Original CHAR RssiThreshold = -25; */ /* SAMSUNG DMC - does not check RSSI tightly in device driver. */ CHAR RssiThreshold = -100; NdisZeroMemory(&apCandiList[0], sizeof(apCandiList)); pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_FAILED_NO_WAC_AP; for (i = 0; i < pAd->ScanTab.BssNr; i++) { /* BSS entry for VarIE processing */ pInBss = (BSS_ENTRY *) &pAd->ScanTab.BssEntry[i]; if ((pInBss->WpsAP & 0x04) && (Count < 8)) { if (pInBss->Rssi >= RssiThreshold) { pApCandEntry = &apCandiList[Count]; NdisZeroMemory(pApCandEntry->Ssid, MAX_LEN_OF_SSID); NdisZeroMemory(pApCandEntry->Bssid, MAC_ADDR_LEN); NdisZeroMemory(pApCandEntry->MacAddr, MAC_ADDR_LEN); NdisZeroMemory(pApCandEntry->Uuid, 16); pApCandEntry->Channel = pInBss->Channel; pApCandEntry->SsidLen = pInBss->SsidLen; NdisMoveMemory(pApCandEntry->Ssid, pInBss->Ssid, pInBss->SsidLen); NdisMoveMemory(pApCandEntry->Bssid, pInBss->Bssid, MAC_ADDR_LEN); NdisMoveMemory(pApCandEntry->MacAddr, pInBss->MacAddr, MAC_ADDR_LEN); Count++; } else { pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_FAILED_LOW_RSSI; DBGPRINT(RT_DEBUG_WARN, ("%s: pInBss->Rssi = %d\n", __FUNCTION__, pInBss->Rssi)); } } } #if 0 if (Count != 1) { NdisZeroMemory(&pWpsCtrl->WscSsid, sizeof(NDIS_802_11_SSID)); NdisZeroMemory(pWpsCtrl->WscBssid, MAC_ADDR_LEN); NdisZeroMemory(pWpsCtrl->WscPeerMAC, MAC_ADDR_LEN); pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; } else #else if (Count != 0) #endif { NdisZeroMemory(&pWpsCtrl->WscSsid, sizeof(NDIS_802_11_SSID)); NdisZeroMemory(pWpsCtrl->WscBssid, MAC_ADDR_LEN); NdisZeroMemory(pWpsCtrl->WscPeerMAC, MAC_ADDR_LEN); pWpsCtrl->WscSsid.SsidLength = apCandiList[0].SsidLen; NdisMoveMemory(pWpsCtrl->WscSsid.Ssid, apCandiList[0].Ssid, apCandiList[0].SsidLen); NdisMoveMemory(pWpsCtrl->WscBssid, apCandiList[0].Bssid, MAC_ADDR_LEN); NdisMoveMemory(pWpsCtrl->WscPeerMAC, apCandiList[0].MacAddr, MAC_ADDR_LEN); pAd->MlmeAux.Channel = apCandiList[0].Channel; } return Count; } BOOLEAN WAC_FindWACAP( IN PRTMP_ADAPTER pAd) { UCHAR ApCount = 0; PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; ApCount = WAC_SearchSamsungWACAP(pAd); pAd->StaCfg.EasyConfigInfo.bWACAP = FALSE; if (ApCount != 0) { /* Update Reconnect Ssid, that user desired to connect. */ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pWpsCtrl->WscSsid.Ssid, pWpsCtrl->WscSsid.SsidLength); pAd->MlmeAux.AutoReconnectSsidLen = pWpsCtrl->WscSsid.SsidLength; pAd->bConfigChanged = TRUE; // Turn off WSC state matchine WscStop(pAd, #ifdef CONFIG_AP_SUPPORT FALSE, #endif /* CONFIG_AP_SUPPORT */ pWpsCtrl); // Set WSC state to WSC_STATE_INIT pWpsCtrl->WscState = WSC_STATE_INIT; pWpsCtrl->WscStatus = STATUS_WSC_SCAN_AP; // Init Registrar pair structures WscInitRegistrarPair(pAd, pWpsCtrl, BSS0); pAd->StaCfg.BssType = BSS_INFRA; pWpsCtrl->WscConfStatus = WSC_SCSTATE_UNCONFIGURED; pWpsCtrl->WscConfMode = WSC_ENROLLEE; pWpsCtrl->WscMode = 1; pAd->StaCfg.EasyConfigInfo.bDoAutoWps = TRUE; pAd->StaCfg.EasyConfigInfo.bWACAP = TRUE; pAd->StaCfg.EasyConfigInfo.CurrentStatus = OFC_PROCEED_SECOND_PHASE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_BSSID, MAC_ADDR_LEN, pWpsCtrl->WscBssid, 0); // call Mlme handler to execute it RTMP_MLME_HANDLER(pAd); return TRUE; } return FALSE; } #endif /* CONFIG_STA_SUPPORT */ #ifdef CONFIG_AP_SUPPORT #ifdef WAC_QOS_PRIORITY VOID WAC_InsertForcePriorityEntryByMAC( IN PLIST_HEADER pWscEnList, IN PUCHAR pMacAddr, IN UCHAR DeviceType) { PWSC_PEER_ENTRY pWscPeer = NULL; pWscPeer = WscFindPeerEntry(pWscEnList, pMacAddr); if (pWscPeer) { NdisGetSystemUpTime(&pWscPeer->receive_time); pWscPeer->device_type = DeviceType; } else { os_alloc_mem(NULL, &pWscPeer, WSC_PEER_ENTRY_SIZE); if (pWscPeer) { NdisZeroMemory(pWscPeer, WSC_PEER_ENTRY_SIZE); NdisMoveMemory(pWscPeer->mac_addr, pMacAddr, MAC_ADDR_LEN); NdisGetSystemUpTime(&pWscPeer->receive_time); pWscPeer->device_type = DeviceType; insertTailList(pWscEnList, (RT_LIST_ENTRY *)pWscPeer); } ASSERT(pWscPeer != NULL); } } #endif /* WAC_QOS_PRIORITY */ #endif /* CONFIG_AP_SUPPORT */ #endif /* WAC_SUPPORT */