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;
}
Exemplo n.º 2
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;
}