xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlan/mlan_join.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_join.c
2  *
3  *  @brief Functions implementing wlan infrastructure and adhoc join routines
4  *
5  *  IOCTL handlers as well as command preparation and response routines
6  *  for sending adhoc start, adhoc join, and association commands
7  *  to the firmware.
8  *
9  *  Copyright (C) 2008-2017, Marvell International Ltd.
10  *
11  *  This software file (the "File") is distributed by Marvell International
12  *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
13  *  (the "License").  You may use, redistribute and/or modify this File in
14  *  accordance with the terms and conditions of the License, a copy of which
15  *  is available by writing to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
17  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
18  *
19  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
20  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
21  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
22  *  this warranty disclaimer.
23  */
24 
25 /******************************************************
26 Change log:
27     10/30/2008: initial version
28 ******************************************************/
29 
30 #include "mlan.h"
31 #include "mlan_join.h"
32 #include "mlan_util.h"
33 #include "mlan_fw.h"
34 #include "mlan_main.h"
35 #include "mlan_wmm.h"
36 #include "mlan_11n.h"
37 #include "mlan_11h.h"
38 #ifdef DRV_EMBEDDED_SUPPLICANT
39 #include "authenticator_api.h"
40 #endif
41 /********************************************************
42 			Local Constants
43 ********************************************************/
44 
45 /********************************************************
46 			Local Variables
47 ********************************************************/
48 
49 /********************************************************
50 			Global Variables
51 ********************************************************/
52 
53 /********************************************************
54 			Local Functions
55 ********************************************************/
56 /**
57  *  @brief Append a generic IE as a pass through TLV to a TLV buffer.
58  *
59  *  This function is called from the network join command prep. routine.
60  *    If the IE buffer has been setup by the application, this routine appends
61  *    the buffer as a pass through TLV type to the request.
62  *
63  *  @param priv     A pointer to mlan_private structure
64  *  @param ppbuffer pointer to command buffer pointer
65  *
66  *  @return         bytes added to the buffer
67  */
68 static int
wlan_cmd_append_generic_ie(mlan_private * priv,t_u8 ** ppbuffer)69 wlan_cmd_append_generic_ie(mlan_private *priv, t_u8 **ppbuffer)
70 {
71 	int ret_len = 0;
72 	MrvlIEtypesHeader_t ie_header;
73 
74 	ENTER();
75 
76 	/* Null Checks */
77 	if (ppbuffer == MNULL) {
78 		LEAVE();
79 		return 0;
80 	}
81 	if (*ppbuffer == MNULL) {
82 		LEAVE();
83 		return 0;
84 	}
85 
86 	/*
87 	 * If there is a generic ie buffer setup, append it to the return
88 	 *   parameter buffer pointer.
89 	 */
90 	if (priv->gen_ie_buf_len) {
91 		PRINTM(MINFO, "append generic IE %d to %p\n",
92 		       priv->gen_ie_buf_len, *ppbuffer);
93 
94 		/* Wrap the generic IE buffer with a pass through TLV type */
95 		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
96 		ie_header.len = wlan_cpu_to_le16(priv->gen_ie_buf_len);
97 		memcpy(priv->adapter, *ppbuffer, &ie_header, sizeof(ie_header));
98 
99 		/* Increment the return size and the return buffer pointer param */
100 		*ppbuffer += sizeof(ie_header);
101 		ret_len += sizeof(ie_header);
102 
103 		/* Copy the generic IE buffer to the output buffer, advance pointer */
104 		memcpy(priv->adapter, *ppbuffer, priv->gen_ie_buf,
105 		       priv->gen_ie_buf_len);
106 
107 		/* Increment the return size and the return buffer pointer param */
108 		*ppbuffer += priv->gen_ie_buf_len;
109 		ret_len += priv->gen_ie_buf_len;
110 
111 		/* Reset the generic IE buffer */
112 		priv->gen_ie_buf_len = 0;
113 	}
114 
115 	/* return the length appended to the buffer */
116 	LEAVE();
117 	return ret_len;
118 }
119 
120 /**
121  *  @brief Append  IE as a pass through TLV to a TLV buffer.
122  *
123  *  This routine appends IE as a pass through TLV type to the request.
124  *
125  *  @param priv     A pointer to mlan_private structure
126  *  @param ie       A pointer to IE buffer
127  *  @param ppbuffer pointer to command buffer pointer
128  *
129  *  @return         bytes added to the buffer
130  */
131 static int
wlan_cmd_append_pass_through_ie(mlan_private * priv,IEEEtypes_Generic_t * ie,t_u8 ** ppbuffer)132 wlan_cmd_append_pass_through_ie(mlan_private *priv, IEEEtypes_Generic_t *ie,
133 				t_u8 **ppbuffer)
134 {
135 	int ret_len = 0;
136 	MrvlIEtypesHeader_t ie_header;
137 
138 	ENTER();
139 
140 	/* Null Checks */
141 	if (ppbuffer == MNULL) {
142 		LEAVE();
143 		return 0;
144 	}
145 	if (*ppbuffer == MNULL) {
146 		LEAVE();
147 		return 0;
148 	}
149 	if (ie->ieee_hdr.len) {
150 		PRINTM(MINFO, "append generic IE %d to %p\n", ie->ieee_hdr.len,
151 		       *ppbuffer);
152 
153 		/* Wrap the generic IE buffer with a pass through TLV type */
154 		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
155 		ie_header.len =
156 			wlan_cpu_to_le16(ie->ieee_hdr.len +
157 					 sizeof(MrvlIEtypesHeader_t));
158 		memcpy(priv->adapter, *ppbuffer, &ie_header, sizeof(ie_header));
159 
160 		/* Increment the return size and the return buffer pointer param */
161 		*ppbuffer += sizeof(ie_header);
162 		ret_len += sizeof(ie_header);
163 
164 		/* Copy the generic IE buffer to the output buffer, advance pointer */
165 		memcpy(priv->adapter, *ppbuffer, ie,
166 		       ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t));
167 
168 		/* Increment the return size and the return buffer pointer param */
169 		*ppbuffer += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t);
170 		ret_len += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t);
171 	}
172 	/* return the length appended to the buffer */
173 	LEAVE();
174 	return ret_len;
175 }
176 
177 /**
178   *  @brief Append TSF tracking info from the scan table for the target AP
179   *
180   *  This function is called from the network join command prep. routine.
181   *     The TSF table TSF sent to the firmware contains two TSF values:
182   *        - the TSF of the target AP from its previous beacon/probe response
183   *        - the TSF timestamp of our local MAC at the time we observed the
184   *          beacon/probe response.
185   *
186   *     The firmware uses the timestamp values to set an initial TSF value
187   *        in the MAC for the new association after a reassociation attempt.
188   *
189   *    @param pmpriv     A pointer to mlan_private structure
190   *    @param ppbuffer   A pointer to command buffer pointer
191   *    @param pbss_desc  A pointer to the BSS Descriptor from the scan table of
192   *                      the AP we are trying to join
193   *
194   *    @return         bytes added to the buffer
195   */
196 static int
wlan_cmd_append_tsf_tlv(mlan_private * pmriv,t_u8 ** ppbuffer,BSSDescriptor_t * pbss_desc)197 wlan_cmd_append_tsf_tlv(mlan_private *pmriv, t_u8 **ppbuffer,
198 			BSSDescriptor_t *pbss_desc)
199 {
200 	MrvlIEtypes_TsfTimestamp_t tsf_tlv;
201 	t_u64 tsf_val;
202 
203 	ENTER();
204 
205 	/* Null Checks */
206 	if (ppbuffer == MNULL) {
207 		LEAVE();
208 		return 0;
209 	}
210 	if (*ppbuffer == MNULL) {
211 		LEAVE();
212 		return 0;
213 	}
214 
215 	memset(pmriv->adapter, &tsf_tlv, 0x00,
216 	       sizeof(MrvlIEtypes_TsfTimestamp_t));
217 
218 	tsf_tlv.header.type = wlan_cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
219 	tsf_tlv.header.len = wlan_cpu_to_le16(2 * sizeof(tsf_val));
220 
221 	memcpy(pmriv->adapter, *ppbuffer, &tsf_tlv, sizeof(tsf_tlv.header));
222 	*ppbuffer += sizeof(tsf_tlv.header);
223 
224 	/* TSF timestamp from the firmware TSF when the bcn/prb rsp was received */
225 	tsf_val = wlan_cpu_to_le64(pbss_desc->network_tsf);
226 	memcpy(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val));
227 	*ppbuffer += sizeof(tsf_val);
228 
229 	memcpy(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
230 	       sizeof(tsf_val));
231 
232 	PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n",
233 	       tsf_val, pbss_desc->network_tsf);
234 
235 	memcpy(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val));
236 	*ppbuffer += sizeof(tsf_val);
237 
238 	LEAVE();
239 	return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
240 }
241 
242 /**
243  *  @brief This function finds out the common rates between rate1 and rate2.
244  *
245  *  It will fill common rates in rate1 as output if found.
246  *
247  *  NOTE: Setting the MSB of the basic rates needs to be taken
248  *   care of, either before or after calling this function
249  *
250  *  @param pmpriv      A pointer to mlan_private structure
251  *  @param rate1       the buffer which keeps input and output
252  *  @param rate1_size  the size of rate1 buffer
253  *  @param rate2       the buffer which keeps rate2
254  *  @param rate2_size  the size of rate2 buffer.
255  *
256  *  @return            MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
257  */
258 static mlan_status
wlan_get_common_rates(IN mlan_private * pmpriv,IN t_u8 * rate1,IN t_u32 rate1_size,IN t_u8 * rate2,IN t_u32 rate2_size)259 wlan_get_common_rates(IN mlan_private *pmpriv,
260 		      IN t_u8 *rate1,
261 		      IN t_u32 rate1_size, IN t_u8 *rate2, IN t_u32 rate2_size)
262 {
263 	mlan_status ret = MLAN_STATUS_SUCCESS;
264 	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
265 	t_u8 *ptr = rate1;
266 	t_u8 *tmp = MNULL;
267 	t_u32 i, j;
268 
269 	ENTER();
270 
271 	ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle, rate1_size,
272 			       MLAN_MEM_DEF, &tmp);
273 	if (ret != MLAN_STATUS_SUCCESS || !tmp) {
274 		PRINTM(MERROR, "Failed to allocate buffer\n");
275 		ret = MLAN_STATUS_FAILURE;
276 		goto done;
277 	}
278 
279 	memcpy(pmpriv->adapter, tmp, rate1, rate1_size);
280 	memset(pmpriv->adapter, rate1, 0, rate1_size);
281 
282 	for (i = 0; rate2[i] && i < rate2_size; i++) {
283 		for (j = 0; tmp[j] && j < rate1_size; j++) {
284 			/* Check common rate, excluding the bit
285 			 * for basic rate */
286 			if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
287 				*rate1++ = tmp[j];
288 				break;
289 			}
290 		}
291 	}
292 
293 	HEXDUMP("rate1 (AP) Rates", tmp, rate1_size);
294 	HEXDUMP("rate2 (Card) Rates", rate2, rate2_size);
295 	HEXDUMP("Common Rates", ptr, rate1 - ptr);
296 	PRINTM(MINFO, "Tx DataRate is set to 0x%X\n", pmpriv->data_rate);
297 
298 	if (!pmpriv->is_data_rate_auto) {
299 		while (*ptr) {
300 			if ((*ptr & 0x7f) == pmpriv->data_rate) {
301 				ret = MLAN_STATUS_SUCCESS;
302 				goto done;
303 			}
304 			ptr++;
305 		}
306 		PRINTM(MMSG, "Previously set fixed data rate %#x is not "
307 		       "compatible with the network\n", pmpriv->data_rate);
308 
309 		ret = MLAN_STATUS_FAILURE;
310 		goto done;
311 	}
312 
313 	ret = MLAN_STATUS_SUCCESS;
314 done:
315 	if (tmp)
316 		pcb->moal_mfree(pmpriv->adapter->pmoal_handle, tmp);
317 
318 	LEAVE();
319 	return ret;
320 }
321 
322 /**
323  *  @brief Create the intersection of the rates supported by a target BSS and
324  *         our pmadapter settings for use in an assoc/join command.
325  *
326  *  @param pmpriv           A pointer to mlan_private structure
327  *  @param pbss_desc        BSS Descriptor whose rates are used in the setup
328  *  @param pout_rates       Output: Octet array of rates common between the BSS
329  *                          and the pmadapter supported rates settings
330  *  @param pout_rates_size  Output: Number of rates/octets set in pout_rates
331  *
332  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
333  */
334 static mlan_status
wlan_setup_rates_from_bssdesc(IN mlan_private * pmpriv,IN BSSDescriptor_t * pbss_desc,OUT t_u8 * pout_rates,OUT t_u32 * pout_rates_size)335 wlan_setup_rates_from_bssdesc(IN mlan_private *pmpriv,
336 			      IN BSSDescriptor_t *pbss_desc,
337 			      OUT t_u8 *pout_rates, OUT t_u32 *pout_rates_size)
338 {
339 	t_u8 card_rates[WLAN_SUPPORTED_RATES];
340 	t_u32 card_rates_size = 0;
341 	ENTER();
342 	/* Copy AP supported rates */
343 	memcpy(pmpriv->adapter, pout_rates, pbss_desc->supported_rates,
344 	       WLAN_SUPPORTED_RATES);
345 
346 	if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
347 	     pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF)
348 	    && (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
349 		/* Special Case: For Japan, 11G rates on CH14 are not allowed */
350 		card_rates_size =
351 			wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
352 						 BAND_B, card_rates);
353 	} else {
354 		/* Get the STA supported rates */
355 		card_rates_size =
356 			wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
357 						 pmpriv->config_bands,
358 						 card_rates);
359 	}
360 	/* Get the common rates between AP and STA supported rates */
361 	if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES,
362 				  card_rates, card_rates_size)) {
363 		*pout_rates_size = 0;
364 		PRINTM(MERROR, "wlan_get_common_rates failed\n");
365 		LEAVE();
366 		return MLAN_STATUS_FAILURE;
367 	}
368 
369 	*pout_rates_size =
370 		MIN(wlan_strlen((char *)pout_rates), WLAN_SUPPORTED_RATES);
371 
372 	LEAVE();
373 	return MLAN_STATUS_SUCCESS;
374 }
375 
376 /**
377  *  @brief Update the scan entry TSF timestamps to reflect a new association
378  *
379  *  @param pmpriv        A pointer to mlan_private structure
380  *  @param pnew_bss_desc A pointer to the newly associated AP's scan table entry
381  *
382  *  @return              N/A
383  */
384 static t_void
wlan_update_tsf_timestamps(IN mlan_private * pmpriv,IN BSSDescriptor_t * pnew_bss_desc)385 wlan_update_tsf_timestamps(IN mlan_private *pmpriv,
386 			   IN BSSDescriptor_t *pnew_bss_desc)
387 {
388 	mlan_adapter *pmadapter = pmpriv->adapter;
389 	t_u32 table_idx;
390 	t_u64 new_tsf_base;
391 	t_s64 tsf_delta;
392 
393 	ENTER();
394 
395 	memcpy(pmpriv->adapter, &new_tsf_base, pnew_bss_desc->time_stamp,
396 	       sizeof(new_tsf_base));
397 
398 	tsf_delta = new_tsf_base - pnew_bss_desc->network_tsf;
399 
400 	PRINTM(MINFO, "TSF: Update TSF timestamps, 0x%016llx -> 0x%016llx\n",
401 	       pnew_bss_desc->network_tsf, new_tsf_base);
402 
403 	for (table_idx = 0; table_idx < pmadapter->num_in_scan_table;
404 	     table_idx++) {
405 		pmadapter->pscan_table[table_idx].network_tsf += tsf_delta;
406 	}
407 
408 	LEAVE();
409 }
410 
411 /**
412  *  @brief Append a wapi IE
413  *
414  *  This function is called from the network join command prep. routine.
415  *    If the IE buffer has been setup by the application, this routine appends
416  *    the buffer as a wapi TLV type to the request.
417  *
418  *  @param priv     A pointer to mlan_private structure
419  *  @param ppbuffer pointer to command buffer pointer
420  *
421  *  @return         bytes added to the buffer
422  */
423 static int
wlan_cmd_append_wapi_ie(mlan_private * priv,t_u8 ** ppbuffer)424 wlan_cmd_append_wapi_ie(mlan_private *priv, t_u8 **ppbuffer)
425 {
426 	int retlen = 0;
427 	MrvlIEtypesHeader_t ie_header;
428 
429 	ENTER();
430 
431 	/* Null Checks */
432 	if (ppbuffer == MNULL) {
433 		LEAVE();
434 		return 0;
435 	}
436 	if (*ppbuffer == MNULL) {
437 		LEAVE();
438 		return 0;
439 	}
440 
441 	/*
442 	 * If there is a wapi ie buffer setup, append it to the return
443 	 *   parameter buffer pointer.
444 	 */
445 	if (priv->wapi_ie_len) {
446 		PRINTM(MCMND, "append wapi ie %d to %p\n", priv->wapi_ie_len,
447 		       *ppbuffer);
448 
449 		/* Wrap the generic IE buffer with a pass through TLV type */
450 		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
451 		ie_header.len = wlan_cpu_to_le16(priv->wapi_ie_len);
452 		memcpy(priv->adapter, *ppbuffer, &ie_header, sizeof(ie_header));
453 
454 		/* Increment the return size and the return buffer pointer param */
455 		*ppbuffer += sizeof(ie_header);
456 		retlen += sizeof(ie_header);
457 
458 		/* Copy the wapi IE buffer to the output buffer, advance pointer */
459 		memcpy(priv->adapter, *ppbuffer, priv->wapi_ie,
460 		       priv->wapi_ie_len);
461 
462 		/* Increment the return size and the return buffer pointer param */
463 		*ppbuffer += priv->wapi_ie_len;
464 		retlen += priv->wapi_ie_len;
465 
466 	}
467 	/* return the length appended to the buffer */
468 	LEAVE();
469 	return retlen;
470 }
471 
472 /********************************************************
473 				Global Functions
474 ********************************************************/
475 /**
476  *  @brief This function updates RSN IE in the association request.
477  *
478  *  @param pmpriv       A pointer to mlan_private structure
479  *
480  *  @param ptlv_rsn_ie       A pointer to rsn_ie TLV
481  */
482 int
wlan_update_rsn_ie(mlan_private * pmpriv,MrvlIEtypes_RsnParamSet_t * ptlv_rsn_ie)483 wlan_update_rsn_ie(mlan_private *pmpriv, MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
484 {
485 	t_u16 *prsn_cap;
486 	t_u16 *ptr;
487 	t_u16 *akm_suite_count_ptr;
488 	t_u16 pmf_mask = 0x00;
489 	t_u8 *temp;
490 	t_u16 pairwise_cipher_count = 0;
491 	t_u16 akm_suite_count = 0;
492 	t_u16 temp_akm_suite_count = 0;
493 	int found = 0;
494 	t_u8 sha_256_oui[4] = { 0x00, 0x0f, 0xac, 0x06 };
495 	mlan_adapter *pmadapter = pmpriv->adapter;
496 
497 	int ap_mfpc = 0, ap_mfpr = 0, ret = MLAN_STATUS_SUCCESS;
498 
499 	pmf_mask =
500 		(((pmpriv->pmfcfg.mfpc << MFPC_BIT) | (pmpriv->pmfcfg.
501 						       mfpr << MFPR_BIT)) |
502 		 (~PMF_MASK));
503 	/* prsn_cap = prsn_ie->rsn_ie + 2 bytes version + 4 bytes group_cipher_suite +
504 	 *            2 bytes pairwise_cipher_count + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
505 	 *            2 bytes akm_suite_count + akm_suite_count * AKM_SUITE_LEN
506 	 */
507 	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8));
508 	pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
509 	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8)
510 			+ sizeof(t_u16) +
511 			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
512 	temp_akm_suite_count = wlan_le16_to_cpu(*ptr);
513 	akm_suite_count = wlan_le16_to_cpu(*ptr);
514 	/* Save pointer to akm_suite_count in RSN IE to update it later */
515 	akm_suite_count_ptr = ptr;
516 	temp = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8)
517 		+ sizeof(t_u16) + pairwise_cipher_count
518 		* PAIRWISE_CIPHER_SUITE_LEN + sizeof(t_u16);
519 	/* ptr now points to the 1st AKM suite */
520 	if (temp_akm_suite_count > 1) {
521 		while (temp_akm_suite_count) {
522 			if (!memcmp
523 			    (pmadapter, temp, sha_256_oui, AKM_SUITE_LEN)) {
524 				found = 1;
525 				break;
526 			}
527 			temp += AKM_SUITE_LEN;
528 			temp_akm_suite_count--;
529 		}
530 		if (found) {
531 			/* Copy SHA256 as AKM suite */
532 			memcpy(pmadapter,
533 			       ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) +
534 						      4 * sizeof(t_u8)
535 						      + sizeof(t_u16) +
536 						      pairwise_cipher_count *
537 						      PAIRWISE_CIPHER_SUITE_LEN
538 						      + sizeof(t_u16)),
539 			       sha_256_oui, AKM_SUITE_LEN);
540 			/* Shift remaining bytes of RSN IE after this */
541 			memmove(pmadapter,
542 				ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) +
543 						       4 * sizeof(t_u8)
544 						       + sizeof(t_u16) +
545 						       pairwise_cipher_count *
546 						       PAIRWISE_CIPHER_SUITE_LEN
547 						       + sizeof(t_u16) +
548 						       AKM_SUITE_LEN),
549 				ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) +
550 						       4 * sizeof(t_u8) +
551 						       sizeof(t_u16) +
552 						       pairwise_cipher_count *
553 						       PAIRWISE_CIPHER_SUITE_LEN
554 						       + sizeof(t_u16) +
555 						       akm_suite_count *
556 						       AKM_SUITE_LEN),
557 				ptlv_rsn_ie->header.len - (sizeof(t_u16) +
558 							   4 * sizeof(t_u8) +
559 							   sizeof(t_u16) +
560 							   pairwise_cipher_count
561 							   *
562 							   PAIRWISE_CIPHER_SUITE_LEN
563 							   + sizeof(t_u16) +
564 							   akm_suite_count *
565 							   AKM_SUITE_LEN));
566 			ptlv_rsn_ie->header.len =
567 				ptlv_rsn_ie->header.len - (akm_suite_count -
568 							   1) * AKM_SUITE_LEN;
569 			/* Update akm suite count */
570 			akm_suite_count = 1;
571 			*akm_suite_count_ptr = akm_suite_count;
572 		}
573 	}
574 	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8)
575 			+ sizeof(t_u16) +
576 			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
577 			sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
578 	prsn_cap = ptr;
579 
580 	ap_mfpc = ((*prsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
581 	ap_mfpr = ((*prsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
582 
583 	if ((!ap_mfpc && !ap_mfpr && pmpriv->pmfcfg.mfpr)
584 	    || ((!ap_mfpc) && ap_mfpr)
585 	    || (ap_mfpc && ap_mfpr && (!pmpriv->pmfcfg.mfpc))
586 		) {
587 		PRINTM(MERROR,
588 		       "Mismatch in PMF config of STA and AP, can't associate to AP\n");
589 		return MLAN_STATUS_FAILURE;
590 	}
591 	/* If PMF is required by AP, just leave the same value with AP */
592 	if (!(*prsn_cap & (0x1 << MFPR_BIT)))
593 		*prsn_cap &= pmf_mask;
594 
595 	return ret;
596 }
597 
598 /**
599  *  @brief This function is to find FT AKM in RSN.
600  *
601  *  @param pmpriv       A pointer to mlan_private structure
602  *
603  *  @param rsn_ie       A pointer to rsn_ie
604  *
605  */
606 t_u8
wlan_ft_akm_is_used(mlan_private * pmpriv,t_u8 * rsn_ie)607 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie)
608 {
609 	t_u8 *temp;
610 	t_u16 count;
611 	t_u16 pairwise_cipher_count = 0;
612 	t_u16 akm_suite_count = 0;
613 	t_u8 found = 0;
614 	t_u8 rsn_ft_1x_oui[4] = { 0x00, 0x0f, 0xac, 0x03 };
615 	t_u8 rsn_ft_psk_oui[4] = { 0x00, 0x0f, 0xac, 0x04 };
616 	t_u8 rsn_ft_sae_oui[4] = { 0x00, 0x0f, 0xac, 0x09 };
617 	mlan_adapter *pmadapter = pmpriv->adapter;
618 
619 	ENTER();
620 
621 	if (!rsn_ie)
622 		goto done;
623 
624 	if (rsn_ie[0] != RSN_IE)
625 		goto done;
626 
627 	/*  2 bytes header + 2 bytes version + 4 bytes group_cipher_suite +
628 	 *  2 bytes pairwise_cipher_count + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN (4) +
629 	 *  2 bytes akm_suite_count + akm_suite_count * AKM_SUITE_LEN (4)
630 	 */
631 	count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8));
632 	pairwise_cipher_count = wlan_le16_to_cpu(count);
633 	count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8)
634 			   + sizeof(t_u16) + pairwise_cipher_count * 4);
635 	akm_suite_count = wlan_le16_to_cpu(count);
636 	temp = (t_u8 *)(rsn_ie + 2 + sizeof(t_u16) + 4 * sizeof(t_u8)
637 			+ sizeof(t_u16) + pairwise_cipher_count
638 			* 4 + sizeof(t_u16));
639 
640 	while (akm_suite_count) {
641 		if (!memcmp
642 		    (pmadapter, temp, rsn_ft_1x_oui, sizeof(rsn_ft_1x_oui)) ||
643 		    !memcmp(pmadapter, temp, rsn_ft_psk_oui,
644 			    sizeof(rsn_ft_psk_oui)) ||
645 		    !memcmp(pmadapter, temp, rsn_ft_sae_oui,
646 			    sizeof(rsn_ft_sae_oui))) {
647 			found = 1;
648 			break;
649 		}
650 		temp += 4;
651 		akm_suite_count--;
652 	}
653 
654 done:
655 	LEAVE();
656 	return found;
657 }
658 
659 /**
660  *  @brief This function prepares command of association.
661  *
662  *  @param pmpriv       A pointer to mlan_private structure
663  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
664  *  @param pdata_buf    A pointer cast of BSSDescriptor_t from the
665  *                        scan table to assoc
666  *
667  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
668  */
669 mlan_status
wlan_cmd_802_11_associate(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_void * pdata_buf)670 wlan_cmd_802_11_associate(IN mlan_private *pmpriv,
671 			  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
672 {
673 	mlan_status ret = MLAN_STATUS_SUCCESS;
674 	mlan_adapter *pmadapter = pmpriv->adapter;
675 	HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
676 	BSSDescriptor_t *pbss_desc;
677 	MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
678 	MrvlIEtypes_PhyParamSet_t *pphy_tlv;
679 	MrvlIEtypes_SsParamSet_t *pss_tlv;
680 	MrvlIEtypes_RatesParamSet_t *prates_tlv;
681 	MrvlIEtypes_AuthType_t *pauth_tlv;
682 	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
683 	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
684 	WLAN_802_11_RATES rates;
685 	t_u32 rates_size;
686 	t_u16 tmp_cap;
687 	t_u8 *pos;
688 #ifdef DRV_EMBEDDED_SUPPLICANT
689 	void *rsn_wpa_ie_tmp = MNULL;
690 #endif
691 	t_u8 ft_akm = 0;
692 	t_u8 oper_class;
693 
694 	ENTER();
695 
696 	pbss_desc = (BSSDescriptor_t *)pdata_buf;
697 	pos = (t_u8 *)passo;
698 
699 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
700 
701 	/* Save so we know which BSS Desc to use in the response handler */
702 	pmpriv->pattempted_bss_desc = pbss_desc;
703 
704 	memcpy(pmadapter, passo->peer_sta_addr,
705 	       pbss_desc->mac_address, sizeof(passo->peer_sta_addr));
706 	pos += sizeof(passo->peer_sta_addr);
707 
708 	/* Set the listen interval */
709 	passo->listen_interval = wlan_cpu_to_le16(pmpriv->listen_interval);
710 	/* Set the beacon period */
711 	passo->beacon_period = wlan_cpu_to_le16(pbss_desc->beacon_period);
712 
713 	pos += sizeof(passo->cap_info);
714 	pos += sizeof(passo->listen_interval);
715 	pos += sizeof(passo->beacon_period);
716 	pos += sizeof(passo->dtim_period);
717 
718 	pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
719 	pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
720 	pssid_tlv->header.len = (t_u16)pbss_desc->ssid.ssid_len;
721 	memcpy(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
722 	       pssid_tlv->header.len);
723 	pos += sizeof(pssid_tlv->header) + pssid_tlv->header.len;
724 	pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
725 
726 	pphy_tlv = (MrvlIEtypes_PhyParamSet_t *)pos;
727 	pphy_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
728 	pphy_tlv->header.len = sizeof(pphy_tlv->fh_ds.ds_param_set);
729 	memcpy(pmadapter, &pphy_tlv->fh_ds.ds_param_set,
730 	       &pbss_desc->phy_param_set.ds_param_set.current_chan,
731 	       sizeof(pphy_tlv->fh_ds.ds_param_set));
732 	pos += sizeof(pphy_tlv->header) + pphy_tlv->header.len;
733 	pphy_tlv->header.len = wlan_cpu_to_le16(pphy_tlv->header.len);
734 
735 	pss_tlv = (MrvlIEtypes_SsParamSet_t *)pos;
736 	pss_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CF);
737 	pss_tlv->header.len = sizeof(pss_tlv->cf_ibss.cf_param_set);
738 	pos += sizeof(pss_tlv->header) + pss_tlv->header.len;
739 	pss_tlv->header.len = wlan_cpu_to_le16(pss_tlv->header.len);
740 
741 	/* Get the common rates supported between the driver and the BSS Desc */
742 	if (wlan_setup_rates_from_bssdesc
743 	    (pmpriv, pbss_desc, rates, &rates_size)) {
744 		ret = MLAN_STATUS_FAILURE;
745 		goto done;
746 	}
747 
748 	/* Save the data rates into Current BSS state structure */
749 	pmpriv->curr_bss_params.num_of_rates = rates_size;
750 	memcpy(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
751 	       rates_size);
752 
753 	/* Setup the Rates TLV in the association command */
754 	prates_tlv = (MrvlIEtypes_RatesParamSet_t *)pos;
755 	prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
756 	prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
757 	memcpy(pmadapter, prates_tlv->rates, rates, rates_size);
758 	pos += sizeof(prates_tlv->header) + rates_size;
759 	PRINTM(MINFO, "ASSOC_CMD: Rates size = %d\n", rates_size);
760 
761 	/* Add the Authentication type to be used for Auth frames if needed */
762 	if (pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO) {
763 		pauth_tlv = (MrvlIEtypes_AuthType_t *)pos;
764 		pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
765 		pauth_tlv->header.len = sizeof(pauth_tlv->auth_type);
766 		if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
767 		    || (pmpriv->sec_info.authentication_mode ==
768 			MLAN_AUTH_MODE_NETWORKEAP))
769 			pauth_tlv->auth_type =
770 				wlan_cpu_to_le16((t_u16)pmpriv->sec_info.
771 						 authentication_mode);
772 		else if (pmpriv->sec_info.authentication_mode ==
773 			 MLAN_AUTH_MODE_FT)
774 			pauth_tlv->auth_type =
775 				wlan_cpu_to_le16(AssocAgentAuth_FastBss_Skip);
776 		else
777 			pauth_tlv->auth_type =
778 				wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
779 		pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
780 		pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
781 	}
782 
783 	if (IS_SUPPORT_MULTI_BANDS(pmadapter)
784 	    && (pbss_desc->bss_band & pmpriv->config_bands)
785 	    && !(ISSUPP_11NENABLED(pmadapter->fw_cap_info)
786 		 && (!pbss_desc->disable_11n)
787 		 && (pmpriv->config_bands & BAND_GN
788 		     || pmpriv->config_bands & BAND_AN)
789 		 && (pbss_desc->pht_cap)
790 	    )
791 		) {
792 		/* Append a channel TLV for the channel the attempted AP was found on */
793 		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
794 		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
795 		pchan_tlv->header.len =
796 			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
797 
798 		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
799 		       sizeof(ChanScanParamSet_t));
800 		pchan_tlv->chan_scan_param[0].chan_number =
801 			(pbss_desc->phy_param_set.ds_param_set.current_chan);
802 		PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
803 		       pchan_tlv->chan_scan_param[0].chan_number);
804 
805 		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
806 			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
807 
808 		PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
809 		       pchan_tlv->chan_scan_param[0].bandcfg);
810 		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
811 	}
812 	if (!pmpriv->wps.session_enable) {
813 		if ((pmpriv->sec_info.wpa_enabled
814 		     || pmpriv->sec_info.wpa2_enabled)) {
815 			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
816 			/* WPA_IE or RSN_IE */
817 			prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
818 			prsn_ie_tlv->header.type =
819 				prsn_ie_tlv->header.type & 0x00FF;
820 			prsn_ie_tlv->header.type =
821 				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
822 			prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
823 			prsn_ie_tlv->header.len =
824 				prsn_ie_tlv->header.len & 0x00FF;
825 			if (prsn_ie_tlv->header.len <=
826 			    (sizeof(pmpriv->wpa_ie) - 2))
827 				memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
828 				       &pmpriv->wpa_ie[2],
829 				       prsn_ie_tlv->header.len);
830 			else {
831 				ret = MLAN_STATUS_FAILURE;
832 				goto done;
833 			}
834 			HEXDUMP("ASSOC_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
835 				sizeof(prsn_ie_tlv->header) +
836 				prsn_ie_tlv->header.len);
837 			pos += sizeof(prsn_ie_tlv->header) +
838 				prsn_ie_tlv->header.len;
839 			prsn_ie_tlv->header.len =
840 				wlan_cpu_to_le16(prsn_ie_tlv->header.len);
841 	/** parse rsn ie to find whether ft akm is used*/
842 			ft_akm = wlan_ft_akm_is_used(pmpriv, pmpriv->wpa_ie);
843 		}
844 #ifdef DRV_EMBEDDED_SUPPLICANT
845 		else if (supplicantIsEnabled(pmpriv->psapriv)) {
846 			supplicantClrEncryptKey(pmpriv->psapriv);
847 
848 			if (pbss_desc->prsn_ie)
849 				rsn_wpa_ie_tmp = pbss_desc->prsn_ie;
850 			else if (pbss_desc->pwpa_ie)
851 				rsn_wpa_ie_tmp = pbss_desc->pwpa_ie;
852 			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
853 			pos += supplicantFormatRsnWpaTlv(pmpriv->psapriv,
854 							 rsn_wpa_ie_tmp,
855 							 prsn_ie_tlv);
856 		}
857 #endif
858 		else if (pmpriv->sec_info.ewpa_enabled) {
859 			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
860 			if (pbss_desc->pwpa_ie) {
861 				prsn_ie_tlv->header.type =
862 					(t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.
863 					element_id;
864 				prsn_ie_tlv->header.type =
865 					prsn_ie_tlv->header.type & 0x00FF;
866 				prsn_ie_tlv->header.type =
867 					wlan_cpu_to_le16(prsn_ie_tlv->header.
868 							 type);
869 				prsn_ie_tlv->header.len =
870 					(t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.
871 					len;
872 				prsn_ie_tlv->header.len =
873 					prsn_ie_tlv->header.len & 0x00FF;
874 				if (prsn_ie_tlv->header.len <=
875 				    (sizeof(pmpriv->wpa_ie))) {
876 					memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
877 					       &((*(pbss_desc->pwpa_ie)).
878 						 vend_hdr.oui[0]),
879 					       prsn_ie_tlv->header.len);
880 				} else {
881 					ret = MLAN_STATUS_FAILURE;
882 					goto done;
883 				}
884 
885 				HEXDUMP("ASSOC_CMD: RSN IE",
886 					(t_u8 *)prsn_ie_tlv,
887 					sizeof(prsn_ie_tlv->header) +
888 					prsn_ie_tlv->header.len);
889 				pos += sizeof(prsn_ie_tlv->header) +
890 					prsn_ie_tlv->header.len;
891 				prsn_ie_tlv->header.len =
892 					wlan_cpu_to_le16(prsn_ie_tlv->header.
893 							 len);
894 			}
895 			if (pbss_desc->prsn_ie) {
896 				prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
897 				prsn_ie_tlv->header.type =
898 					(t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.
899 					element_id;
900 				prsn_ie_tlv->header.type =
901 					prsn_ie_tlv->header.type & 0x00FF;
902 				prsn_ie_tlv->header.type =
903 					wlan_cpu_to_le16(prsn_ie_tlv->header.
904 							 type);
905 				prsn_ie_tlv->header.len =
906 					(t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.
907 					len;
908 				prsn_ie_tlv->header.len =
909 					prsn_ie_tlv->header.len & 0x00FF;
910 				if (prsn_ie_tlv->header.len <=
911 				    (sizeof(pmpriv->wpa_ie))) {
912 					memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
913 					       &((*(pbss_desc->prsn_ie)).
914 						 data[0])
915 					       , prsn_ie_tlv->header.len);
916 					ret = wlan_update_rsn_ie(pmpriv,
917 								 prsn_ie_tlv);
918 					if (ret != MLAN_STATUS_SUCCESS) {
919 						goto done;
920 					}
921 				} else {
922 					ret = MLAN_STATUS_FAILURE;
923 					goto done;
924 				}
925 
926 				HEXDUMP("ASSOC_CMD: RSN IE",
927 					(t_u8 *)prsn_ie_tlv,
928 					sizeof(prsn_ie_tlv->header) +
929 					prsn_ie_tlv->header.len);
930 				pos += sizeof(prsn_ie_tlv->header) +
931 					prsn_ie_tlv->header.len;
932 				prsn_ie_tlv->header.len =
933 					wlan_cpu_to_le16(prsn_ie_tlv->header.
934 							 len);
935 			}
936 		}
937 	}
938 
939 	if (ISSUPP_11NENABLED(pmadapter->fw_cap_info)
940 	    && (!pbss_desc->disable_11n)
941 	    && wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
942 		wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
943 	if (pmpriv->adapter->ecsa_enable) {
944 		if (MLAN_STATUS_SUCCESS ==
945 		    wlan_get_curr_oper_class(pmpriv,
946 					     pbss_desc->phy_param_set.
947 					     ds_param_set.current_chan,
948 					     pbss_desc->curr_bandwidth,
949 					     &oper_class))
950 			wlan_add_supported_oper_class_ie(pmpriv, &pos,
951 							 oper_class);
952 	}
953 
954 	wlan_wmm_process_association_req(pmpriv, &pos, &pbss_desc->wmm_ie,
955 					 pbss_desc->pht_cap);
956 	if (pmpriv->sec_info.wapi_enabled && pmpriv->wapi_ie_len)
957 		wlan_cmd_append_wapi_ie(pmpriv, &pos);
958 
959 	wlan_cmd_append_generic_ie(pmpriv, &pos);
960 
961 	if (ft_akm && pbss_desc->pmd_ie)
962 		wlan_cmd_append_pass_through_ie(pmpriv,
963 						(IEEEtypes_Generic_t *)
964 						pbss_desc->pmd_ie, &pos);
965 	wlan_cmd_append_tsf_tlv(pmpriv, &pos, pbss_desc);
966 
967 	if (wlan_11d_create_dnld_countryinfo(pmpriv, (t_u8)pbss_desc->bss_band)) {
968 		PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
969 		ret = MLAN_STATUS_FAILURE;
970 		goto done;
971 	}
972 	if (wlan_11d_parse_dnld_countryinfo
973 	    (pmpriv, pmpriv->pattempted_bss_desc)) {
974 		ret = MLAN_STATUS_FAILURE;
975 		goto done;
976 	}
977 
978 	/*
979 	 * Call 11h join API after capability bits are set so adhoc/infra 11h
980 	 * behavior can be properly triggered.  pos modified if data is appended
981 	 */
982 	wlan_11h_process_join(pmpriv, &pos, &passo->cap_info,
983 			      (t_u8)pbss_desc->bss_band,
984 			      pbss_desc->phy_param_set.ds_param_set.
985 			      current_chan, &pbss_desc->wlan_11h_bss_info);
986 
987 	cmd->size = wlan_cpu_to_le16((t_u16)(pos - (t_u8 *)passo) + S_DS_GEN);
988 
989 	/* Set the Capability info at last */
990 	memcpy(pmadapter, &tmp_cap, &pbss_desc->cap_info,
991 	       sizeof(passo->cap_info));
992 
993 	if (pmpriv->config_bands == BAND_B)
994 		SHORT_SLOT_TIME_DISABLED(tmp_cap);
995 
996 	/* set SpectrumMgmt(BIT8) and RadioMeasurement(BIT12) if 11K is enabled */
997 	if (pmpriv->enable_11k) {
998 		SPECTRUM_MGMT_ENABLED(tmp_cap);
999 		RADIO_MEASUREMENT_ENABLED(tmp_cap);
1000 	}
1001 
1002 	RADIO_MEASUREMENT_ENABLED(tmp_cap);
1003 
1004 	tmp_cap &= CAPINFO_MASK;
1005 	PRINTM(MINFO, "ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
1006 	       tmp_cap, CAPINFO_MASK);
1007 	tmp_cap = wlan_cpu_to_le16(tmp_cap);
1008 	memcpy(pmadapter, &passo->cap_info, &tmp_cap, sizeof(passo->cap_info));
1009 
1010 done:
1011 	LEAVE();
1012 	return ret;
1013 }
1014 
1015 /**
1016  *  @brief Association firmware command response handler
1017  *
1018  *   The response buffer for the association command has the following
1019  *      memory layout.
1020  *
1021  *   For cases where an association response was not received (indicated
1022  *      by the CapInfo and AId field):
1023  *
1024  *     .------------------------------------------------------------.
1025  *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
1026  *     .------------------------------------------------------------.
1027  *     |  cap_info/Error Return(t_u16):                             |
1028  *     |           0xFFFF(-1): Internal error for association       |
1029  *     |           0xFFFE(-2): Authentication unhandled message     |
1030  *     |           0xFFFD(-3): Authentication refused               |
1031  *     |           0xFFFC(-4): Timeout waiting for AP response      |
1032  *     |           0xFFFB(-5): Internal error for authentication    |
1033  *     .------------------------------------------------------------.
1034  *     |  status_code(t_u16):                                       |
1035  *     |        If cap_info is -1:                                  |
1036  *     |           An internal firmware failure prevented the       |
1037  *     |           command from being processed. The status code    |
1038  *     |           is 6 if associate response parameter invlaid,    |
1039  *     |           1 otherwise.                                     |
1040  *     |                                                            |
1041  *     |        If cap_info is -2:                                  |
1042  *     |           An authentication frame was received but was     |
1043  *     |           not handled by the firmware. IEEE Status code    |
1044  *     |           for the failure is returned.                     |
1045  *     |                                                            |
1046  *     |        If cap_info is -3:                                  |
1047  *     |           An authentication frame was received and the     |
1048  *     |           status_code is the IEEE Status reported in the   |
1049  *     |           response.                                        |
1050  *     |                                                            |
1051  *     |        If cap_info is -4:                                  |
1052  *     |           (1) Association response timeout                 |
1053  *     |           (2) Authentication response timeout              |
1054  *     |                                                            |
1055  *     |        If cap_info is -5:                                  |
1056  *     |           An internal firmware failure prevented the       |
1057  *     |           command from being processed. The status code    |
1058  *     |           is 6 if authentication parameter invlaid,        |
1059  *     |           1 otherwise.                                     |
1060  *     .------------------------------------------------------------.
1061  *     |  a_id(t_u16): 0xFFFF                                       |
1062  *     .------------------------------------------------------------.
1063  *
1064  *
1065  *   For cases where an association response was received, the IEEE
1066  *     standard association response frame is returned:
1067  *
1068  *     .------------------------------------------------------------.
1069  *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
1070  *     .------------------------------------------------------------.
1071  *     |  cap_info(t_u16): IEEE Capability                          |
1072  *     .------------------------------------------------------------.
1073  *     |  status_code(t_u16): IEEE Status Code                      |
1074  *     .------------------------------------------------------------.
1075  *     |  a_id(t_u16): IEEE Association ID                          |
1076  *     .------------------------------------------------------------.
1077  *     |  IEEE IEs(variable): Any received IEs comprising the       |
1078  *     |                      remaining portion of a received       |
1079  *     |                      association response frame.           |
1080  *     .------------------------------------------------------------.
1081  *
1082  *  For simplistic handling, the status_code field can be used to determine
1083  *    an association success (0) or failure (non-zero).
1084  *
1085  *  @param pmpriv       A pointer to mlan_private structure
1086  *  @param resp         A pointer to HostCmd_DS_COMMAND
1087  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1088  *
1089  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1090  */
1091 mlan_status
wlan_ret_802_11_associate(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * resp,IN t_void * pioctl_buf)1092 wlan_ret_802_11_associate(IN mlan_private *pmpriv,
1093 			  IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
1094 {
1095 	mlan_status ret = MLAN_STATUS_SUCCESS;
1096 	mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1097 	IEEEtypes_AssocRsp_t *passoc_rsp;
1098 	BSSDescriptor_t *pbss_desc;
1099 	t_u8 enable_data = MTRUE;
1100 	t_u8 event_buf[100];
1101 	mlan_event *pevent = (mlan_event *)event_buf;
1102 	t_u8 cur_mac[MLAN_MAC_ADDR_LENGTH];
1103 	t_u8 media_connected = pmpriv->media_connected;
1104 	ENTER();
1105 
1106 	passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
1107 	passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code);
1108 	if (pmpriv->media_connected == MTRUE)
1109 		memcpy(pmpriv->adapter, cur_mac,
1110 		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
1111 		       MLAN_MAC_ADDR_LENGTH);
1112 
1113 	HEXDUMP("ASSOC_RESP:", (t_u8 *)&resp->params, (resp->size - S_DS_GEN));
1114 
1115 	pmpriv->assoc_rsp_size = MIN(resp->size - S_DS_GEN,
1116 				     sizeof(pmpriv->assoc_rsp_buf));
1117 
1118 	memcpy(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
1119 	       pmpriv->assoc_rsp_size);
1120 
1121 	if (passoc_rsp->status_code) {
1122 		if (pmpriv->media_connected == MTRUE) {
1123 			if (pmpriv->port_ctrl_mode == MTRUE)
1124 				pmpriv->port_open = pmpriv->prior_port_status;
1125 			if (!memcmp
1126 			    (pmpriv->adapter, cur_mac,
1127 			     pmpriv->pattempted_bss_desc->mac_address,
1128 			     MLAN_MAC_ADDR_LENGTH))
1129 				wlan_reset_connect_state(pmpriv, MTRUE);
1130 			else
1131 				wlan_recv_event(pmpriv,
1132 						MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT,
1133 						MNULL);
1134 		} else
1135 			wlan_reset_connect_state(pmpriv, MTRUE);
1136 		pmpriv->adapter->dbg.num_cmd_assoc_failure++;
1137 		PRINTM(MERROR, "ASSOC_RESP: Association Failed, "
1138 		       "status code = %d, error = 0x%x, a_id = 0x%x\n",
1139 		       passoc_rsp->status_code,
1140 		       wlan_le16_to_cpu(*(t_u16 *)&passoc_rsp->capability),
1141 		       wlan_le16_to_cpu(passoc_rsp->a_id));
1142 
1143 		ret = MLAN_STATUS_FAILURE;
1144 		goto done;
1145 	}
1146 
1147 	/* Send a Media Connected event, according to the Spec */
1148 	pmpriv->media_connected = MTRUE;
1149 
1150 	pmpriv->adapter->pps_uapsd_mode = MFALSE;
1151 	pmpriv->adapter->tx_lock_flag = MFALSE;
1152 	pmpriv->adapter->delay_null_pkt = MFALSE;
1153 
1154 	/* Set the attempted BSSID Index to current */
1155 	pbss_desc = pmpriv->pattempted_bss_desc;
1156 
1157 	PRINTM(MCMND, "ASSOC_RESP: %-32s (a_id = 0x%x)\n", pbss_desc->ssid.ssid,
1158 	       wlan_le16_to_cpu(passoc_rsp->a_id));
1159 	/* Restore default extended capabilities */
1160 	memcpy(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
1161 	       sizeof(pmpriv->ext_cap));
1162 	/* Make a copy of current BSSID descriptor */
1163 	memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
1164 	       pbss_desc, sizeof(BSSDescriptor_t));
1165 
1166 	/* Update curr_bss_params */
1167 	pmpriv->curr_bss_params.bss_descriptor.channel
1168 		= pbss_desc->phy_param_set.ds_param_set.current_chan;
1169 
1170 	pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
1171 
1172 	/* Store current channel for further reference.
1173 	 * This would save one extra call to get current
1174 	 * channel when disconnect/bw_ch event is raised.
1175 	 */
1176 	pmpriv->adapter->dfsr_channel =
1177 		pmpriv->curr_bss_params.bss_descriptor.channel;
1178 
1179 	/*
1180 	 * Adjust the timestamps in the scan table to be relative to the newly
1181 	 * associated AP's TSF
1182 	 */
1183 	wlan_update_tsf_timestamps(pmpriv, pbss_desc);
1184 
1185 	if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE)
1186 		pmpriv->curr_bss_params.wmm_enabled = MTRUE;
1187 	else
1188 		pmpriv->curr_bss_params.wmm_enabled = MFALSE;
1189 
1190 	if ((pmpriv->wmm_required
1191 	     || (pbss_desc->pht_cap &&
1192 		 (pbss_desc->pht_cap->ieee_hdr.element_id == HT_CAPABILITY))
1193 	    ) && pmpriv->curr_bss_params.wmm_enabled)
1194 		pmpriv->wmm_enabled = MTRUE;
1195 	else
1196 		pmpriv->wmm_enabled = MFALSE;
1197 
1198 	pmpriv->curr_bss_params.wmm_uapsd_enabled = MFALSE;
1199 
1200 	if (pmpriv->wmm_enabled == MTRUE)
1201 		pmpriv->curr_bss_params.wmm_uapsd_enabled
1202 			= pbss_desc->wmm_ie.qos_info.qos_uapsd;
1203 
1204 	PRINTM(MINFO, "ASSOC_RESP: curr_pkt_filter is 0x%x\n",
1205 	       pmpriv->curr_pkt_filter);
1206 	if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled)
1207 		pmpriv->wpa_is_gtk_set = MFALSE;
1208 
1209 	if (pmpriv->wmm_enabled)
1210 		/* Don't re-enable carrier until we get the WMM_GET_STATUS event */
1211 		enable_data = MFALSE;
1212 	else
1213 		/* Since WMM is not enabled, setup the queues with the defaults */
1214 		wlan_wmm_setup_queues(pmpriv);
1215 
1216 	if (enable_data)
1217 		PRINTM(MINFO, "Post association, re-enabling data flow\n");
1218 
1219 	/* Reset SNR/NF/RSSI values */
1220 	pmpriv->data_rssi_last = 0;
1221 	pmpriv->data_nf_last = 0;
1222 	pmpriv->data_rssi_avg = 0;
1223 	pmpriv->data_nf_avg = 0;
1224 	pmpriv->bcn_rssi_last = 0;
1225 	pmpriv->bcn_nf_last = 0;
1226 	pmpriv->bcn_rssi_avg = 0;
1227 	pmpriv->bcn_nf_avg = 0;
1228 	pmpriv->amsdu_rx_cnt = 0;
1229 	pmpriv->amsdu_tx_cnt = 0;
1230 	pmpriv->msdu_in_rx_amsdu_cnt = 0;
1231 	pmpriv->msdu_in_tx_amsdu_cnt = 0;
1232 	pmpriv->rxpd_rate = 0;
1233 	pmpriv->rxpd_rate_info = 0;
1234 	if (pbss_desc->pht_cap) {
1235 		if (GETHT_MAXAMSDU(pbss_desc->pht_cap->ht_cap.ht_cap_info))
1236 			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
1237 		else
1238 			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
1239 	}
1240 
1241 	wlan_save_curr_bcn(pmpriv);
1242 
1243 	pmpriv->adapter->dbg.num_cmd_assoc_success++;
1244 
1245 	PRINTM(MINFO, "ASSOC_RESP: Associated\n");
1246 	pevent->bss_index = pmpriv->bss_index;
1247 	pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
1248 	pevent->event_len = MLAN_MAC_ADDR_LENGTH;
1249 	memcpy(pmpriv->adapter, (t_u8 *)pevent->event_buf,
1250 	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
1251 	       MLAN_MAC_ADDR_LENGTH);
1252 
1253 	/* Add the ra_list here for infra mode as there will be only 1 ra always */
1254 	if (media_connected) {
1255 	/** replace ralist's mac address with new mac address */
1256 		if (0 ==
1257 		    wlan_ralist_update(pmpriv, cur_mac,
1258 				       pmpriv->curr_bss_params.bss_descriptor.
1259 				       mac_address))
1260 			wlan_ralist_add(pmpriv,
1261 					pmpriv->curr_bss_params.bss_descriptor.
1262 					mac_address);
1263 		wlan_11n_cleanup_reorder_tbl(pmpriv);
1264 		wlan_11n_deleteall_txbastream_tbl(pmpriv);
1265 
1266 	} else
1267 		wlan_ralist_add(pmpriv,
1268 				pmpriv->curr_bss_params.bss_descriptor.
1269 				mac_address);
1270 
1271 	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
1272 
1273 	/* Send OBSS scan param to the application if available */
1274 	wlan_2040_coex_event(pmpriv);
1275 	wlan_coex_ampdu_rxwinsize(pmpriv->adapter);
1276 
1277 	if (!pmpriv->sec_info.wpa_enabled
1278 	    && !pmpriv->sec_info.wpa2_enabled
1279 	    && !pmpriv->sec_info.ewpa_enabled
1280 	    && !pmpriv->sec_info.wapi_enabled && !pmpriv->wps.session_enable
1281 #ifdef DRV_EMBEDDED_SUPPLICANT
1282 	    && !supplicantIsEnabled(pmpriv->psapriv)
1283 #endif
1284 		) {
1285 		/* We are in Open/WEP mode, open port immediately */
1286 		if (pmpriv->port_ctrl_mode == MTRUE) {
1287 			pmpriv->port_open = MTRUE;
1288 			PRINTM(MINFO, "ASSOC_RESP: port_status = OPEN\n");
1289 		}
1290 	}
1291 
1292 	if (pmpriv->sec_info.wpa_enabled
1293 	    || pmpriv->sec_info.wpa2_enabled
1294 	    || pmpriv->sec_info.ewpa_enabled
1295 	    || pmpriv->sec_info.wapi_enabled || pmpriv->wps.session_enable
1296 #ifdef DRV_EMBEDDED_SUPPLICANT
1297 	    || (supplicantIsEnabled(pmpriv->psapriv))
1298 #endif
1299 		)
1300 		pmpriv->adapter->scan_block = MTRUE;
1301 
1302 #ifdef DRV_EMBEDDED_SUPPLICANT
1303 	supplicantInitSession(pmpriv->psapriv,
1304 			      (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
1305 			      ssid.ssid,
1306 			      pmpriv->curr_bss_params.bss_descriptor.ssid.
1307 			      ssid_len,
1308 			      (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
1309 			      mac_address, (t_u8 *)&pmpriv->curr_addr);
1310 #endif
1311 
1312 done:
1313 	/* Need to indicate IOCTL complete */
1314 	if (pioctl_req != MNULL) {
1315 		if (ret != MLAN_STATUS_SUCCESS) {
1316 			if (passoc_rsp->status_code)
1317 				pioctl_req->status_code =
1318 					(wlan_le16_to_cpu
1319 					 (*(t_u16 *)&passoc_rsp->
1320 					  capability) << 16) +
1321 					passoc_rsp->status_code;
1322 			else
1323 				pioctl_req->status_code =
1324 					MLAN_ERROR_CMD_ASSOC_FAIL;
1325 		} else {
1326 			pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
1327 		}
1328 	}
1329 
1330 	LEAVE();
1331 	return ret;
1332 }
1333 
1334 /**
1335  *  @brief This function prepares command of ad_hoc_start.
1336  *
1337  *  @param pmpriv       A pointer to mlan_private structure
1338  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1339  *  @param pdata_buf    A pointer cast of mlan_802_11_ssid structure
1340  *
1341  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1342  */
1343 mlan_status
wlan_cmd_802_11_ad_hoc_start(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_void * pdata_buf)1344 wlan_cmd_802_11_ad_hoc_start(IN mlan_private *pmpriv,
1345 			     IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
1346 {
1347 	mlan_status ret = MLAN_STATUS_SUCCESS;
1348 	mlan_adapter *pmadapter = pmpriv->adapter;
1349 	HostCmd_DS_802_11_AD_HOC_START *padhoc_start = &cmd->params.adhoc_start;
1350 	BSSDescriptor_t *pbss_desc;
1351 	t_u32 cmd_append_size = 0;
1352 	t_u32 i;
1353 	t_u16 tmp_cap;
1354 	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
1355 
1356 	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
1357 	MrvlIETypes_HTCap_t *pht_cap;
1358 	MrvlIETypes_HTInfo_t *pht_info;
1359 	t_u32 rx_mcs_supp = 0;
1360 	/* wpa ie for WPA_NONE AES */
1361 	const t_u8 wpa_ie[24] =
1362 		{ 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
1363 		0x00, 0x50, 0xf2, 0x04, 0x01, 0x00, 0x00, 0x50,
1364 		0xf2, 0x00, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x00
1365 	};
1366 	t_s32 append_size_11h = 0;
1367 	t_u8 *pos =
1368 		(t_u8 *)padhoc_start + sizeof(HostCmd_DS_802_11_AD_HOC_START);
1369 
1370 	ENTER();
1371 
1372 	if (!pmadapter) {
1373 		ret = MLAN_STATUS_FAILURE;
1374 		goto done;
1375 	}
1376 
1377 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
1378 
1379 	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
1380 	pmpriv->pattempted_bss_desc = pbss_desc;
1381 
1382 	/*
1383 	 * Fill in the parameters for 2 data structures:
1384 	 *   1. HostCmd_DS_802_11_AD_HOC_START command
1385 	 *   2. pbss_desc
1386 	 * Driver will fill up SSID, bss_mode,IBSS param, Physical Param,
1387 	 * probe delay, and Cap info.
1388 	 * Firmware will fill up beacon period, Basic rates
1389 	 * and operational rates.
1390 	 */
1391 
1392 	memset(pmadapter, padhoc_start->ssid, 0, MLAN_MAX_SSID_LENGTH);
1393 
1394 	memcpy(pmadapter, padhoc_start->ssid,
1395 	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
1396 	       MIN(MLAN_MAX_SSID_LENGTH,
1397 		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
1398 
1399 	PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
1400 
1401 	memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
1402 	memcpy(pmadapter, pbss_desc->ssid.ssid,
1403 	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
1404 	       MIN(MLAN_MAX_SSID_LENGTH,
1405 		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
1406 
1407 	pbss_desc->ssid.ssid_len =
1408 		MIN(MLAN_MAX_SSID_LENGTH,
1409 		    ((mlan_802_11_ssid *)pdata_buf)->ssid_len);
1410 
1411 	/* Set the BSS mode */
1412 	padhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
1413 	pbss_desc->bss_mode = MLAN_BSS_MODE_IBSS;
1414 	padhoc_start->beacon_period = wlan_cpu_to_le16(pmpriv->beacon_period);
1415 	pbss_desc->beacon_period = pmpriv->beacon_period;
1416 
1417 	/* Set Physical param set */
1418 /** Parameter IE Id */
1419 #define DS_PARA_IE_ID   3
1420 /** Parameter IE length */
1421 #define DS_PARA_IE_LEN  1
1422 
1423 	padhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
1424 	padhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
1425 
1426 	if (!wlan_get_cfp_by_band_and_channel
1427 	    (pmadapter, pmadapter->adhoc_start_band,
1428 	     (t_u16)pmpriv->adhoc_channel, pmadapter->region_channel)) {
1429 
1430 		chan_freq_power_t *cfp;
1431 		cfp = wlan_get_cfp_by_band_and_channel(pmadapter,
1432 						       pmadapter->
1433 						       adhoc_start_band,
1434 						       FIRST_VALID_CHANNEL,
1435 						       pmadapter->
1436 						       region_channel);
1437 		if (cfp)
1438 			pmpriv->adhoc_channel = (t_u8)cfp->channel;
1439 	}
1440 
1441 	MASSERT(pmpriv->adhoc_channel);
1442 
1443 	PRINTM(MINFO, "ADHOC_S_CMD: Creating ADHOC on Channel %d\n",
1444 	       pmpriv->adhoc_channel);
1445 
1446 	pmpriv->curr_bss_params.bss_descriptor.channel = pmpriv->adhoc_channel;
1447 	pmpriv->curr_bss_params.band = pmadapter->adhoc_start_band;
1448 
1449 	pbss_desc->channel = pmpriv->adhoc_channel;
1450 	padhoc_start->phy_param_set.ds_param_set.current_chan =
1451 		pmpriv->adhoc_channel;
1452 
1453 	memcpy(pmadapter, &pbss_desc->phy_param_set,
1454 	       &padhoc_start->phy_param_set, sizeof(IEEEtypes_PhyParamSet_t));
1455 
1456 	pbss_desc->network_type_use = Wlan802_11DS;
1457 
1458 	/* Set IBSS param set */
1459 /** IBSS parameter IE Id */
1460 #define IBSS_PARA_IE_ID   6
1461 /** IBSS parameter IE length */
1462 #define IBSS_PARA_IE_LEN  2
1463 
1464 	padhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
1465 	padhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
1466 	padhoc_start->ss_param_set.ibss_param_set.atim_window
1467 		= wlan_cpu_to_le16(pmpriv->atim_window);
1468 	pbss_desc->atim_window = pmpriv->atim_window;
1469 	memcpy(pmadapter, &pbss_desc->ss_param_set,
1470 	       &padhoc_start->ss_param_set, sizeof(IEEEtypes_SsParamSet_t));
1471 
1472 	/* Set Capability info */
1473 	padhoc_start->cap.ess = 0;
1474 	padhoc_start->cap.ibss = 1;
1475 	pbss_desc->cap_info.ibss = 1;
1476 
1477 	/* Set up privacy in pbss_desc */
1478 	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled
1479 	    || pmpriv->adhoc_aes_enabled
1480 	    || pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
1481 /** Ad-Hoc capability privacy on */
1482 #define AD_HOC_CAP_PRIVACY_ON   1
1483 		PRINTM(MINFO, "ADHOC_S_CMD: wep_status set, Privacy to WEP\n");
1484 		pbss_desc->privacy = Wlan802_11PrivFilter8021xWEP;
1485 		padhoc_start->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
1486 	} else {
1487 		PRINTM(MWARN, "ADHOC_S_CMD: wep_status NOT set, Setting "
1488 		       "Privacy to ACCEPT ALL\n");
1489 		pbss_desc->privacy = Wlan802_11PrivFilterAcceptAll;
1490 	}
1491 
1492 	memset(pmadapter, padhoc_start->DataRate, 0,
1493 	       sizeof(padhoc_start->DataRate));
1494 
1495 	if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
1496 	     pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF)
1497 	    && (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
1498 		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
1499 					   BAND_B, padhoc_start->DataRate);
1500 	} else {
1501 		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
1502 					   pmadapter->adhoc_start_band,
1503 					   padhoc_start->DataRate);
1504 	}
1505 
1506 	if ((pmadapter->adhoc_start_band & BAND_G) &&
1507 	    (pmpriv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
1508 		ret = wlan_prepare_cmd(pmpriv,
1509 				       HostCmd_CMD_MAC_CONTROL,
1510 				       HostCmd_ACT_GEN_SET,
1511 				       0, MNULL, &pmpriv->curr_pkt_filter);
1512 
1513 		if (ret) {
1514 			PRINTM(MERROR,
1515 			       "ADHOC_S_CMD: G Protection config failed\n");
1516 			ret = MLAN_STATUS_FAILURE;
1517 			goto done;
1518 		}
1519 	}
1520 	/* Find the last non zero */
1521 	for (i = 0; i < sizeof(padhoc_start->DataRate)
1522 	     && padhoc_start->DataRate[i]; i++)
1523 		/* XXX Do not delete no-operation line */
1524 		;
1525 
1526 	pmpriv->curr_bss_params.num_of_rates = i;
1527 
1528 	/* Copy the ad-hoc creating rates into Current BSS rate structure */
1529 	memcpy(pmadapter, &pmpriv->curr_bss_params.data_rates,
1530 	       &padhoc_start->DataRate, pmpriv->curr_bss_params.num_of_rates);
1531 
1532 	PRINTM(MINFO, "ADHOC_S_CMD: Rates=%02x %02x %02x %02x\n",
1533 	       padhoc_start->DataRate[0], padhoc_start->DataRate[1],
1534 	       padhoc_start->DataRate[2], padhoc_start->DataRate[3]);
1535 
1536 	PRINTM(MINFO, "ADHOC_S_CMD: AD HOC Start command is ready\n");
1537 
1538 	if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
1539 		/* Append a channel TLV */
1540 		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
1541 		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
1542 		pchan_tlv->header.len =
1543 			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
1544 
1545 		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
1546 		       sizeof(ChanScanParamSet_t));
1547 		pchan_tlv->chan_scan_param[0].chan_number =
1548 			(t_u8)pmpriv->curr_bss_params.bss_descriptor.channel;
1549 
1550 		PRINTM(MINFO, "ADHOC_S_CMD: TLV Chan = %d\n",
1551 		       pchan_tlv->chan_scan_param[0].chan_number);
1552 
1553 		pchan_tlv->chan_scan_param[0].bandcfg.chanBand
1554 			= wlan_band_to_radio_type(pmpriv->curr_bss_params.band);
1555 		if (pmadapter->adhoc_start_band & BAND_GN
1556 		    || pmadapter->adhoc_start_band & BAND_AN) {
1557 			if (pmadapter->chan_bandwidth == CHANNEL_BW_40MHZ_ABOVE) {
1558 				pchan_tlv->chan_scan_param[0].bandcfg.
1559 					chan2Offset = SEC_CHAN_ABOVE;
1560 				pchan_tlv->chan_scan_param[0].bandcfg.
1561 					chanWidth = CHAN_BW_40MHZ;
1562 			} else if (pmadapter->chan_bandwidth ==
1563 				   CHANNEL_BW_40MHZ_BELOW) {
1564 				pchan_tlv->chan_scan_param[0].bandcfg.
1565 					chan2Offset = SEC_CHAN_BELOW;
1566 				pchan_tlv->chan_scan_param[0].bandcfg.
1567 					chanWidth = CHAN_BW_40MHZ;
1568 			}
1569 		}
1570 		PRINTM(MINFO, "ADHOC_S_CMD: TLV Bandcfg = %x\n",
1571 		       pchan_tlv->chan_scan_param[0].bandcfg);
1572 		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1573 		cmd_append_size +=
1574 			sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1575 	}
1576 
1577 	if (wlan_11d_create_dnld_countryinfo
1578 	    (pmpriv, pmpriv->curr_bss_params.band)) {
1579 		PRINTM(MERROR, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
1580 		ret = MLAN_STATUS_FAILURE;
1581 		goto done;
1582 	}
1583 
1584 	/*
1585 	 * Call 11h start API to add any 11h flags/elements as TLV parameters
1586 	 */
1587 	append_size_11h =
1588 		wlan_11h_process_start(pmpriv, &pos, &padhoc_start->cap,
1589 				       pmpriv->adhoc_channel,
1590 				       &pbss_desc->wlan_11h_bss_info);
1591 	if (append_size_11h >= 0)
1592 		cmd_append_size += append_size_11h;
1593 	else {
1594 		ret = MLAN_STATUS_FAILURE;
1595 		goto done;
1596 	}
1597 
1598 	if (pmpriv->sec_info.ewpa_enabled) {
1599 		memcpy(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(wpa_ie));
1600 		pmpriv->wpa_ie_len = sizeof(wpa_ie);
1601 	}
1602 
1603 	if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
1604 		prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1605 		prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
1606 		/* WPA_IE or RSN_IE */
1607 		prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
1608 		prsn_ie_tlv->header.type =
1609 			wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1610 		prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
1611 		prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
1612 		if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
1613 			memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
1614 			       &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len);
1615 		else {
1616 			ret = MLAN_STATUS_FAILURE;
1617 			goto done;
1618 		}
1619 
1620 		DBG_HEXDUMP(MCMD_D, "ADHOC_S_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
1621 			    sizeof(prsn_ie_tlv->header) +
1622 			    prsn_ie_tlv->header.len);
1623 		pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1624 		cmd_append_size +=
1625 			sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1626 		prsn_ie_tlv->header.len =
1627 			wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1628 	}
1629 
1630 	if (pmadapter->adhoc_11n_enabled == MTRUE) {
1631 		{
1632 			pht_cap = (MrvlIETypes_HTCap_t *)pos;
1633 			memset(pmadapter, pht_cap, 0,
1634 			       sizeof(MrvlIETypes_HTCap_t));
1635 			pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
1636 			pht_cap->header.len = sizeof(HTCap_t);
1637 			rx_mcs_supp =
1638 				GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
1639 			/* Set MCS for 1x1/2x2 */
1640 			memset(pmadapter,
1641 			       (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
1642 			       rx_mcs_supp);
1643 			wlan_fill_ht_cap_tlv(pmpriv, pht_cap,
1644 					     pmpriv->curr_bss_params.band,
1645 					     MTRUE);
1646 			HEXDUMP("ADHOC_START: HT_CAPABILITIES IE",
1647 				(t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
1648 			pos += sizeof(MrvlIETypes_HTCap_t);
1649 			cmd_append_size += sizeof(MrvlIETypes_HTCap_t);
1650 			pht_cap->header.len =
1651 				wlan_cpu_to_le16(pht_cap->header.len);
1652 		}
1653 		{
1654 			pht_info = (MrvlIETypes_HTInfo_t *)pos;
1655 			memset(pmadapter, pht_info, 0,
1656 			       sizeof(MrvlIETypes_HTInfo_t));
1657 			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
1658 			pht_info->header.len = sizeof(HTInfo_t);
1659 			pht_info->ht_info.pri_chan =
1660 				(t_u8)pmpriv->curr_bss_params.bss_descriptor.
1661 				channel;
1662 			if ((pmadapter->chan_bandwidth ==
1663 			     CHANNEL_BW_40MHZ_ABOVE) ||
1664 			    (pmadapter->chan_bandwidth ==
1665 			     CHANNEL_BW_40MHZ_BELOW)) {
1666 				pht_info->ht_info.field2 =
1667 					pmadapter->chan_bandwidth;
1668 				SET_CHANWIDTH40(pht_info->ht_info.field2);
1669 			}
1670 			pht_info->ht_info.field3 =
1671 				wlan_cpu_to_le16(NON_GREENFIELD_STAS);
1672 			pht_info->ht_info.basic_mcs_set[0] = 0xff;
1673 			HEXDUMP("ADHOC_START: HT_INFORMATION IE",
1674 				(t_u8 *)pht_info, sizeof(MrvlIETypes_HTInfo_t));
1675 			pos += sizeof(MrvlIETypes_HTInfo_t);
1676 			cmd_append_size += sizeof(MrvlIETypes_HTInfo_t);
1677 			pht_info->header.len =
1678 				wlan_cpu_to_le16(pht_info->header.len);
1679 		}
1680 	}
1681 
1682 	cmd->size =
1683 		(t_u16)
1684 		wlan_cpu_to_le16((t_u16)(sizeof(HostCmd_DS_802_11_AD_HOC_START)
1685 					 + S_DS_GEN + cmd_append_size));
1686 
1687 	memcpy(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16));
1688 
1689 	if (pmadapter->adhoc_start_band == BAND_B)
1690 		SHORT_SLOT_TIME_DISABLED(tmp_cap);
1691 	else
1692 		SHORT_SLOT_TIME_ENABLED(tmp_cap);
1693 
1694 	tmp_cap = wlan_cpu_to_le16(tmp_cap);
1695 	memcpy(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16));
1696 
1697 	ret = MLAN_STATUS_SUCCESS;
1698 done:
1699 	LEAVE();
1700 	return ret;
1701 }
1702 
1703 /**
1704  *  @brief This function prepares command of ad_hoc_join.
1705  *
1706  *  @param pmpriv       A pointer to mlan_private structure
1707  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1708  *  @param pdata_buf    Void cast of BSSDescriptor_t from the
1709  *                        scan table to join
1710  *
1711  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1712  */
1713 mlan_status
wlan_cmd_802_11_ad_hoc_join(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_void * pdata_buf)1714 wlan_cmd_802_11_ad_hoc_join(IN mlan_private *pmpriv,
1715 			    IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
1716 {
1717 	mlan_status ret = MLAN_STATUS_SUCCESS;
1718 	mlan_adapter *pmadapter = pmpriv->adapter;
1719 	HostCmd_DS_802_11_AD_HOC_JOIN *padhoc_join = &cmd->params.adhoc_join;
1720 	BSSDescriptor_t *pbss_desc = (BSSDescriptor_t *)pdata_buf;
1721 	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
1722 	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
1723 	t_u32 cmd_append_size = 0;
1724 	t_u16 tmp_cap;
1725 	t_u32 i, rates_size = 0;
1726 	t_u32 curr_pkt_filter;
1727 	t_u8 *pos = (t_u8 *)padhoc_join + sizeof(HostCmd_DS_802_11_AD_HOC_JOIN);
1728 
1729 	ENTER();
1730 
1731 /** Use G protection */
1732 #define USE_G_PROTECTION        0x02
1733 	if (pbss_desc->erp_flags & USE_G_PROTECTION) {
1734 		curr_pkt_filter =
1735 			pmpriv->
1736 			curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
1737 
1738 		ret = wlan_prepare_cmd(pmpriv,
1739 				       HostCmd_CMD_MAC_CONTROL,
1740 				       HostCmd_ACT_GEN_SET,
1741 				       0, MNULL, &curr_pkt_filter);
1742 		if (ret) {
1743 			PRINTM(MERROR,
1744 			       "ADHOC_J_CMD: G Protection config failed\n");
1745 			ret = MLAN_STATUS_FAILURE;
1746 			goto done;
1747 		}
1748 	}
1749 
1750 	pmpriv->pattempted_bss_desc = pbss_desc;
1751 
1752 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
1753 
1754 	padhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
1755 
1756 	padhoc_join->bss_descriptor.beacon_period
1757 		= wlan_cpu_to_le16(pbss_desc->beacon_period);
1758 
1759 	memcpy(pmadapter, &padhoc_join->bss_descriptor.bssid,
1760 	       &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
1761 
1762 	memcpy(pmadapter, &padhoc_join->bss_descriptor.ssid,
1763 	       &pbss_desc->ssid.ssid,
1764 	       MIN(MLAN_MAX_SSID_LENGTH, pbss_desc->ssid.ssid_len));
1765 
1766 	memcpy(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
1767 	       &pbss_desc->phy_param_set, sizeof(IEEEtypes_PhyParamSet_t));
1768 
1769 	padhoc_join->bss_descriptor.phy_param_set.fh_param_set.dwell_time
1770 		=
1771 		wlan_cpu_to_le16(padhoc_join->bss_descriptor.phy_param_set.
1772 				 fh_param_set.dwell_time);
1773 
1774 	memcpy(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
1775 	       &pbss_desc->ss_param_set, sizeof(IEEEtypes_SsParamSet_t));
1776 	padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window
1777 		=
1778 		wlan_cpu_to_le16(padhoc_join->bss_descriptor.ss_param_set.
1779 				 ibss_param_set.atim_window);
1780 
1781 	memcpy(pmadapter, &tmp_cap, &pbss_desc->cap_info,
1782 	       sizeof(IEEEtypes_CapInfo_t));
1783 
1784 	tmp_cap &= CAPINFO_MASK;
1785 
1786 	PRINTM(MINFO, "ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
1787 	       tmp_cap, CAPINFO_MASK);
1788 	memcpy(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
1789 	       sizeof(IEEEtypes_CapInfo_t));
1790 
1791 	/* Information on BSSID descriptor passed to FW */
1792 	PRINTM(MINFO,
1793 	       "ADHOC_J_CMD: BSSID = " MACSTR ", SSID = %s\n",
1794 	       MAC2STR(padhoc_join->bss_descriptor.bssid),
1795 	       padhoc_join->bss_descriptor.ssid);
1796 
1797 	for (i = 0; i < WLAN_SUPPORTED_RATES && pbss_desc->supported_rates[i];
1798 	     i++)
1799 		/* XXX Do not delete no-operation line */
1800 		;
1801 	rates_size = i;
1802 
1803 	/* Copy Data Rates from the Rates recorded in scan response */
1804 	memset(pmadapter, padhoc_join->bss_descriptor.data_rates, 0,
1805 	       sizeof(padhoc_join->bss_descriptor.data_rates));
1806 	memcpy(pmadapter, padhoc_join->bss_descriptor.data_rates,
1807 	       pbss_desc->supported_rates, rates_size);
1808 
1809 	HEXDUMP("Adapted Rates:", padhoc_join->bss_descriptor.data_rates,
1810 		rates_size);
1811 
1812 	/* Copy the adhoc join rates into Current BSS state structure */
1813 	pmpriv->curr_bss_params.num_of_rates = rates_size;
1814 	memcpy(pmadapter, &pmpriv->curr_bss_params.data_rates,
1815 	       pbss_desc->supported_rates, rates_size);
1816 
1817 	/* Copy the channel information */
1818 	pmpriv->curr_bss_params.bss_descriptor.channel = pbss_desc->channel;
1819 	pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
1820 
1821 	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled
1822 	    || pmpriv->adhoc_aes_enabled
1823 	    || pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled)
1824 		padhoc_join->bss_descriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
1825 
1826 	if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
1827 		/* Append a channel TLV */
1828 		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
1829 		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
1830 		pchan_tlv->header.len =
1831 			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
1832 
1833 		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
1834 		       sizeof(ChanScanParamSet_t));
1835 		pchan_tlv->chan_scan_param[0].chan_number =
1836 			(pbss_desc->phy_param_set.ds_param_set.current_chan);
1837 		PRINTM(MINFO, "ADHOC_J_CMD: TLV Chan = %d\n",
1838 		       pchan_tlv->chan_scan_param[0].chan_number);
1839 
1840 		pchan_tlv->chan_scan_param[0].bandcfg.chanBand
1841 			= wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
1842 
1843 		PRINTM(MINFO, "ADHOC_J_CMD: TLV Bandcfg = %x\n",
1844 		       pchan_tlv->chan_scan_param[0].bandcfg);
1845 		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1846 		cmd_append_size +=
1847 			sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
1848 	}
1849 
1850 	if (wlan_11d_create_dnld_countryinfo(pmpriv, (t_u8)pbss_desc->bss_band)) {
1851 		PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
1852 		ret = MLAN_STATUS_FAILURE;
1853 		goto done;
1854 	}
1855 	if (wlan_11d_parse_dnld_countryinfo
1856 	    (pmpriv, pmpriv->pattempted_bss_desc)) {
1857 		ret = MLAN_STATUS_FAILURE;
1858 		goto done;
1859 	}
1860 
1861 	/*
1862 	 * Call 11h join API after capability bits are set so
1863 	 *   adhoc/infra 11h behavior can be properly triggered.
1864 	 *   pos modified if data is appended
1865 	 */
1866 	cmd_append_size += wlan_11h_process_join(pmpriv, &pos,
1867 						 &padhoc_join->bss_descriptor.
1868 						 cap, (t_u8)pbss_desc->bss_band,
1869 						 pbss_desc->channel,
1870 						 &pbss_desc->wlan_11h_bss_info);
1871 
1872 	if (pmpriv->sec_info.wpa_enabled) {
1873 		prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1874 		/* WPA_IE or RSN_IE */
1875 		prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
1876 		prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
1877 		prsn_ie_tlv->header.type =
1878 			wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1879 		prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
1880 		prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
1881 		if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
1882 			memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
1883 			       &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len);
1884 		else {
1885 			ret = MLAN_STATUS_FAILURE;
1886 			goto done;
1887 		}
1888 
1889 		HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
1890 			sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len);
1891 		pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1892 		cmd_append_size +=
1893 			sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
1894 		prsn_ie_tlv->header.len =
1895 			wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1896 	} else if (pmpriv->sec_info.ewpa_enabled) {
1897 		prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1898 		if (pbss_desc->pwpa_ie) {
1899 			prsn_ie_tlv->header.type =
1900 				(t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.
1901 				element_id;
1902 			prsn_ie_tlv->header.type =
1903 				prsn_ie_tlv->header.type & 0x00FF;
1904 			prsn_ie_tlv->header.type =
1905 				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1906 			prsn_ie_tlv->header.len =
1907 				(t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.len;
1908 			prsn_ie_tlv->header.len =
1909 				prsn_ie_tlv->header.len & 0x00FF;
1910 			if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie))) {
1911 				memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
1912 				       &((*(pbss_desc->pwpa_ie)).vend_hdr.
1913 					 oui[0]), prsn_ie_tlv->header.len);
1914 			} else {
1915 				ret = MLAN_STATUS_FAILURE;
1916 				goto done;
1917 			}
1918 
1919 			HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
1920 				sizeof(prsn_ie_tlv->header) +
1921 				prsn_ie_tlv->header.len);
1922 			pos += sizeof(prsn_ie_tlv->header) +
1923 				prsn_ie_tlv->header.len;
1924 			cmd_append_size +=
1925 				sizeof(prsn_ie_tlv->header) +
1926 				prsn_ie_tlv->header.len;
1927 			prsn_ie_tlv->header.len =
1928 				wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1929 		}
1930 		if (pbss_desc->prsn_ie) {
1931 			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
1932 			prsn_ie_tlv->header.type =
1933 				(t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.
1934 				element_id;
1935 			prsn_ie_tlv->header.type =
1936 				prsn_ie_tlv->header.type & 0x00FF;
1937 			prsn_ie_tlv->header.type =
1938 				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
1939 			prsn_ie_tlv->header.len =
1940 				(t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.len;
1941 			prsn_ie_tlv->header.len =
1942 				prsn_ie_tlv->header.len & 0x00FF;
1943 			if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie))) {
1944 				memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
1945 				       &((*(pbss_desc->prsn_ie)).data[0])
1946 				       , prsn_ie_tlv->header.len);
1947 			} else {
1948 				ret = MLAN_STATUS_FAILURE;
1949 				goto done;
1950 			}
1951 
1952 			HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
1953 				sizeof(prsn_ie_tlv->header) +
1954 				prsn_ie_tlv->header.len);
1955 			pos += sizeof(prsn_ie_tlv->header) +
1956 				prsn_ie_tlv->header.len;
1957 			cmd_append_size +=
1958 				sizeof(prsn_ie_tlv->header) +
1959 				prsn_ie_tlv->header.len;
1960 			prsn_ie_tlv->header.len =
1961 				wlan_cpu_to_le16(prsn_ie_tlv->header.len);
1962 		}
1963 	}
1964 
1965 	if (ISSUPP_11NENABLED(pmadapter->fw_cap_info)
1966 	    && wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band)
1967 		)
1968 		cmd_append_size +=
1969 			wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
1970 
1971 	cmd->size =
1972 		(t_u16)
1973 		wlan_cpu_to_le16((t_u16)(sizeof(HostCmd_DS_802_11_AD_HOC_JOIN)
1974 					 + S_DS_GEN + cmd_append_size));
1975 
1976 	memcpy(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
1977 	       sizeof(IEEEtypes_CapInfo_t));
1978 	tmp_cap = wlan_cpu_to_le16(tmp_cap);
1979 
1980 	memcpy(pmadapter, &padhoc_join->bss_descriptor.cap,
1981 	       &tmp_cap, sizeof(IEEEtypes_CapInfo_t));
1982 
1983 done:
1984 	LEAVE();
1985 	return ret;
1986 }
1987 
1988 /**
1989  *  @brief This function handles the command response of ad_hoc_start and
1990  *          ad_hoc_join
1991  *
1992  *  @param pmpriv       A pointer to mlan_private structure
1993  *  @param resp         A pointer to HostCmd_DS_COMMAND
1994  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1995  *
1996  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1997  */
1998 mlan_status
wlan_ret_802_11_ad_hoc(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * resp,IN t_void * pioctl_buf)1999 wlan_ret_802_11_ad_hoc(IN mlan_private *pmpriv,
2000 		       IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
2001 {
2002 	mlan_status ret = MLAN_STATUS_SUCCESS;
2003 	mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2004 	HostCmd_DS_802_11_AD_HOC_START_RESULT *padhoc_start_result =
2005 		&resp->params.adhoc_start_result;
2006 	HostCmd_DS_802_11_AD_HOC_JOIN_RESULT *padhoc_join_result =
2007 		&resp->params.adhoc_join_result;
2008 	BSSDescriptor_t *pbss_desc;
2009 	t_u16 command = resp->command;
2010 	t_u8 result = 0;
2011 	t_u8 event_buf[100];
2012 	mlan_event *pevent = (mlan_event *)event_buf;
2013 	int ie_len = 0;
2014 	IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
2015 	mlan_adapter *pmadapter = pmpriv->adapter;
2016 	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
2017 
2018 	ENTER();
2019 
2020 	pmpriv->wmm_enabled = MFALSE;
2021 	if (command == HostCmd_CMD_802_11_AD_HOC_START) {
2022 		result = padhoc_start_result->result;
2023 		ie_len = resp->size -
2024 			(sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
2025 			 S_DS_GEN);
2026 		pwmm_param_ie =
2027 			(IEEEtypes_WmmParameter_t *)((t_u8 *)resp +
2028 						     (sizeof
2029 						      (HostCmd_DS_802_11_AD_HOC_START_RESULT)
2030 						      + S_DS_GEN));
2031 	} else {
2032 		result = padhoc_join_result->result;
2033 		ie_len = resp->size -
2034 			(sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
2035 			 S_DS_GEN);
2036 		pwmm_param_ie =
2037 			(IEEEtypes_WmmParameter_t *)((t_u8 *)resp +
2038 						     (sizeof
2039 						      (HostCmd_DS_802_11_AD_HOC_JOIN_RESULT)
2040 						      + S_DS_GEN));
2041 	}
2042 
2043 	pbss_desc = pmpriv->pattempted_bss_desc;
2044 
2045 	/*
2046 	 * Join result code 0 --> SUCCESS
2047 	 */
2048 	if (result) {
2049 		PRINTM(MERROR, "ADHOC_RESP Failed 0x%x\n", result);
2050 		if (pmpriv->media_connected == MTRUE)
2051 			wlan_reset_connect_state(pmpriv, MTRUE);
2052 		if (pmpriv->adhoc_state == ADHOC_STARTING)
2053 			pmpriv->adhoc_state = ADHOC_IDLE;
2054 
2055 		memset(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
2056 		       0x00, sizeof(BSSDescriptor_t));
2057 
2058 		ret = MLAN_STATUS_FAILURE;
2059 		goto done;
2060 	}
2061 
2062 	/* Send a Media Connected event, according to the Spec */
2063 	pmpriv->media_connected = MTRUE;
2064 
2065 	if (command == HostCmd_CMD_802_11_AD_HOC_START) {
2066 		PRINTM(MINFO, "ADHOC_S_RESP  %s\n", pbss_desc->ssid.ssid);
2067 
2068 		/* Update the created network descriptor with the new BSSID */
2069 		memcpy(pmpriv->adapter, pbss_desc->mac_address,
2070 		       padhoc_start_result->bssid, MLAN_MAC_ADDR_LENGTH);
2071 
2072 		pmpriv->adhoc_state = ADHOC_STARTED;
2073 		if (pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS)
2074 			wlan_11h_radar_detected_callback((t_void *)pmpriv);
2075 	} else {
2076 		/*
2077 		 * Now the join cmd should be successful.
2078 		 * If BSSID has changed use SSID to compare instead of BSSID
2079 		 */
2080 		PRINTM(MINFO, "ADHOC_J_RESP  %s\n", pbss_desc->ssid.ssid);
2081 
2082 		/*
2083 		 * Make a copy of current BSSID descriptor, only needed
2084 		 * for join since the current descriptor is already
2085 		 * being used for adhoc start
2086 		 */
2087 		memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
2088 		       pbss_desc, sizeof(BSSDescriptor_t));
2089 
2090 		pmpriv->adhoc_state = ADHOC_JOINED;
2091 	}
2092 
2093     /** process wmm ie */
2094 	if (ie_len >= sizeof(IEEEtypes_VendorHeader_t)) {
2095 		if ((pwmm_param_ie->vend_hdr.element_id == VENDOR_SPECIFIC_221)
2096 		    && !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
2097 			       sizeof(wmm_oui)) &&
2098 		    (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
2099 			DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
2100 				    ie_len);
2101 			memcpy(pmpriv->adapter,
2102 			       (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
2103 			       wmm_ie, pwmm_param_ie,
2104 			       MIN(sizeof(IEEEtypes_WmmParameter_t),
2105 				   (pwmm_param_ie->vend_hdr.len + 2)));
2106 			pmpriv->wmm_enabled = MTRUE;
2107 			wlan_wmm_setup_queue_priorities(pmpriv, pwmm_param_ie);
2108 			wlan_wmm_setup_ac_downgrade(pmpriv);
2109 		}
2110 	}
2111 	/* Since WMM is not enabled, setup the queues with the defaults */
2112 	if (!pmpriv->wmm_enabled)
2113 		wlan_wmm_setup_queues(pmpriv);
2114 
2115 	PRINTM(MINFO, "ADHOC_RESP: Channel = %d\n", pmpriv->adhoc_channel);
2116 	PRINTM(MINFO, "ADHOC_RESP: BSSID = " MACSTR "\n",
2117 	       MAC2STR(pmpriv->curr_bss_params.bss_descriptor.mac_address));
2118 
2119 	pevent->bss_index = pmpriv->bss_index;
2120 	pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
2121 	pevent->event_len = MLAN_MAC_ADDR_LENGTH;
2122 	memcpy(pmpriv->adapter, (t_u8 *)pevent->event_buf,
2123 	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
2124 	       MLAN_MAC_ADDR_LENGTH);
2125 	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
2126 	wlan_save_curr_bcn(pmpriv);
2127 
2128 done:
2129 	/* Need to indicate IOCTL complete */
2130 	if (pioctl_req != MNULL) {
2131 		if (ret != MLAN_STATUS_SUCCESS)
2132 			pioctl_req->status_code = MLAN_ERROR_CMD_ASSOC_FAIL;
2133 		else
2134 			pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
2135 	}
2136 
2137 	LEAVE();
2138 	return ret;
2139 }
2140 
2141 /**
2142  *  @brief Associated to a specific BSS discovered in a scan
2143  *
2144  *  @param pmpriv       A pointer to mlan_private structure
2145  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
2146  *  @param pbss_desc     A pointer to the BSS descriptor to associate with.
2147  *
2148  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2149  */
2150 mlan_status
wlan_associate(IN mlan_private * pmpriv,IN t_void * pioctl_buf,IN BSSDescriptor_t * pbss_desc)2151 wlan_associate(IN mlan_private *pmpriv,
2152 	       IN t_void *pioctl_buf, IN BSSDescriptor_t *pbss_desc)
2153 {
2154 	mlan_status ret = MLAN_STATUS_SUCCESS;
2155 	t_u8 current_bssid[MLAN_MAC_ADDR_LENGTH];
2156 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2157 
2158 	ENTER();
2159 
2160 	/* Return error if the pmadapter or table entry
2161 	 *  is not marked as infra */
2162 	if ((pmpriv->bss_mode != MLAN_BSS_MODE_INFRA) ||
2163 	    (pbss_desc->bss_mode != MLAN_BSS_MODE_INFRA)) {
2164 		if (pioctl_req)
2165 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2166 		LEAVE();
2167 		return MLAN_STATUS_FAILURE;
2168 	}
2169 
2170 	memcpy(pmpriv->adapter, &current_bssid,
2171 	       &pmpriv->curr_bss_params.bss_descriptor.mac_address,
2172 	       sizeof(current_bssid));
2173 
2174 	/* Clear any past association response stored for application retrieval */
2175 	pmpriv->assoc_rsp_size = 0;
2176 
2177 	ret = wlan_prepare_cmd(pmpriv,
2178 			       HostCmd_CMD_802_11_ASSOCIATE,
2179 			       HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
2180 
2181 	LEAVE();
2182 	return ret;
2183 }
2184 
2185 /**
2186  *  @brief Start an Adhoc Network
2187  *
2188  *  @param pmpriv       A pointer to mlan_private structure
2189  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
2190  *  @param padhoc_ssid  The ssid of the Adhoc Network
2191  *
2192  *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
2193  */
2194 mlan_status
wlan_adhoc_start(IN mlan_private * pmpriv,IN t_void * pioctl_buf,IN mlan_802_11_ssid * padhoc_ssid)2195 wlan_adhoc_start(IN mlan_private *pmpriv,
2196 		 IN t_void *pioctl_buf, IN mlan_802_11_ssid *padhoc_ssid)
2197 {
2198 	mlan_status ret = MLAN_STATUS_SUCCESS;
2199 	wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
2200 	t_u8 radar = MFALSE;
2201 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2202 
2203 	ENTER();
2204 
2205 	/*
2206 	 * If the report indicates no measurement was done, leave the default
2207 	 * return value alone.
2208 	 */
2209 	if (!pmeas_state->meas_rpt_returned.rpt.basic.map.unmeasured) {
2210 		radar = pmeas_state->meas_rpt_returned.rpt.basic.map.
2211 			radar ? MTRUE : MFALSE;
2212 	}
2213 
2214 	if (radar) {
2215 		if (pioctl_req)
2216 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2217 		ret = MLAN_STATUS_FAILURE;
2218 		LEAVE();
2219 		return ret;
2220 	}
2221 
2222 	PRINTM(MINFO, "Adhoc Channel = %d\n", pmpriv->adhoc_channel);
2223 	PRINTM(MINFO, "curr_bss_params.channel = %d\n",
2224 	       pmpriv->curr_bss_params.bss_descriptor.channel);
2225 	PRINTM(MINFO, "curr_bss_params.band = %d\n",
2226 	       pmpriv->curr_bss_params.band);
2227 
2228 	ret = wlan_prepare_cmd(pmpriv,
2229 			       HostCmd_CMD_802_11_AD_HOC_START,
2230 			       HostCmd_ACT_GEN_SET, 0, pioctl_buf, padhoc_ssid);
2231 #if defined(STA_SUPPORT)
2232 	if (ret == MLAN_STATUS_SUCCESS)
2233 		memcpy(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
2234 		       padhoc_ssid, sizeof(mlan_802_11_ssid));
2235 #endif
2236 
2237 	LEAVE();
2238 	return ret;
2239 }
2240 
2241 /**
2242  *  @brief Join an adhoc network found in a previous scan
2243  *
2244  *  @param pmpriv       A pointer to mlan_private structure
2245  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
2246  *  @param pbss_desc     A pointer to the BSS descriptor found in a previous scan
2247  *                      to attempt to join
2248  *
2249  *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
2250  */
2251 mlan_status
wlan_adhoc_join(IN mlan_private * pmpriv,IN t_void * pioctl_buf,IN BSSDescriptor_t * pbss_desc)2252 wlan_adhoc_join(IN mlan_private *pmpriv,
2253 		IN t_void *pioctl_buf, IN BSSDescriptor_t *pbss_desc)
2254 {
2255 	pmlan_adapter pmadapter = pmpriv->adapter;
2256 	mlan_status ret = MLAN_STATUS_SUCCESS;
2257 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2258 
2259 	ENTER();
2260 
2261 	PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid =%s\n",
2262 	       pmpriv->curr_bss_params.bss_descriptor.ssid.ssid);
2263 	PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid_len =%u\n",
2264 	       pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len);
2265 	PRINTM(MINFO, "wlan_adhoc_join: ssid =%s\n", pbss_desc->ssid.ssid);
2266 	PRINTM(MINFO, "wlan_adhoc_join: ssid len =%u\n",
2267 	       pbss_desc->ssid.ssid_len);
2268 
2269 	/* Check if the requested SSID is already joined */
2270 	if (pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
2271 	    !wlan_ssid_cmp(pmadapter, &pbss_desc->ssid,
2272 			   &pmpriv->curr_bss_params.bss_descriptor.ssid) &&
2273 	    (pmpriv->curr_bss_params.bss_descriptor.bss_mode ==
2274 	     MLAN_BSS_MODE_IBSS)) {
2275 
2276 		PRINTM(MINFO,
2277 		       "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
2278 		       "not attempting to re-join\n");
2279 
2280 		if (pioctl_req)
2281 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2282 		LEAVE();
2283 		return MLAN_STATUS_FAILURE;
2284 	}
2285 
2286 	PRINTM(MINFO, "curr_bss_params.channel = %d\n",
2287 	       pmpriv->curr_bss_params.bss_descriptor.channel);
2288 	PRINTM(MINFO, "curr_bss_params.band = %d\n",
2289 	       pmpriv->curr_bss_params.band);
2290 
2291 	ret = wlan_prepare_cmd(pmpriv,
2292 			       HostCmd_CMD_802_11_AD_HOC_JOIN,
2293 			       HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
2294 
2295 	LEAVE();
2296 	return ret;
2297 }
2298 
2299 /**
2300  *  @brief Send Deauthentication Request or Stop the AdHoc network depending on mode
2301  *
2302  *  @param pmpriv    A pointer to mlan_private structure
2303  *  @param pioctl_req A pointer to mlan_ioctl_req structure
2304  *  @param deauth_param A pointer to mlan_deauth_param structure
2305  *
2306  *  @return          MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail, MLAN_STATUS_PENDING--pending
2307  */
2308 mlan_status
wlan_disconnect(IN mlan_private * pmpriv,IN mlan_ioctl_req * pioctl_req,IN mlan_deauth_param * deauth_param)2309 wlan_disconnect(IN mlan_private *pmpriv,
2310 		IN mlan_ioctl_req *pioctl_req,
2311 		IN mlan_deauth_param *deauth_param)
2312 {
2313 	mlan_status ret = MLAN_STATUS_SUCCESS;
2314 	mlan_deauth_param local_param = {
2315 		.mac_addr = {0, 0, 0, 0, 0, 0},
2316 		.reason_code = DEF_DEAUTH_REASON_CODE
2317 	};
2318 	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
2319 
2320 	ENTER();
2321 
2322 	if (deauth_param)
2323 		memcpy(pmpriv->adapter, &local_param, deauth_param,
2324 		       sizeof(*deauth_param));
2325 	if (pmpriv->media_connected == MTRUE) {
2326 		if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
2327 			if (!deauth_param ||
2328 			    !memcmp(pmpriv->adapter, deauth_param->mac_addr,
2329 				    zero_mac, sizeof(zero_mac)))
2330 				memcpy(pmpriv->adapter, local_param.mac_addr,
2331 				       (t_u8 *)&pmpriv->curr_bss_params.
2332 				       bss_descriptor.mac_address,
2333 				       MLAN_MAC_ADDR_LENGTH);
2334 #ifdef WIFI_DIRECT_SUPPORT
2335 			if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
2336 				ret = wlan_prepare_cmd(pmpriv,
2337 						       HostCmd_CMD_802_11_DISASSOCIATE,
2338 						       HostCmd_ACT_GEN_SET,
2339 						       0,
2340 						       (t_void *)pioctl_req,
2341 						       &local_param);
2342 			else
2343 #endif
2344 				ret = wlan_prepare_cmd(pmpriv,
2345 						       HostCmd_CMD_802_11_DEAUTHENTICATE,
2346 						       HostCmd_ACT_GEN_SET,
2347 						       0,
2348 						       (t_void *)pioctl_req,
2349 						       &local_param);
2350 
2351 			if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
2352 				ret = MLAN_STATUS_PENDING;
2353 
2354 		} else if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
2355 			ret = wlan_prepare_cmd(pmpriv,
2356 					       HostCmd_CMD_802_11_AD_HOC_STOP,
2357 					       HostCmd_ACT_GEN_SET,
2358 					       0, (t_void *)pioctl_req, MNULL);
2359 
2360 			if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
2361 				ret = MLAN_STATUS_PENDING;
2362 		}
2363 	}
2364 
2365 	LEAVE();
2366 	return ret;
2367 }
2368 
2369 /**
2370  *  @brief Convert band to radio type used in channel TLV
2371  *
2372  *  @param band     Band enumeration to convert to a channel TLV radio type
2373  *
2374  *  @return         Radio type designator for use in a channel TLV
2375  */
2376 t_u8
wlan_band_to_radio_type(IN t_u8 band)2377 wlan_band_to_radio_type(IN t_u8 band)
2378 {
2379 	t_u8 ret_radio_type;
2380 
2381 	ENTER();
2382 
2383 	switch (band) {
2384 	case BAND_A:
2385 	case BAND_AN:
2386 	case BAND_A | BAND_AN:
2387 		ret_radio_type = BAND_5GHZ;
2388 		break;
2389 	case BAND_B:
2390 	case BAND_G:
2391 	case BAND_B | BAND_G:
2392 	default:
2393 		ret_radio_type = BAND_2GHZ;
2394 		break;
2395 	}
2396 
2397 	LEAVE();
2398 	return ret_radio_type;
2399 }
2400