u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code) { u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 }; u32 len=0, p2pielen = 0; // P2P OUI p2pielen = 0; p2pie[ p2pielen++ ] = 0x50; p2pie[ p2pielen++ ] = 0x6F; p2pie[ p2pielen++ ] = 0x9A; p2pie[ p2pielen++ ] = 0x09; // WFA P2P v1.0 // According to the P2P Specification, the Association response frame should contain 2 P2P attributes // 1. Status // 2. Extended Listen Timing (optional) // Status ATTR p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code); // Extended Listen Timing ATTR // Type: // Length: // Value: pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len); return len; }
u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) { u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 }; u16 capability=0; u32 len=0, p2pielen = 0; // P2P OUI p2pielen = 0; p2pie[ p2pielen++ ] = 0x50; p2pie[ p2pielen++ ] = 0x6F; p2pie[ p2pielen++ ] = 0x9A; p2pie[ p2pielen++ ] = 0x09; // WFA P2P v1.0 // According to the P2P Specification, the beacon frame should contain 3 P2P attributes // 1. P2P Capability // 2. P2P Device ID // 3. Notice of Absence ( NOA ) // P2P Capability ATTR // Type: // Length: // Value: // Device Capability Bitmap, 1 byte // Be able to participate in additional P2P Groups and // support the P2P Invitation Procedure // Group Capability Bitmap, 1 byte capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY; capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8); if(pwdinfo->p2p_state == P2P_STATE_PROVISIONING_ING) capability |= (P2P_GRPCAP_GROUP_FORMATION<<8); capability = cpu_to_le16(capability); p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability); // P2P Device ID ATTR p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr); // Notice of Absence ATTR // Type: // Length: // Value: //go_add_noa_attr(pwdinfo); pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len); return len; }
inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt) { u8 ie_data[3]; ie_data[0] = ch_switch_mode; ie_data[1] = new_ch; ie_data[2] = ch_switch_cnt; return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); }
inline uint8_t *rtw_set_ie_ch_switch(uint8_t *buf, uint32_t *buf_len, uint8_t ch_switch_mode, uint8_t new_ch, uint8_t ch_switch_cnt) { uint8_t ie_data[3]; ie_data[0] = ch_switch_mode; ie_data[1] = new_ch; ie_data[2] = ch_switch_cnt; return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); }
inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 flags, u16 reason, u16 precedence) { u8 ie_data[6]; ie_data[0] = ttl; ie_data[1] = flags; RTW_PUT_LE16((u8*)&ie_data[2], reason); RTW_PUT_LE16((u8*)&ie_data[4], precedence); return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len); }
inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 flags, u16 reason, u16 precedence) { u8 ie_data[6]; ie_data[0] = ttl; ie_data[1] = flags; *(u16 *)(ie_data+2) = cpu_to_le16(reason); *(u16 *)(ie_data+4) = cpu_to_le16(precedence); return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len); }
inline uint8_t *rtw_set_ie_mesh_ch_switch_parm(uint8_t *buf, uint32_t *buf_len, uint8_t ttl, uint8_t flags, u16 reason, u16 precedence) { uint8_t ie_data[6]; ie_data[0] = ttl; ie_data[1] = flags; RTW_PUT_LE16((uint8_t *)&ie_data[2], reason); RTW_PUT_LE16((uint8_t *)&ie_data[4], precedence); return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len); }
inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset) { return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len); }
void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength) { struct rtw_ieee80211_hdr *pwlanhdr; u16 *fctrl; u32 rate_len, pktlen; struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; //DBG_871X("%s\n", __FUNCTION__); pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); SetFrameSubType(pframe, WIFI_BEACON); pframe += sizeof(struct rtw_ieee80211_hdr_3addr); pktlen = sizeof (struct rtw_ieee80211_hdr_3addr); //timestamp will be inserted by hardware pframe += 8; pktlen += 8; // beacon interval: 2 bytes _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); pframe += 2; pktlen += 2; // capability info: 2 bytes _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); pframe += 2; pktlen += 2; if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { DBG_871X("ie len=%u\n", cur_network->IELength); pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs); _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen); goto _ConstructBeacon; } //below for ad-hoc mode // SSID pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); // supported rates... rate_len = rtw_get_rateset_len(cur_network->SupportedRates); pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen); // DS parameter set pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen); if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { u32 ATIMWindow; // IBSS Parameter Set... //ATIMWindow = cur->Configuration.ATIMWindow; ATIMWindow = 0; pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen); } //todo: ERP IE // EXTERNDED SUPPORTED RATE if (rate_len > 8) { pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen); } //todo:HT for adhoc _ConstructBeacon: if ((pktlen + TXDESC_SIZE) > 512) { DBG_871X("beacon frame too large\n"); return; } *pLength = pktlen; //DBG_871X("%s bcn_sz=%u\n", __FUNCTION__, pktlen); }
inline uint8_t *rtw_set_ie_secondary_ch_offset(uint8_t *buf, uint32_t *buf_len, uint8_t secondary_ch_offset) { return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len); }
u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) { u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 }; u32 len=0, p2pielen = 0; // P2P OUI p2pielen = 0; p2pie[ p2pielen++ ] = 0x50; p2pie[ p2pielen++ ] = 0x6F; p2pie[ p2pielen++ ] = 0x9A; p2pie[ p2pielen++ ] = 0x09; // WFA P2P v1.0 // Commented by Albert 20100907 // According to the P2P Specification, the probe response frame should contain 5 P2P attributes // 1. P2P Capability // 2. Extended Listen Timing // 3. Notice of Absence ( NOA ) ( Only GO needs this ) // 4. Device Info // 5. Group Info ( Only GO need this ) // P2P Capability ATTR // Type: p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY; // Length: //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); RTW_PUT_LE16(p2pie + p2pielen, 0x0002); p2pielen += 2; // Value: // Device Capability Bitmap, 1 byte // Be able to participate in additional P2P Groups and // support the P2P Invitation Procedure p2pie[ p2pielen++ ] = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY; // Group Capability Bitmap, 1 byte if(pwdinfo->role == P2P_ROLE_GO) { p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS); if(pwdinfo->p2p_state == P2P_STATE_PROVISIONING_ING) p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION; p2pielen++; } else if ( pwdinfo->role == P2P_ROLE_DEVICE ) { // Group Capability Bitmap, 1 byte p2pie[ p2pielen++ ] = 0x00; } // Extended Listen Timing ATTR // Type: p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING; // Length: //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 ); RTW_PUT_LE16(p2pie + p2pielen, 0x0004); p2pielen += 2; // Value: // Availability Period //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF); p2pielen += 2; // Availability Interval //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF); p2pielen += 2; // Notice of Absence ATTR // Type: // Length: // Value: if(pwdinfo->role == P2P_ROLE_GO) { //go_add_noa_attr(pwdinfo); } // Device Info ATTR // Type: p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO; // Length: // 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) // + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len); p2pielen += 2; // Value: // P2P Device Address _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN ); p2pielen += ETH_ALEN; // Config Method // This field should be big endian. Noted by P2P specification. //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm ); RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm); p2pielen += 2; // Primary Device Type // Category ID //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_RTK_WIDI ); RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_RTK_WIDI); p2pielen += 2; // OUI //*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); p2pielen += 4; // Sub Category ID //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_RTK_DMP ); RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_RTK_DMP); p2pielen += 2; // Number of Secondary Device Types p2pie[ p2pielen++ ] = 0x00; // No Secondary Device Type List // Device Name // Type: //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME); p2pielen += 2; // Length: //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len); p2pielen += 2; // Value: _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len ); p2pielen += pwdinfo->device_name_len; // Group Info ATTR // Type: // Length: // Value: if(pwdinfo->role == P2P_ROLE_GO) { p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen); } pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len); return len; }
static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken) { struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; struct ieee80211_hdr *pwlanhdr; unsigned short *fctrl; _adapter *padapter = pwdinfo->padapter; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); unsigned char category = WLAN_CATEGORY_P2P;//P2P action frame u32 p2poui = cpu_to_be32(P2POUI); u8 oui_subtype = P2P_PRESENCE_RESPONSE; u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 }; u8 noa_attr_content[32] = { 0x00 }; u32 p2pielen = 0; DBG_871X("[%s]\n", __FUNCTION__); if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) { return; } //update attribute pattrib = &pmgntframe->attrib; update_mgntframe_attrib(padapter, pattrib); _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; pwlanhdr = (struct ieee80211_hdr *)pframe; fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); _rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN); _rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); //Build P2P action frame header pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen)); //Add P2P IE header // P2P OUI p2pielen = 0; p2pie[ p2pielen++ ] = 0x50; p2pie[ p2pielen++ ] = 0x6F; p2pie[ p2pielen++ ] = 0x9A; p2pie[ p2pielen++ ] = 0x09; // WFA P2P v1.0 //Add Status attribute in P2P IE p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status); //Add NoA attribute in P2P IE noa_attr_content[0] = 0x1;//index noa_attr_content[1] = 0x0;//CTWindow and OppPS Parameters //todo: Notice of Absence Descriptor(s) p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content); pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen)); pattrib->last_txcmdsz = pattrib->pktlen; dump_mgntframe(padapter, pmgntframe); }
static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method) { _adapter *padapter = pwdinfo->padapter; unsigned char category = WLAN_CATEGORY_PUBLIC; u8 action = P2P_PUB_ACTION_ACTION; u8 dialogToken = frame_body[7]; // The Dialog Token of provisioning discovery request frame. u32 p2poui = cpu_to_be32(P2POUI); u8 oui_subtype = P2P_PROVISION_DISC_RESP; u8 wpsie[ 100 ] = { 0x00 }; u8 wpsielen = 0; struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; struct ieee80211_hdr *pwlanhdr; unsigned short *fctrl; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) { return; } //update attribute pattrib = &pmgntframe->attrib; update_mgntframe_attrib(padapter, pattrib); _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; pwlanhdr = (struct ieee80211_hdr *)pframe; fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen)); wpsielen = 0; // WPS OUI //*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI ); RTW_PUT_BE32(wpsie, WPSOUI); wpsielen += 4; #if 0 // WPS version // Type: *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 ); wpsielen += 2; // Length: *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 ); wpsielen += 2; // Value: wpsie[wpsielen++] = WPS_VERSION_1; // Version 1.0 #endif // Config Method // Type: //*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD ); RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD); wpsielen += 2; // Length: //*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 ); RTW_PUT_BE16(wpsie + wpsielen, 0x0002); wpsielen += 2; // Value: //*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method ); RTW_PUT_BE16(wpsie + wpsielen, config_method); wpsielen += 2; pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen ); pattrib->last_txcmdsz = pattrib->pktlen; dump_mgntframe(padapter, pmgntframe); return; }
static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken) { struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; struct ieee80211_hdr *pwlanhdr; unsigned short *fctrl; _adapter *padapter = pwdinfo->padapter; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); unsigned char category = WLAN_CATEGORY_PUBLIC; u8 action = P2P_PUB_ACTION_ACTION; u32 p2poui = cpu_to_be32(P2POUI); u8 oui_subtype = P2P_DEVDISC_RESP; u8 p2pie[8] = { 0x00 }; u32 p2pielen = 0; DBG_871X("[%s]\n", __FUNCTION__); if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) { return; } //update attribute pattrib = &pmgntframe->attrib; update_mgntframe_attrib(padapter, pattrib); _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; pwlanhdr = (struct ieee80211_hdr *)pframe; fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); _rtw_memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN); _rtw_memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); //Build P2P public action frame header pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen)); //Build P2P IE // P2P OUI p2pielen = 0; p2pie[ p2pielen++ ] = 0x50; p2pie[ p2pielen++ ] = 0x6F; p2pie[ p2pielen++ ] = 0x9A; p2pie[ p2pielen++ ] = 0x09; // WFA P2P v1.0 // P2P_ATTR_STATUS p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status); pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen); pattrib->last_txcmdsz = pattrib->pktlen; dump_mgntframe(padapter, pmgntframe); }
int rtw_generate_ie(struct registry_priv *pregistrypriv) { u8 wireless_mode; int sz = 0, rateLen; WLAN_BSSID_EX* pdev_network = &pregistrypriv->dev_network; u8* ie = pdev_network->IEs; _func_enter_; //timestamp will be inserted by hardware sz += 8; ie += sz; //beacon interval : 2bytes *(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);//BCN_INTERVAL; sz += 2; ie += 2; //capability info *(u16*)ie = 0; *(u16*)ie |= cpu_to_le16(cap_IBSS); if(pregistrypriv->preamble == PREAMBLE_SHORT) *(u16*)ie |= cpu_to_le16(cap_ShortPremble); if (pdev_network->Privacy) *(u16*)ie |= cpu_to_le16(cap_Privacy); sz += 2; ie += 2; //SSID ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); //supported rates if(pregistrypriv->wireless_mode == WIRELESS_11ABGN) { if(pdev_network->Configuration.DSConfig > 14) wireless_mode = WIRELESS_11A_5N; else wireless_mode = WIRELESS_11BG_24N; } else { wireless_mode = pregistrypriv->wireless_mode; } rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ; rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); if (rateLen > 8) { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz); //ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); } else { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz); } //DS parameter set ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); //IBSS Parameter Set ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); if (rateLen > 8) { ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); } #ifdef CONFIG_80211N_HT //HT Cap. if(((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N)) && (pregistrypriv->ht_enable==_TRUE)) { //todo: } #endif //CONFIG_80211N_HT //pdev_network->IELength = sz; //update IELength _func_exit_; //return _SUCCESS; return sz; }
int rtw_generate_ie(struct registry_priv *pregistrypriv) { u8 wireless_mode; int sz = 0, rateLen; struct wlan_bssid_ex*pdev_network = &pregistrypriv->dev_network; u8*ie = pdev_network->IEs; /* timestamp will be inserted by hardware */ sz += 8; ie += sz; /* beacon interval : 2bytes */ *(__le16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */ sz += 2; ie += 2; /* capability info */ *(u16*)ie = 0; *(__le16*)ie |= cpu_to_le16(cap_IBSS); if (pregistrypriv->preamble == PREAMBLE_SHORT) *(__le16*)ie |= cpu_to_le16(cap_ShortPremble); if (pdev_network->Privacy) *(__le16*)ie |= cpu_to_le16(cap_Privacy); sz += 2; ie += 2; /* SSID */ ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); /* supported rates */ if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { if (pdev_network->Configuration.DSConfig > 14) wireless_mode = WIRELESS_11A_5N; else wireless_mode = WIRELESS_11BG_24N; } else { wireless_mode = pregistrypriv->wireless_mode; } rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ; rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); if (rateLen > 8) { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz); /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ } else { ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz); } /* DS parameter set */ ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); /* IBSS Parameter Set */ ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); if (rateLen > 8) { ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); } /* HT Cap. */ if (((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N)) && (pregistrypriv->ht_enable ==true)) { /* todo: */ } /* pdev_network->IELength = sz; update IELength */ /* return _SUCCESS; */ return sz; }
u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr ) { u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 }; u32 len=0, p2pielen = 0; // P2P OUI p2pielen = 0; p2pie[ p2pielen++ ] = 0x50; p2pie[ p2pielen++ ] = 0x6F; p2pie[ p2pielen++ ] = 0x9A; p2pie[ p2pielen++ ] = 0x09; // WFA P2P v1.0 // Commented by Albert 20110301 // According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes // 1. P2P Capability // 2. Device Info // 3. Group ID ( When joining an operating P2P Group ) // P2P Capability ATTR // Type: p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY; // Length: //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); RTW_PUT_LE16(p2pie + p2pielen, 0x0002); p2pielen += 2; // Value: // Device Capability Bitmap, 1 byte // Be able to participate in additional P2P Groups and // support the P2P Invitation Procedure p2pie[ p2pielen++ ] = P2P_DEVCAP_INVITATION_PROC; // Group Capability Bitmap, 1 byte p2pie[ p2pielen++ ] = 0x00; // Device Info ATTR // Type: p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO; // Length: // 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) // + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len); p2pielen += 2; // Value: // P2P Device Address _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN ); p2pielen += ETH_ALEN; // Config Method // This field should be big endian. Noted by P2P specification. if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC ) { //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC ); RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC); } else { //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY ); RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY); } p2pielen += 2; // Primary Device Type // Category ID //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_RTK_WIDI ); RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_RTK_WIDI); p2pielen += 2; // OUI //*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); p2pielen += 4; // Sub Category ID //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_RTK_DMP ); RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_RTK_DMP); p2pielen += 2; // Number of Secondary Device Types p2pie[ p2pielen++ ] = 0x00; // No Secondary Device Type List // Device Name // Type: //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME); p2pielen += 2; // Length: //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len); p2pielen += 2; // Value: _rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len ); p2pielen += pwdinfo->device_name_len; if ( pwdinfo->role == P2P_ROLE_CLIENT ) { // Added by Albert 2011/05/19 // In this case, the pdev_raddr is the device address of the group owner. // P2P Group ID ATTR // Type: p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID; // Length: //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + ussidlen ); RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen); p2pielen += 2; // Value: _rtw_memcpy( p2pie + p2pielen, pdev_raddr, ETH_ALEN ); p2pielen += ETH_ALEN; _rtw_memcpy( p2pie + p2pielen, pssid, ussidlen ); p2pielen += ussidlen; } pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len); return len; }