s32 wilc_parse_network_info(u8 *msg_buffer, struct network_info **ret_network_info) { struct network_info *network_info = NULL; u8 msg_type = 0; u8 msg_id = 0; u16 msg_len = 0; u16 wid_id = (u16)WID_NIL; u16 wid_len = 0; u8 *wid_val = NULL; msg_type = msg_buffer[0]; if ('N' != msg_type) return -EFAULT; msg_id = msg_buffer[1]; msg_len = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); wid_id = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); wid_len = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); wid_val = &msg_buffer[8]; { u8 *msa = NULL; u16 rx_len = 0; u8 *tim_elm = NULL; u8 *ies = NULL; u16 ies_len = 0; u8 index = 0; u32 tsf_lo; u32 tsf_hi; network_info = kzalloc(sizeof(*network_info), GFP_KERNEL); if (!network_info) return -ENOMEM; network_info->rssi = wid_val[0]; msa = &wid_val[1]; rx_len = wid_len - 1; network_info->cap_info = get_cap_info(msa); network_info->tsf_lo = get_beacon_timestamp_lo(msa); tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); network_info->tsf_hi = tsf_lo | ((u64)tsf_hi << 32); get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->bssid); network_info->ch = get_current_channel_802_11n(msa, rx_len + FCS_LEN); index = MAC_HDR_LEN + TIME_STAMP_LEN; network_info->beacon_period = get_beacon_period(msa + index); index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); if (tim_elm) network_info->dtim_period = tim_elm[3]; ies = &msa[TAG_PARAM_OFFSET]; ies_len = rx_len - TAG_PARAM_OFFSET; if (ies_len > 0) { network_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); if (!network_info->ies) { kfree(network_info); return -ENOMEM; } } network_info->ies_len = ies_len; } *ret_network_info = network_info; return 0; }
void process_p2p_noa_attr(UWORD8 *attr_start_ptr, UWORD8 ie_len) { UWORD8 num = 0; UWORD8 noa_index = 0; UWORD16 index = 0; UWORD16 attr_len = 0; UWORD8 *noa = 0; UWORD8 curr_ct_window = mget_p2p_CTW(); BOOL_T noa_update_flag = BFALSE; BOOL_T ctwin_update_flag = BFALSE; noa = p2p_get_attr(NOTICE_OF_ABSENCE, attr_start_ptr, ie_len, &attr_len); /* If no NOA attribute is present then reset the CT Window and schedules */ if(NULL == noa) { if(get_num_noa_sched() != 0) /* NOA schedule was present earlier */ noa_update_flag = BTRUE; if(curr_ct_window != 0) /* Non-zero CT Window was present earlier */ ctwin_update_flag = BTRUE; mset_p2p_CTW(0); reset_noa_dscr(); update_machw_noa_attr(ctwin_update_flag, noa_update_flag); return; } /* Extract the NOA attrbiute Index - will be checked later. Process */ /* CT Window first since the index will not be updated even if CT Window */ /* is changed. */ noa_index = noa[index++]; /* Update the CT Window if the Opportunistic PS bit is set */ if((noa[index] & BIT7) == 0) { mset_p2p_CTW(0); /* No OppPS */ } else { mset_p2p_CTW(noa[index] & 0x7F); } if(curr_ct_window != mget_p2p_CTW()) /* CT Window has been modified */ ctwin_update_flag = BTRUE; index++; /* Skip the CTWindow and OppPS Parameters Field */ /* Check if the NOA attribute has changed by comparing the Index (which */ /* indicates the instance of the NOA schedule) with the saved global NOA */ /* index. If it has not changed, return without doing anything. */ if(noa_index != g_noa_index) { /* Update the global NOA instance index with the received instance value */ g_noa_index = noa_index; /* NOA schedule has been modified */ noa_update_flag = BTRUE; /* Reset the NOA descriptors */ reset_noa_dscr(); /* Process the attribute till the end is reached */ while(index < attr_len) { g_noa_dscr[num].cnt_typ = noa[index++]; g_noa_dscr[num].duration = MAKE_WORD32(MAKE_WORD16(noa[index], noa[index + 1]), MAKE_WORD16(noa[index + 2], noa[index + 3])); index += 4; g_noa_dscr[num].interval = MAKE_WORD32(MAKE_WORD16(noa[index], noa[index + 1]), MAKE_WORD16(noa[index + 2], noa[index + 3])); index += 4; g_noa_dscr[num].start_time = MAKE_WORD32(MAKE_WORD16(noa[index], noa[index + 1]), MAKE_WORD16(noa[index + 2], noa[index + 3])); index += 4; /* Increment the number of NOA schedules extracted */ num++; /* NUM_NOA_DSCR NOA schedules are processed, Remaining are ignored */ if (num >= NUM_NOA_DSCR) break; } /* Update the number of NOA schedules */ set_num_noa_sched(num); } /* Update MAC HW with the NOA attribute values */ update_machw_noa_attr(ctwin_update_flag, noa_update_flag); }
void update_11n_params_sta(UWORD8 *msa, UWORD16 offset, UWORD16 rx_len, sta_entry_t *entry) { UWORD16 index = offset; UWORD16 info_elem = 0; UWORD8 mcs_bmp_index; UWORD16 cap_info = 0; ht_struct_t *ht_hdl = &(entry->ht_hdl); ba_struct_t *ba_hdl = &(entry->ba_hdl); UWORD8 is_ht_present = 0; TROUT_FUNC_ENTER; /* Update the capability information */ cap_info = get_cap_info(msa); /* Update the Block ACK capability */ update_ba_cap(ba_hdl, cap_info); while(index < (rx_len - FCS_LEN)) { /* Search for HT Capabilities Element */ if(msa[index] == IHTCAP) { UWORD16 ofst = index; is_ht_present = 1; /* Presence of HT Capability Element implies the station is HT */ /* capable */ ht_hdl->ht_capable = 1; ofst += IE_HDR_LEN; /* Parse HT Capabilities Info Field */ info_elem = MAKE_WORD16(msa[ofst], msa[ofst + 1]); /* LDPC Coding Capability */ ht_hdl->ldpc_cod_cap = (info_elem & BIT0); /* Channel Width Element is initialized by the channel width */ /* supported field. This will subsequently be overidden by the */ /* STA-Channel Width field of the HT-Operation Element */ ht_hdl->chan_width = ((info_elem & BIT1) >> 1); /* Extract the SMPS mode B2 & B3 */ { UWORD8 smps = (info_elem & 0x000C); if(smps == STATIC_SMPS) ht_hdl->smps_mode = STATIC_MODE; else if(smps == DYNAMIC_SMPS) ht_hdl->smps_mode = DYNAMIC_MODE; else if(smps == SM_ENABLED) ht_hdl->smps_mode = MIMO_MODE; } /* Extract support for reception of Greenfield packets */ ht_hdl->greenfield = ((info_elem & BIT4) >> 4); /* Extract Short-GI support for reception of 20MHz packets */ ht_hdl->short_gi_20 = ((info_elem & BIT5) >> 5); /* Extract Short-GI support for reception of 40MHz packets */ ht_hdl->short_gi_40 = ((info_elem & BIT6) >> 6); /* Extract STBC reception capability */ ht_hdl->rx_stbc = ((info_elem & 0x30) >> 8); /* Extract AMSDU max-size field */ if(0 == (info_elem & BIT11)) ht_hdl->sta_amsdu_maxsize = 3839; else ht_hdl->sta_amsdu_maxsize = 7935; /* DSSS/CCK Mode in 40 MHz */ ht_hdl->dsss_cck_40mhz = ((info_elem & BIT12) >> 12); /* Extract support for L-SIG TXOP Protection */ ht_hdl->lsig_txop_prot = ((info_elem & BIT15) >> 15); ofst += HT_CAPINFO_FIELD_LEN; /* Parse A-MPDU Parameters Field */ /* Extract the Maximum Rx A-MPDU factor (B1 - B0) */ ht_hdl->max_rx_ampdu_factor = (msa[ofst] & 0x03); /* Extract the Minimum MPDU Start Spacing (B2 - B4) */ ht_hdl->min_mpdu_start_spacing = (msa[ofst] >> 2) & 0x07; ofst += AMPDU_PARAM_LEN; /* Parse Supported MCS Set Field */ /* AND the Rx MCS bitmask with supported Tx MCS bitmask */ /* and reset the last 3 bits in the last */ /* byte since the bitmask is 77 bits */ for(mcs_bmp_index = 0; mcs_bmp_index < MCS_BITMASK_LEN; mcs_bmp_index++) { ht_hdl->rx_mcs_bitmask[mcs_bmp_index] = mget_SupportedMCSTxValue().mcs_bmp[mcs_bmp_index] & (*(UWORD8 *)(msa + ofst + mcs_bmp_index)); } ht_hdl->rx_mcs_bitmask[MCS_BITMASK_LEN - 1] &= 0x1F; ofst += MCS_SET_FIELD_LEN; /* Parse HT Extended Capabilities Info Field */ info_elem = MAKE_WORD16(msa[ofst], msa[ofst + 1]); /* Extract HTC support Information */ if((info_elem & BIT10) != 0) ht_hdl->htc_support = 1; ofst += HT_EXTCAP_FIELD_LEN; /* Parse Tx Beamforming Field */ ofst += TX_BF_FIELD_LEN; /* Parse ASEL Capabilities Field */ ofst += ASEL_FIELD_LEN; } /* Increment index by length information & tag header */ index += msa[index + 1] + IE_HDR_LEN; }
/** * @brief parses the received 'N' message * @details * @param[in] pu8MsgBuffer The message to be parsed * @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info * @return Error code indicating success/failure * @note * @author mabubakr * @date 1 Mar 2012 * @version 1.0 */ s32 parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) { tstrNetworkInfo *pstrNetworkInfo = NULL; u8 u8MsgType = 0; u8 u8MsgID = 0; u16 u16MsgLen = 0; u16 u16WidID = (u16)WID_NIL; u16 u16WidLen = 0; u8 *pu8WidVal = NULL; u8MsgType = pu8MsgBuffer[0]; /* Check whether the received message type is 'N' */ if ('N' != u8MsgType) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } /* Extract message ID */ u8MsgID = pu8MsgBuffer[1]; /* Extract message Length */ u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]); /* Extract WID ID */ u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]); /* Extract WID Length */ u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]); /* Assign a pointer to the WID value */ pu8WidVal = &pu8MsgBuffer[8]; /* parse the WID value of the WID "WID_NEWORK_INFO" */ { u8 *pu8msa = NULL; u16 u16RxLen = 0; u8 *pu8TimElm = NULL; u8 *pu8IEs = NULL; u16 u16IEsLen = 0; u8 u8index = 0; u32 u32Tsf_Lo; u32 u32Tsf_Hi; pstrNetworkInfo = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); if (!pstrNetworkInfo) return -ENOMEM; pstrNetworkInfo->s8rssi = pu8WidVal[0]; /* Assign a pointer to msa "Mac Header Start Address" */ pu8msa = &pu8WidVal[1]; u16RxLen = u16WidLen - 1; /* parse msa*/ /* Get the cap_info */ pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); /* Get time-stamp [Low only 32 bit] */ pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); /* Get full time-stamp [Low and High 64 bit] */ u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); /* Get SSID */ get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen); /* Get BSSID */ get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); /* * Extract current channel information from * the beacon/probe response frame */ pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, u16RxLen + FCS_LEN); /* Get beacon period */ u8index = MAC_HDR_LEN + TIME_STAMP_LEN; pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; /* Get DTIM Period */ pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index); if (pu8TimElm != NULL) pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (u16IEsLen > 0) { pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL); if (!pstrNetworkInfo->pu8IEs) return -ENOMEM; } pstrNetworkInfo->u16IEsLen = u16IEsLen; } *ppstrNetworkInfo = pstrNetworkInfo; return 0; }