• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*!
3  *  @file	coreconfigurator.c
4  *  @brief
5  *  @author
6  *  @sa		coreconfigurator.h
7  *  @date	1 Mar 2012
8  *  @version	1.0
9  */
10 
11 #include "coreconfigurator.h"
12 #include "wilc_wlan_if.h"
13 #include "wilc_wlan.h"
14 #include <linux/errno.h>
15 #include <linux/slab.h>
16 #define TAG_PARAM_OFFSET	(MAC_HDR_LEN + TIME_STAMP_LEN + \
17 							BEACON_INTERVAL_LEN + CAP_INFO_LEN)
18 
19 /* Basic Frame Type Codes (2-bit) */
20 enum basic_frame_type {
21 	FRAME_TYPE_CONTROL     = 0x04,
22 	FRAME_TYPE_DATA        = 0x08,
23 	FRAME_TYPE_MANAGEMENT  = 0x00,
24 	FRAME_TYPE_RESERVED    = 0x0C,
25 	FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF
26 };
27 
28 /* Frame Type and Subtype Codes (6-bit) */
29 enum sub_frame_type {
30 	ASSOC_REQ             = 0x00,
31 	ASSOC_RSP             = 0x10,
32 	REASSOC_REQ           = 0x20,
33 	REASSOC_RSP           = 0x30,
34 	PROBE_REQ             = 0x40,
35 	PROBE_RSP             = 0x50,
36 	BEACON                = 0x80,
37 	ATIM                  = 0x90,
38 	DISASOC               = 0xA0,
39 	AUTH                  = 0xB0,
40 	DEAUTH                = 0xC0,
41 	ACTION                = 0xD0,
42 	PS_POLL               = 0xA4,
43 	RTS                   = 0xB4,
44 	CTS                   = 0xC4,
45 	ACK                   = 0xD4,
46 	CFEND                 = 0xE4,
47 	CFEND_ACK             = 0xF4,
48 	DATA                  = 0x08,
49 	DATA_ACK              = 0x18,
50 	DATA_POLL             = 0x28,
51 	DATA_POLL_ACK         = 0x38,
52 	NULL_FRAME            = 0x48,
53 	CFACK                 = 0x58,
54 	CFPOLL                = 0x68,
55 	CFPOLL_ACK            = 0x78,
56 	QOS_DATA              = 0x88,
57 	QOS_DATA_ACK          = 0x98,
58 	QOS_DATA_POLL         = 0xA8,
59 	QOS_DATA_POLL_ACK     = 0xB8,
60 	QOS_NULL_FRAME        = 0xC8,
61 	QOS_CFPOLL            = 0xE8,
62 	QOS_CFPOLL_ACK        = 0xF8,
63 	BLOCKACK_REQ          = 0x84,
64 	BLOCKACK              = 0x94,
65 	FRAME_SUBTYPE_FORCE_32BIT  = 0xFFFFFFFF
66 };
67 
68 /* Element ID  of various Information Elements */
69 enum info_element_id {
70 	ISSID               = 0,   /* Service Set Identifier         */
71 	ISUPRATES           = 1,   /* Supported Rates                */
72 	IFHPARMS            = 2,   /* FH parameter set               */
73 	IDSPARMS            = 3,   /* DS parameter set               */
74 	ICFPARMS            = 4,   /* CF parameter set               */
75 	ITIM                = 5,   /* Traffic Information Map        */
76 	IIBPARMS            = 6,   /* IBSS parameter set             */
77 	ICOUNTRY            = 7,   /* Country element                */
78 	IEDCAPARAMS         = 12,  /* EDCA parameter set             */
79 	ITSPEC              = 13,  /* Traffic Specification          */
80 	ITCLAS              = 14,  /* Traffic Classification         */
81 	ISCHED              = 15,  /* Schedule                       */
82 	ICTEXT              = 16,  /* Challenge Text                 */
83 	IPOWERCONSTRAINT    = 32,  /* Power Constraint               */
84 	IPOWERCAPABILITY    = 33,  /* Power Capability               */
85 	ITPCREQUEST         = 34,  /* TPC Request                    */
86 	ITPCREPORT          = 35,  /* TPC Report                     */
87 	ISUPCHANNEL         = 36,  /* Supported channel list         */
88 	ICHSWANNOUNC        = 37,  /* Channel Switch Announcement    */
89 	IMEASUREMENTREQUEST = 38,  /* Measurement request            */
90 	IMEASUREMENTREPORT  = 39,  /* Measurement report             */
91 	IQUIET              = 40,  /* Quiet element Info             */
92 	IIBSSDFS            = 41,  /* IBSS DFS                       */
93 	IERPINFO            = 42,  /* ERP Information                */
94 	ITSDELAY            = 43,  /* TS Delay                       */
95 	ITCLASPROCESS       = 44,  /* TCLAS Processing               */
96 	IHTCAP              = 45,  /* HT Capabilities                */
97 	IQOSCAP             = 46,  /* QoS Capability                 */
98 	IRSNELEMENT         = 48,  /* RSN Information Element        */
99 	IEXSUPRATES         = 50,  /* Extended Supported Rates       */
100 	IEXCHSWANNOUNC      = 60,  /* Extended Ch Switch Announcement*/
101 	IHTOPERATION        = 61,  /* HT Information                 */
102 	ISECCHOFF           = 62,  /* Secondary Channel Offeset      */
103 	I2040COEX           = 72,  /* 20/40 Coexistence IE           */
104 	I2040INTOLCHREPORT  = 73,  /* 20/40 Intolerant channel report*/
105 	IOBSSSCAN           = 74,  /* OBSS Scan parameters           */
106 	IEXTCAP             = 127, /* Extended capability            */
107 	IWMM                = 221, /* WMM parameters                 */
108 	IWPAELEMENT         = 221, /* WPA Information Element        */
109 	INFOELEM_ID_FORCE_32BIT  = 0xFFFFFFFF
110 };
111 
112 /* This function extracts the beacon period field from the beacon or probe   */
113 /* response frame.                                                           */
get_beacon_period(u8 * data)114 static inline u16 get_beacon_period(u8 *data)
115 {
116 	u16 bcn_per;
117 
118 	bcn_per  = data[0];
119 	bcn_per |= (data[1] << 8);
120 
121 	return bcn_per;
122 }
123 
get_beacon_timestamp_lo(u8 * data)124 static inline u32 get_beacon_timestamp_lo(u8 *data)
125 {
126 	u32 time_stamp = 0;
127 	u32 index    = MAC_HDR_LEN;
128 
129 	time_stamp |= data[index++];
130 	time_stamp |= (data[index++] << 8);
131 	time_stamp |= (data[index++] << 16);
132 	time_stamp |= (data[index]   << 24);
133 
134 	return time_stamp;
135 }
136 
get_beacon_timestamp_hi(u8 * data)137 static inline u32 get_beacon_timestamp_hi(u8 *data)
138 {
139 	u32 time_stamp = 0;
140 	u32 index    = (MAC_HDR_LEN + 4);
141 
142 	time_stamp |= data[index++];
143 	time_stamp |= (data[index++] << 8);
144 	time_stamp |= (data[index++] << 16);
145 	time_stamp |= (data[index]   << 24);
146 
147 	return time_stamp;
148 }
149 
150 /* This function extracts the 'frame type and sub type' bits from the MAC    */
151 /* header of the input frame.                                                */
152 /* Returns the value in the LSB of the returned value.                       */
get_sub_type(u8 * header)153 static inline enum sub_frame_type get_sub_type(u8 *header)
154 {
155 	return ((enum sub_frame_type)(header[0] & 0xFC));
156 }
157 
158 /* This function extracts the 'to ds' bit from the MAC header of the input   */
159 /* frame.                                                                    */
160 /* Returns the value in the LSB of the returned value.                       */
get_to_ds(u8 * header)161 static inline u8 get_to_ds(u8 *header)
162 {
163 	return (header[1] & 0x01);
164 }
165 
166 /* This function extracts the 'from ds' bit from the MAC header of the input */
167 /* frame.                                                                    */
168 /* Returns the value in the LSB of the returned value.                       */
get_from_ds(u8 * header)169 static inline u8 get_from_ds(u8 *header)
170 {
171 	return ((header[1] & 0x02) >> 1);
172 }
173 
174 /* This function extracts the MAC Address in 'address1' field of the MAC     */
175 /* header and updates the MAC Address in the allocated 'addr' variable.      */
get_address1(u8 * pu8msa,u8 * addr)176 static inline void get_address1(u8 *pu8msa, u8 *addr)
177 {
178 	memcpy(addr, pu8msa + 4, 6);
179 }
180 
181 /* This function extracts the MAC Address in 'address2' field of the MAC     */
182 /* header and updates the MAC Address in the allocated 'addr' variable.      */
get_address2(u8 * pu8msa,u8 * addr)183 static inline void get_address2(u8 *pu8msa, u8 *addr)
184 {
185 	memcpy(addr, pu8msa + 10, 6);
186 }
187 
188 /* This function extracts the MAC Address in 'address3' field of the MAC     */
189 /* header and updates the MAC Address in the allocated 'addr' variable.      */
get_address3(u8 * pu8msa,u8 * addr)190 static inline void get_address3(u8 *pu8msa, u8 *addr)
191 {
192 	memcpy(addr, pu8msa + 16, 6);
193 }
194 
195 /* This function extracts the BSSID from the incoming WLAN packet based on   */
196 /* the 'from ds' bit, and updates the MAC Address in the allocated 'addr'    */
197 /* variable.                                                                 */
get_BSSID(u8 * data,u8 * bssid)198 static inline void get_BSSID(u8 *data, u8 *bssid)
199 {
200 	if (get_from_ds(data) == 1)
201 		get_address2(data, bssid);
202 	else if (get_to_ds(data) == 1)
203 		get_address1(data, bssid);
204 	else
205 		get_address3(data, bssid);
206 }
207 
208 /* This function extracts the SSID from a beacon/probe response frame        */
get_ssid(u8 * data,u8 * ssid,u8 * p_ssid_len)209 static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len)
210 {
211 	u8 len = 0;
212 	u8 i   = 0;
213 	u8 j   = 0;
214 
215 	len = data[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
216 		   CAP_INFO_LEN + 1];
217 	j   = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
218 		CAP_INFO_LEN + 2;
219 
220 	/* If the SSID length field is set wrongly to a value greater than the   */
221 	/* allowed maximum SSID length limit, reset the length to 0              */
222 	if (len >= MAX_SSID_LEN)
223 		len = 0;
224 
225 	for (i = 0; i < len; i++, j++)
226 		ssid[i] = data[j];
227 
228 	ssid[len] = '\0';
229 
230 	*p_ssid_len = len;
231 }
232 
233 /* This function extracts the capability info field from the beacon or probe */
234 /* response frame.                                                           */
get_cap_info(u8 * data)235 static inline u16 get_cap_info(u8 *data)
236 {
237 	u16 cap_info = 0;
238 	u16 index    = MAC_HDR_LEN;
239 	enum sub_frame_type st;
240 
241 	st = get_sub_type(data);
242 
243 	/* Location of the Capability field is different for Beacon and */
244 	/* Association frames.                                          */
245 	if ((st == BEACON) || (st == PROBE_RSP))
246 		index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN;
247 
248 	cap_info  = data[index];
249 	cap_info |= (data[index + 1] << 8);
250 
251 	return cap_info;
252 }
253 
254 /* This function extracts the capability info field from the Association */
255 /* response frame.                                                                       */
get_assoc_resp_cap_info(u8 * data)256 static inline u16 get_assoc_resp_cap_info(u8 *data)
257 {
258 	u16 cap_info;
259 
260 	cap_info  = data[0];
261 	cap_info |= (data[1] << 8);
262 
263 	return cap_info;
264 }
265 
266 /* This function extracts the association status code from the incoming       */
267 /* association response frame and returns association status code            */
get_asoc_status(u8 * data)268 static inline u16 get_asoc_status(u8 *data)
269 {
270 	u16 asoc_status;
271 
272 	asoc_status = data[3];
273 	asoc_status = (asoc_status << 8) | data[2];
274 
275 	return asoc_status;
276 }
277 
278 /* This function extracts association ID from the incoming association       */
279 /* response frame							                                     */
get_asoc_id(u8 * data)280 static inline u16 get_asoc_id(u8 *data)
281 {
282 	u16 asoc_id;
283 
284 	asoc_id  = data[4];
285 	asoc_id |= (data[5] << 8);
286 
287 	return asoc_id;
288 }
289 
get_tim_elm(u8 * pu8msa,u16 u16RxLen,u16 u16TagParamOffset)290 u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset)
291 {
292 	u16 u16index;
293 
294 	/*************************************************************************/
295 	/*                       Beacon Frame - Frame Body                       */
296 	/* --------------------------------------------------------------------- */
297 	/* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm   | */
298 	/* --------------------------------------------------------------------- */
299 	/* |8         |2         |2       |2-34 |3-10     |3        |4-256     | */
300 	/* --------------------------------------------------------------------- */
301 	/*                                                                       */
302 	/*************************************************************************/
303 
304 	u16index = u16TagParamOffset;
305 
306 	/* Search for the TIM Element Field and return if the element is found */
307 	while (u16index < (u16RxLen - FCS_LEN)) {
308 		if (pu8msa[u16index] == ITIM)
309 			return &pu8msa[u16index];
310 		u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
311 	}
312 
313 	return NULL;
314 }
315 
316 /* This function gets the current channel information from
317  * the 802.11n beacon/probe response frame */
get_current_channel_802_11n(u8 * pu8msa,u16 u16RxLen)318 u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen)
319 {
320 	u16 index;
321 
322 	index = TAG_PARAM_OFFSET;
323 	while (index < (u16RxLen - FCS_LEN)) {
324 		if (pu8msa[index] == IDSPARMS)
325 			return pu8msa[index + 2];
326 		/* Increment index by length information and header */
327 		index += pu8msa[index + 1] + IE_HDR_LEN;
328 	}
329 
330 	/* Return current channel information from the MIB, if beacon/probe  */
331 	/* response frame does not contain the DS parameter set IE           */
332 	/* return (mget_CurrentChannel() + 1); */
333 	return 0;  /* no MIB here */
334 }
335 
336 /**
337  *  @brief                      parses the received 'N' message
338  *  @details
339  *  @param[in]  pu8MsgBuffer The message to be parsed
340  *  @param[out]         ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info
341  *  @return             Error code indicating success/failure
342  *  @note
343  *  @author		mabubakr
344  *  @date			1 Mar 2012
345  *  @version		1.0
346  */
parse_network_info(u8 * pu8MsgBuffer,tstrNetworkInfo ** ppstrNetworkInfo)347 s32 parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
348 {
349 	tstrNetworkInfo *pstrNetworkInfo = NULL;
350 	u8 u8MsgType = 0;
351 	u8 u8MsgID = 0;
352 	u16 u16MsgLen = 0;
353 
354 	u16 u16WidID = (u16)WID_NIL;
355 	u16 u16WidLen  = 0;
356 	u8  *pu8WidVal = NULL;
357 
358 	u8MsgType = pu8MsgBuffer[0];
359 
360 	/* Check whether the received message type is 'N' */
361 	if ('N' != u8MsgType) {
362 		PRINT_ER("Received Message format incorrect.\n");
363 		return -EFAULT;
364 	}
365 
366 	/* Extract message ID */
367 	u8MsgID = pu8MsgBuffer[1];
368 
369 	/* Extract message Length */
370 	u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]);
371 
372 	/* Extract WID ID */
373 	u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]);
374 
375 	/* Extract WID Length */
376 	u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]);
377 
378 	/* Assign a pointer to the WID value */
379 	pu8WidVal  = &pu8MsgBuffer[8];
380 
381 	/* parse the WID value of the WID "WID_NEWORK_INFO" */
382 	{
383 		u8  *pu8msa = NULL;
384 		u16 u16RxLen = 0;
385 		u8 *pu8TimElm = NULL;
386 		u8 *pu8IEs = NULL;
387 		u16 u16IEsLen = 0;
388 		u8 u8index = 0;
389 		u32 u32Tsf_Lo;
390 		u32 u32Tsf_Hi;
391 
392 		pstrNetworkInfo = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL);
393 		if (!pstrNetworkInfo)
394 			return -ENOMEM;
395 
396 		pstrNetworkInfo->s8rssi = pu8WidVal[0];
397 
398 		/* Assign a pointer to msa "Mac Header Start Address" */
399 		pu8msa = &pu8WidVal[1];
400 
401 		u16RxLen = u16WidLen - 1;
402 
403 		/* parse msa*/
404 
405 		/* Get the cap_info */
406 		pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa);
407 		/* Get time-stamp [Low only 32 bit] */
408 		pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa);
409 		PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf);
410 
411 		/* Get full time-stamp [Low and High 64 bit] */
412 		u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa);
413 		u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa);
414 
415 		pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32);
416 
417 		/* Get SSID */
418 		get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen);
419 
420 		/* Get BSSID */
421 		get_BSSID(pu8msa, pstrNetworkInfo->au8bssid);
422 
423 		/*
424 		 * Extract current channel information from
425 		 * the beacon/probe response frame
426 		 */
427 		pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa,
428 							u16RxLen + FCS_LEN);
429 
430 		/* Get beacon period */
431 		u8index = MAC_HDR_LEN + TIME_STAMP_LEN;
432 
433 		pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index);
434 
435 		u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
436 
437 		/* Get DTIM Period */
438 		pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index);
439 		if (pu8TimElm != NULL)
440 			pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
441 		pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
442 		u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN);
443 
444 		if (u16IEsLen > 0) {
445 			pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen,
446 							  GFP_KERNEL);
447 			if (!pstrNetworkInfo->pu8IEs)
448 				return -ENOMEM;
449 		}
450 		pstrNetworkInfo->u16IEsLen = u16IEsLen;
451 
452 	}
453 
454 	*ppstrNetworkInfo = pstrNetworkInfo;
455 
456 	return 0;
457 }
458 
459 /**
460  *  @brief              Deallocates the parsed Network Info
461  *  @details
462  *  @param[in]  pstrNetworkInfo Network Info to be deallocated
463  *  @return             Error code indicating success/failure
464  *  @note
465  *  @author		mabubakr
466  *  @date		1 Mar 2012
467  *  @version		1.0
468  */
DeallocateNetworkInfo(tstrNetworkInfo * pstrNetworkInfo)469 s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo)
470 {
471 	s32 s32Error = 0;
472 
473 	if (pstrNetworkInfo != NULL) {
474 		if (pstrNetworkInfo->pu8IEs != NULL) {
475 			kfree(pstrNetworkInfo->pu8IEs);
476 			pstrNetworkInfo->pu8IEs = NULL;
477 		} else {
478 			s32Error = -EFAULT;
479 		}
480 
481 		kfree(pstrNetworkInfo);
482 		pstrNetworkInfo = NULL;
483 
484 	} else {
485 		s32Error = -EFAULT;
486 	}
487 
488 	return s32Error;
489 }
490 
491 /**
492  *  @brief                      parses the received Association Response frame
493  *  @details
494  *  @param[in]  pu8Buffer The Association Response frame to be parsed
495  *  @param[out]         ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info
496  *  @return             Error code indicating success/failure
497  *  @note
498  *  @author		mabubakr
499  *  @date			2 Apr 2012
500  *  @version		1.0
501  */
ParseAssocRespInfo(u8 * pu8Buffer,u32 u32BufferLen,tstrConnectRespInfo ** ppstrConnectRespInfo)502 s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
503 			       tstrConnectRespInfo **ppstrConnectRespInfo)
504 {
505 	s32 s32Error = 0;
506 	tstrConnectRespInfo *pstrConnectRespInfo = NULL;
507 	u16 u16AssocRespLen = 0;
508 	u8 *pu8IEs = NULL;
509 	u16 u16IEsLen = 0;
510 
511 	pstrConnectRespInfo = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL);
512 	if (!pstrConnectRespInfo)
513 		return -ENOMEM;
514 
515 	/* u16AssocRespLen = pu8Buffer[0]; */
516 	u16AssocRespLen = (u16)u32BufferLen;
517 
518 	/* get the status code */
519 	pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer);
520 	if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
521 
522 		/* get the capability */
523 		pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer);
524 
525 		/* get the Association ID */
526 		pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer);
527 
528 		/* get the Information Elements */
529 		pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
530 		u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
531 
532 		pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL);
533 		if (!pstrConnectRespInfo->pu8RespIEs)
534 			return -ENOMEM;
535 
536 		pstrConnectRespInfo->u16RespIEsLen = u16IEsLen;
537 	}
538 
539 	*ppstrConnectRespInfo = pstrConnectRespInfo;
540 
541 	return s32Error;
542 }
543 
544 /**
545  *  @brief                      Deallocates the parsed Association Response Info
546  *  @details
547  *  @param[in]  pstrNetworkInfo Network Info to be deallocated
548  *  @return             Error code indicating success/failure
549  *  @note
550  *  @author		mabubakr
551  *  @date			2 Apr 2012
552  *  @version		1.0
553  */
DeallocateAssocRespInfo(tstrConnectRespInfo * pstrConnectRespInfo)554 s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo)
555 {
556 	s32 s32Error = 0;
557 
558 	if (pstrConnectRespInfo != NULL) {
559 		if (pstrConnectRespInfo->pu8RespIEs != NULL) {
560 			kfree(pstrConnectRespInfo->pu8RespIEs);
561 			pstrConnectRespInfo->pu8RespIEs = NULL;
562 		} else {
563 			s32Error = -EFAULT;
564 		}
565 
566 		kfree(pstrConnectRespInfo);
567 		pstrConnectRespInfo = NULL;
568 
569 	} else {
570 		s32Error = -EFAULT;
571 	}
572 
573 	return s32Error;
574 }
575 
576 /**
577  *  @brief              sends certain Configuration Packet based on the input WIDs pstrWIDs
578  *  using driver config layer
579  *
580  *  @details
581  *  @param[in]  pstrWIDs WIDs to be sent in the configuration packet
582  *  @param[in]  u32WIDsCount number of WIDs to be sent in the configuration packet
583  *  @param[out]         pu8RxResp The received Packet Response
584  *  @param[out]         ps32RxRespLen Length of the received Packet Response
585  *  @return     Error code indicating success/failure
586  *  @note
587  *  @author	mabubakr
588  *  @date		1 Mar 2012
589  *  @version	1.0
590  */
send_config_pkt(u8 mode,struct wid * wids,u32 count,u32 drv)591 s32 send_config_pkt(u8 mode, struct wid *wids, u32 count, u32 drv)
592 {
593 	s32 counter = 0, ret = 0;
594 
595 	if (mode == GET_CFG) {
596 		for (counter = 0; counter < count; counter++) {
597 			PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter,
598 				   (counter == count - 1));
599 			if (!wilc_wlan_cfg_get(!counter,
600 					       wids[counter].id,
601 					       (counter == count - 1),
602 					       drv)) {
603 				ret = -1;
604 				printk("[Sendconfigpkt]Get Timed out\n");
605 				break;
606 			}
607 		}
608 		counter = 0;
609 		for (counter = 0; counter < count; counter++) {
610 			wids[counter].size = wilc_wlan_cfg_get_val(
611 					wids[counter].id,
612 					wids[counter].val,
613 					wids[counter].size);
614 
615 		}
616 	} else if (mode == SET_CFG) {
617 		for (counter = 0; counter < count; counter++) {
618 			PRINT_D(CORECONFIG_DBG, "Sending config SET PACKET WID:%x\n", wids[counter].id);
619 			if (!wilc_wlan_cfg_set(!counter,
620 					       wids[counter].id,
621 					       wids[counter].val,
622 					       wids[counter].size,
623 					       (counter == count - 1),
624 					       drv)) {
625 				ret = -1;
626 				printk("[Sendconfigpkt]Set Timed out\n");
627 				break;
628 			}
629 		}
630 	}
631 
632 	return ret;
633 }
634