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;
    }
Esempio n. 4
0
/**
 *  @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;
}