3 * @file coreconfigurator.c
6 * @sa coreconfigurator.h
12 /*****************************************************************************/
14 /*****************************************************************************/
15 #include "coreconfigurator.h"
16 #include <linux/errno.h>
17 /*****************************************************************************/
19 /*****************************************************************************/
20 #define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \
21 BEACON_INTERVAL_LEN + CAP_INFO_LEN)
23 /*****************************************************************************/
25 /*****************************************************************************/
28 /*****************************************************************************/
29 /* Type Definitions */
30 /*****************************************************************************/
32 /* Basic Frame Type Codes (2-bit) */
34 FRAME_TYPE_CONTROL = 0x04,
35 FRAME_TYPE_DATA = 0x08,
36 FRAME_TYPE_MANAGEMENT = 0x00,
37 FRAME_TYPE_RESERVED = 0x0C,
38 FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF
41 /* Frame Type and Subtype Codes (6-bit) */
72 QOS_DATA_POLL_ACK = 0xB8,
73 QOS_NULL_FRAME = 0xC8,
75 QOS_CFPOLL_ACK = 0xF8,
78 FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF
81 /* Element ID of various Information Elements */
83 ISSID = 0, /* Service Set Identifier */
84 ISUPRATES = 1, /* Supported Rates */
85 IFHPARMS = 2, /* FH parameter set */
86 IDSPARMS = 3, /* DS parameter set */
87 ICFPARMS = 4, /* CF parameter set */
88 ITIM = 5, /* Traffic Information Map */
89 IIBPARMS = 6, /* IBSS parameter set */
90 ICOUNTRY = 7, /* Country element */
91 IEDCAPARAMS = 12, /* EDCA parameter set */
92 ITSPEC = 13, /* Traffic Specification */
93 ITCLAS = 14, /* Traffic Classification */
94 ISCHED = 15, /* Schedule */
95 ICTEXT = 16, /* Challenge Text */
96 IPOWERCONSTRAINT = 32, /* Power Constraint */
97 IPOWERCAPABILITY = 33, /* Power Capability */
98 ITPCREQUEST = 34, /* TPC Request */
99 ITPCREPORT = 35, /* TPC Report */
100 ISUPCHANNEL = 36, /* Supported channel list */
101 ICHSWANNOUNC = 37, /* Channel Switch Announcement */
102 IMEASUREMENTREQUEST = 38, /* Measurement request */
103 IMEASUREMENTREPORT = 39, /* Measurement report */
104 IQUIET = 40, /* Quiet element Info */
105 IIBSSDFS = 41, /* IBSS DFS */
106 IERPINFO = 42, /* ERP Information */
107 ITSDELAY = 43, /* TS Delay */
108 ITCLASPROCESS = 44, /* TCLAS Processing */
109 IHTCAP = 45, /* HT Capabilities */
110 IQOSCAP = 46, /* QoS Capability */
111 IRSNELEMENT = 48, /* RSN Information Element */
112 IEXSUPRATES = 50, /* Extended Supported Rates */
113 IEXCHSWANNOUNC = 60, /* Extended Ch Switch Announcement*/
114 IHTOPERATION = 61, /* HT Information */
115 ISECCHOFF = 62, /* Secondary Channel Offeset */
116 I2040COEX = 72, /* 20/40 Coexistence IE */
117 I2040INTOLCHREPORT = 73, /* 20/40 Intolerant channel report*/
118 IOBSSSCAN = 74, /* OBSS Scan parameters */
119 IEXTCAP = 127, /* Extended capability */
120 IWMM = 221, /* WMM parameters */
121 IWPAELEMENT = 221, /* WPA Information Element */
122 INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF
128 s32 s32MaxRespBuffLen;
135 /*****************************************************************************/
136 /* Extern Variable Declarations */
137 /*****************************************************************************/
139 /*****************************************************************************/
140 /* Global Variables */
141 /*****************************************************************************/
142 /*****************************************************************************/
143 /* Static Function Declarations */
144 /*****************************************************************************/
148 /*****************************************************************************/
150 /*****************************************************************************/
152 /* This function extracts the beacon period field from the beacon or probe */
153 /* response frame. */
154 static inline u16 get_beacon_period(u8 *data)
159 bcn_per |= (data[1] << 8);
164 static inline u32 get_beacon_timestamp_lo(u8 *data)
167 u32 index = MAC_HDR_LEN;
169 time_stamp |= data[index++];
170 time_stamp |= (data[index++] << 8);
171 time_stamp |= (data[index++] << 16);
172 time_stamp |= (data[index] << 24);
177 static inline u32 get_beacon_timestamp_hi(u8 *data)
180 u32 index = (MAC_HDR_LEN + 4);
182 time_stamp |= data[index++];
183 time_stamp |= (data[index++] << 8);
184 time_stamp |= (data[index++] << 16);
185 time_stamp |= (data[index] << 24);
190 /* This function extracts the 'frame type and sub type' bits from the MAC */
191 /* header of the input frame. */
192 /* Returns the value in the LSB of the returned value. */
193 static inline tenuFrmSubtype get_sub_type(u8 *header)
195 return ((tenuFrmSubtype)(header[0] & 0xFC));
198 /* This function extracts the 'to ds' bit from the MAC header of the input */
200 /* Returns the value in the LSB of the returned value. */
201 static inline u8 get_to_ds(u8 *header)
203 return (header[1] & 0x01);
206 /* This function extracts the 'from ds' bit from the MAC header of the input */
208 /* Returns the value in the LSB of the returned value. */
209 static inline u8 get_from_ds(u8 *header)
211 return ((header[1] & 0x02) >> 1);
214 /* This function extracts the MAC Address in 'address1' field of the MAC */
215 /* header and updates the MAC Address in the allocated 'addr' variable. */
216 static inline void get_address1(u8 *pu8msa, u8 *addr)
218 memcpy(addr, pu8msa + 4, 6);
221 /* This function extracts the MAC Address in 'address2' field of the MAC */
222 /* header and updates the MAC Address in the allocated 'addr' variable. */
223 static inline void get_address2(u8 *pu8msa, u8 *addr)
225 memcpy(addr, pu8msa + 10, 6);
228 /* This function extracts the MAC Address in 'address3' field of the MAC */
229 /* header and updates the MAC Address in the allocated 'addr' variable. */
230 static inline void get_address3(u8 *pu8msa, u8 *addr)
232 memcpy(addr, pu8msa + 16, 6);
235 /* This function extracts the BSSID from the incoming WLAN packet based on */
236 /* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */
238 static inline void get_BSSID(u8 *data, u8 *bssid)
240 if (get_from_ds(data) == 1)
241 get_address2(data, bssid);
242 else if (get_to_ds(data) == 1)
243 get_address1(data, bssid);
245 get_address3(data, bssid);
248 /* This function extracts the SSID from a beacon/probe response frame */
249 static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len)
255 len = data[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
257 j = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
260 /* If the SSID length field is set wrongly to a value greater than the */
261 /* allowed maximum SSID length limit, reset the length to 0 */
262 if (len >= MAX_SSID_LEN)
265 for (i = 0; i < len; i++, j++)
273 /* This function extracts the capability info field from the beacon or probe */
274 /* response frame. */
275 static inline u16 get_cap_info(u8 *data)
278 u16 index = MAC_HDR_LEN;
281 st = get_sub_type(data);
283 /* Location of the Capability field is different for Beacon and */
284 /* Association frames. */
285 if ((st == BEACON) || (st == PROBE_RSP))
286 index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN;
288 cap_info = data[index];
289 cap_info |= (data[index + 1] << 8);
294 /* This function extracts the capability info field from the Association */
295 /* response frame. */
296 static inline u16 get_assoc_resp_cap_info(u8 *data)
301 cap_info |= (data[1] << 8);
306 /* This funcion extracts the association status code from the incoming */
307 /* association response frame and returns association status code */
308 static inline u16 get_asoc_status(u8 *data)
312 asoc_status = data[3];
313 asoc_status = (asoc_status << 8) | data[2];
318 /* This function extracts association ID from the incoming association */
320 static inline u16 get_asoc_id(u8 *data)
325 asoc_id |= (data[5] << 8);
330 u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset)
334 /*************************************************************************/
335 /* Beacon Frame - Frame Body */
336 /* --------------------------------------------------------------------- */
337 /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */
338 /* --------------------------------------------------------------------- */
339 /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */
340 /* --------------------------------------------------------------------- */
342 /*************************************************************************/
344 u16index = u16TagParamOffset;
346 /* Search for the TIM Element Field and return if the element is found */
347 while (u16index < (u16RxLen - FCS_LEN)) {
348 if (pu8msa[u16index] == ITIM)
349 return &pu8msa[u16index];
351 u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
357 /* This function gets the current channel information from
358 * the 802.11n beacon/probe response frame */
359 u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen)
363 index = TAG_PARAM_OFFSET;
364 while (index < (u16RxLen - FCS_LEN)) {
365 if (pu8msa[index] == IDSPARMS)
366 return pu8msa[index + 2];
368 /* Increment index by length information and header */
369 index += pu8msa[index + 1] + IE_HDR_LEN;
372 /* Return current channel information from the MIB, if beacon/probe */
373 /* response frame does not contain the DS parameter set IE */
374 /* return (mget_CurrentChannel() + 1); */
375 return 0; /* no MIB here */
378 u8 get_current_channel(u8 *pu8msa, u16 u16RxLen)
380 /* Extract current channel information from */
381 /* the beacon/probe response frame */
382 return get_current_channel_802_11n(pu8msa, u16RxLen);
386 * @brief parses the received 'N' message
388 * @param[in] pu8MsgBuffer The message to be parsed
389 * @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info
390 * @return Error code indicating success/failure
396 s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
399 tstrNetworkInfo *pstrNetworkInfo = NULL;
404 u16 u16WidID = (u16)WID_NIL;
406 u8 *pu8WidVal = NULL;
408 u8MsgType = pu8MsgBuffer[0];
410 /* Check whether the received message type is 'N' */
411 if ('N' != u8MsgType) {
412 PRINT_ER("Received Message format incorrect.\n");
416 /* Extract message ID */
417 u8MsgID = pu8MsgBuffer[1];
419 /* Extract message Length */
420 u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]);
423 u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]);
425 /* Extract WID Length */
426 u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]);
428 /* Assign a pointer to the WID value */
429 pu8WidVal = &pu8MsgBuffer[8];
431 /* parse the WID value of the WID "WID_NEWORK_INFO" */
435 u8 *pu8TimElm = NULL;
442 pstrNetworkInfo = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL);
443 if (!pstrNetworkInfo)
446 pstrNetworkInfo->s8rssi = pu8WidVal[0];
448 /* Assign a pointer to msa "Mac Header Start Address" */
449 pu8msa = &pu8WidVal[1];
451 u16RxLen = u16WidLen - 1;
455 /* Get the cap_info */
456 pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa);
457 /* Get time-stamp [Low only 32 bit] */
458 pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa);
459 PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf);
461 /* Get full time-stamp [Low and High 64 bit] */
462 u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa);
463 u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa);
465 pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32);
468 get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &(pstrNetworkInfo->u8SsidLen));
471 get_BSSID(pu8msa, pstrNetworkInfo->au8bssid);
473 /* Get the current channel */
474 pstrNetworkInfo->u8channel = get_current_channel(pu8msa, (u16RxLen + FCS_LEN));
476 /* Get beacon period */
477 u8index = (MAC_HDR_LEN + TIME_STAMP_LEN);
479 pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index);
481 u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
483 /* Get DTIM Period */
484 pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index);
485 if (pu8TimElm != NULL)
486 pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
487 pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
488 u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN);
491 pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen,
493 if (!pstrNetworkInfo->pu8IEs)
496 pstrNetworkInfo->u16IEsLen = u16IEsLen;
500 *ppstrNetworkInfo = pstrNetworkInfo;
506 * @brief Deallocates the parsed Network Info
508 * @param[in] pstrNetworkInfo Network Info to be deallocated
509 * @return Error code indicating success/failure
515 s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo)
519 if (pstrNetworkInfo != NULL) {
520 if (pstrNetworkInfo->pu8IEs != NULL) {
521 kfree(pstrNetworkInfo->pu8IEs);
522 pstrNetworkInfo->pu8IEs = NULL;
527 kfree(pstrNetworkInfo);
528 pstrNetworkInfo = NULL;
538 * @brief parses the received Association Response frame
540 * @param[in] pu8Buffer The Association Response frame to be parsed
541 * @param[out] ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info
542 * @return Error code indicating success/failure
548 s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
549 tstrConnectRespInfo **ppstrConnectRespInfo)
552 tstrConnectRespInfo *pstrConnectRespInfo = NULL;
553 u16 u16AssocRespLen = 0;
557 pstrConnectRespInfo = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL);
558 if (!pstrConnectRespInfo)
561 /* u16AssocRespLen = pu8Buffer[0]; */
562 u16AssocRespLen = (u16)u32BufferLen;
564 /* get the status code */
565 pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer);
566 if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
568 /* get the capability */
569 pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer);
571 /* get the Association ID */
572 pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer);
574 /* get the Information Elements */
575 pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
576 u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
578 pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL);
579 if (!pstrConnectRespInfo->pu8RespIEs)
582 pstrConnectRespInfo->u16RespIEsLen = u16IEsLen;
585 *ppstrConnectRespInfo = pstrConnectRespInfo;
592 * @brief Deallocates the parsed Association Response Info
594 * @param[in] pstrNetworkInfo Network Info to be deallocated
595 * @return Error code indicating success/failure
601 s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo)
605 if (pstrConnectRespInfo != NULL) {
606 if (pstrConnectRespInfo->pu8RespIEs != NULL) {
607 kfree(pstrConnectRespInfo->pu8RespIEs);
608 pstrConnectRespInfo->pu8RespIEs = NULL;
613 kfree(pstrConnectRespInfo);
614 pstrConnectRespInfo = NULL;
623 #ifndef CONNECT_DIRECT
624 s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
625 wid_site_survey_reslts_s **ppstrSurveyResults,
626 u32 *pu32SurveyResultsCount)
629 wid_site_survey_reslts_s *pstrSurveyResults = NULL;
630 u32 u32SurveyResultsCount = 0;
631 u32 u32SurveyBytesLength = 0;
633 u32 u32RcvdSurveyResultsNum = 2;
634 u8 u8ReadSurveyResFragNum;
638 for (i = 0; i < u32RcvdSurveyResultsNum; i++) {
639 u32SurveyBytesLength = ppu8RcvdSiteSurveyResults[i][0];
642 for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
643 u32SurveyResultsCount++;
647 pstrSurveyResults = kmalloc_array(u32SurveyResultsCount,
648 sizeof(wid_site_survey_reslts_s), GFP_KERNEL);
649 if (!pstrSurveyResults)
652 memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
654 u32SurveyResultsCount = 0;
656 for (i = 0; i < u32RcvdSurveyResultsNum; i++) {
657 pu8BufferPtr = ppu8RcvdSiteSurveyResults[i];
659 u32SurveyBytesLength = pu8BufferPtr[0];
661 /* TODO: mostafa: pu8BufferPtr[1] contains the fragment num */
662 u8ReadSurveyResFragNum = pu8BufferPtr[1];
666 for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
667 memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH);
668 pu8BufferPtr += SURVEY_RESULT_LENGTH;
669 u32SurveyResultsCount++;
674 *ppstrSurveyResults = pstrSurveyResults;
675 *pu32SurveyResultsCount = u32SurveyResultsCount;
681 s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults)
685 if (pstrSurveyResults != NULL) {
686 kfree(pstrSurveyResults);
693 /*Using the global handle of the driver*/
694 extern wilc_wlan_oup_t *gpstrWlanOps;
696 * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs
697 * using driver config layer
700 * @param[in] pstrWIDs WIDs to be sent in the configuration packet
701 * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet
702 * @param[out] pu8RxResp The received Packet Response
703 * @param[out] ps32RxRespLen Length of the received Packet Response
704 * @return Error code indicating success/failure
710 s32 send_config_pkt(u8 u8Mode, tstrWID *pstrWIDs,
711 u32 u32WIDsCount, bool bRespRequired, u32 drvHandler)
713 s32 counter = 0, ret = 0;
715 if (gpstrWlanOps == NULL) {
716 PRINT_D(CORECONFIG_DBG, "Net Dev is still not initialized\n");
719 PRINT_D(CORECONFIG_DBG, "Net Dev is initialized\n");
721 if (gpstrWlanOps->wlan_cfg_set == NULL ||
722 gpstrWlanOps->wlan_cfg_get == NULL) {
723 PRINT_D(CORECONFIG_DBG, "Set and Get is still not initialized\n");
726 PRINT_D(CORECONFIG_DBG, "SET is initialized\n");
728 if (u8Mode == GET_CFG) {
729 for (counter = 0; counter < u32WIDsCount; counter++) {
730 PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter,
731 (counter == u32WIDsCount - 1));
732 if (!gpstrWlanOps->wlan_cfg_get(!counter,
733 pstrWIDs[counter].u16WIDid,
734 (counter == u32WIDsCount - 1), drvHandler)) {
736 printk("[Sendconfigpkt]Get Timed out\n");
744 for (counter = 0; counter < u32WIDsCount; counter++) {
745 pstrWIDs[counter].s32ValueSize = gpstrWlanOps->wlan_cfg_get_value(
746 pstrWIDs[counter].u16WIDid,
747 pstrWIDs[counter].ps8WidVal, pstrWIDs[counter].s32ValueSize);
750 } else if (u8Mode == SET_CFG) {
751 for (counter = 0; counter < u32WIDsCount; counter++) {
752 PRINT_D(CORECONFIG_DBG, "Sending config SET PACKET WID:%x\n", pstrWIDs[counter].u16WIDid);
753 if (!gpstrWlanOps->wlan_cfg_set(!counter,
754 pstrWIDs[counter].u16WIDid, pstrWIDs[counter].ps8WidVal,
755 pstrWIDs[counter].s32ValueSize,
756 (counter == u32WIDsCount - 1), drvHandler)) {
758 printk("[Sendconfigpkt]Set Timed out\n");