blob: 365b3492fa017d684dc417e93dd1d35e3a424181 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*
29 * This file sch_beacon_gen.cc contains beacon generation related
30 * functions
31 *
32 * Author: Sandesh Goel
33 * Date: 02/25/02
34 * History:-
35 * Date Modified by Modification Information
36 * --------------------------------------------------------------------
37 *
38 */
39
40#include "cds_api.h"
41#include "wni_cfg.h"
42#include "ani_global.h"
43#include "sir_mac_prot_def.h"
44
45#include "lim_utils.h"
46#include "lim_api.h"
47
48#include "wma_if.h"
49#include "cfg_api.h"
50#include "sch_api.h"
51
52#include "parser_api.h"
53
54#include "sch_debug.h"
55
56/* */
57/* March 15, 2006 */
58/* Temporarily (maybe for all of Alpha-1), assuming TIM = 0 */
59/* */
60
61const uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x9 };
62
63tSirRetStatus sch_get_p2p_ie_offset(uint8_t *pExtraIe, uint32_t extraIeLen,
64 uint16_t *pP2pIeOffset)
65{
66 tSirRetStatus status = eSIR_FAILURE;
67 *pP2pIeOffset = 0;
68
69 /* Extra IE is not present */
70 if (0 == extraIeLen) {
71 return status;
72 }
73 /* Calculate the P2P IE Offset */
74 do {
75 if (*pExtraIe == 0xDD) {
76 if (cdf_mem_compare
77 ((void *)(pExtraIe + 2), &p2p_oui, sizeof(p2p_oui))) {
78 status = eSIR_SUCCESS;
79 break;
80 }
81 }
82
83 (*pP2pIeOffset)++;
84 pExtraIe++;
85 } while (--extraIeLen > 0);
86
87 return status;
88}
89
90/**
91 * sch_append_addn_ie() - adds additional IEs to frame
92 * @mac_ctx: mac global context
93 * @session: pe session pointer
94 * @frm: frame where additional IE is to be added
95 * @max_bcn_size: max beacon size
96 * @num_bytes: final size
97 *
98 * Return: status of operation
99 */
100tSirRetStatus
101sch_append_addn_ie(tpAniSirGlobal mac_ctx, tpPESession session,
102 uint8_t *frm, uint32_t max_bcn_size, uint32_t *num_bytes)
103{
104 tSirRetStatus status = eSIR_FAILURE;
105 uint32_t present, len;
106 uint8_t add_ie[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN];
107 uint8_t *p2p_ie = NULL;
108 uint8_t noa_len = 0;
109 uint8_t noa_strm[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
110
111 present = (session->addIeParams.probeRespBCNDataLen != 0);
112 if (!present)
113 return status;
114
115 len = session->addIeParams.probeRespBCNDataLen;
116 if (!(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
117 ((len + *num_bytes) <= max_bcn_size)))
118 return status;
119
120 cdf_mem_copy(&add_ie[0], session->addIeParams.probeRespBCNData_buff,
121 len);
122
123 p2p_ie = limGetP2pIEPtr(mac_ctx, &add_ie[0], len);
124 if ((p2p_ie != NULL) && !mac_ctx->beacon_offload) {
125 /* get NoA attribute stream P2P IE */
126 noa_len = lim_get_noa_attr_stream(mac_ctx, noa_strm, session);
127 if (noa_len) {
128 if ((noa_len + len) <=
129 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
130 cdf_mem_copy(&add_ie[len], noa_strm, noa_len);
131 len += noa_len;
132 p2p_ie[1] += noa_len;
133 } else {
134 sch_log(mac_ctx, LOGE,
135 FL("Not able to insert NoA because of length constraint"));
136 }
137 }
138 }
139 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
140 cdf_mem_copy(frm, &add_ie[0], len);
141 *num_bytes = *num_bytes + len;
142 } else {
143 sch_log(mac_ctx, LOGW,
144 FL("Not able to insert because of len constraint %d"),
145 len);
146 }
147 return status;
148}
149
150/**
151 * sch_set_fixed_beacon_fields() - sets the fixed params in beacon frame
152 * @mac_ctx: mac global context
153 * @session: pe session entry
154 * @band: out param, band caclculated
155 * @opr_ch: operating channels
156 *
157 * Return: status of operation
158 */
159
160tSirRetStatus
161sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session)
162{
163 tpAniBeaconStruct bcn_struct = (tpAniBeaconStruct)
164 session->pSchBeaconFrameBegin;
165 tpSirMacMgmtHdr mac;
166 uint16_t offset;
167 uint8_t *ptr;
168 tDot11fBeacon1 *bcn_1;
169 tDot11fBeacon2 *bcn_2;
170 uint32_t i, n_status, n_bytes;
171 uint32_t wps_ap_enable = 0, tmp;
172 tDot11fIEWscProbeRes *wsc_prb_res;
173 uint8_t *extra_ie = NULL;
174 uint32_t extra_ie_len = 0;
175 uint16_t extra_ie_offset = 0;
176 uint16_t p2p_ie_offset = 0;
177 tSirRetStatus status = eSIR_SUCCESS;
178 bool is_vht_enabled = false;
179
180 bcn_1 = cdf_mem_malloc(sizeof(tDot11fBeacon1));
181 if (NULL == bcn_1) {
182 sch_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
183 return eSIR_MEM_ALLOC_FAILED;
184 }
185
186 bcn_2 = cdf_mem_malloc(sizeof(tDot11fBeacon2));
187 if (NULL == bcn_2) {
188 sch_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
189 cdf_mem_free(bcn_1);
190 return eSIR_MEM_ALLOC_FAILED;
191 }
192
193 wsc_prb_res = cdf_mem_malloc(sizeof(tDot11fIEWscProbeRes));
194 if (NULL == wsc_prb_res) {
195 sch_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
196 cdf_mem_free(bcn_1);
197 cdf_mem_free(bcn_2);
198 return eSIR_MEM_ALLOC_FAILED;
199 }
200
201 sch_log(mac_ctx, LOG1, FL("Setting fixed beacon fields"));
202
203 /*
204 * First set the fixed fields:
205 * set the TFP headers, set the mac header
206 */
207 cdf_mem_set((uint8_t *) &bcn_struct->macHdr, sizeof(tSirMacMgmtHdr), 0);
208 mac = (tpSirMacMgmtHdr) &bcn_struct->macHdr;
209 mac->fc.type = SIR_MAC_MGMT_FRAME;
210 mac->fc.subType = SIR_MAC_MGMT_BEACON;
211
212 for (i = 0; i < 6; i++)
213 mac->da[i] = 0xff;
214
215 cdf_mem_copy(mac->sa, session->selfMacAddr,
216 sizeof(session->selfMacAddr));
217 cdf_mem_copy(mac->bssId, session->bssId, sizeof(session->bssId));
218
219 mac->fc.fromDS = 0;
220 mac->fc.toDS = 0;
221
222 /* Now set the beacon body */
223 cdf_mem_set((uint8_t *) bcn_1, sizeof(tDot11fBeacon1), 0);
224
225 /* Skip over the timestamp (it'll be updated later). */
226 bcn_1->BeaconInterval.interval =
227 mac_ctx->sch.schObject.gSchBeaconInterval;
228 populate_dot11f_capabilities(mac_ctx, &bcn_1->Capabilities, session);
229 if (session->ssidHidden) {
230 bcn_1->SSID.present = 1;
231 /* rest of the fileds are 0 for hidden ssid */
232 if ((session->ssId.length) &&
233 (session->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS))
234 bcn_1->SSID.num_ssid = session->ssId.length;
235 } else {
236 populate_dot11f_ssid(mac_ctx, &session->ssId, &bcn_1->SSID);
237 }
238
239 populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
240 &bcn_1->SuppRates, session);
241 populate_dot11f_ds_params(mac_ctx, &bcn_1->DSParams,
242 session->currentOperChannel);
243 populate_dot11f_ibss_params(mac_ctx, &bcn_1->IBSSParams, session);
244
245 offset = sizeof(tAniBeaconStruct);
246 ptr = session->pSchBeaconFrameBegin + offset;
247
248 if (LIM_IS_AP_ROLE(session)) {
249 /* Initialize the default IE bitmap to zero */
250 cdf_mem_set((uint8_t *) &(session->DefProbeRspIeBitmap),
251 (sizeof(uint32_t) * 8), 0);
252
253 /* Initialize the default IE bitmap to zero */
254 cdf_mem_set((uint8_t *) &(session->probeRespFrame),
255 sizeof(session->probeRespFrame), 0);
256
257 /*
258 * Can be efficiently updated whenever new IE added in Probe
259 * response in future
260 */
261 if (lim_update_probe_rsp_template_ie_bitmap_beacon1(mac_ctx,
262 bcn_1, session) != eSIR_SUCCESS)
263 sch_log(mac_ctx, LOGE,
264 FL("Failed to build ProbeRsp template"));
265 }
266
267 n_status = dot11f_pack_beacon1(mac_ctx, bcn_1, ptr,
268 SCH_MAX_BEACON_SIZE - offset, &n_bytes);
269 if (DOT11F_FAILED(n_status)) {
270 sch_log(mac_ctx, LOGE,
271 FL("Failed to packed a tDot11fBeacon1 (0x%08x.)."),
272 n_status);
273 cdf_mem_free(bcn_1);
274 cdf_mem_free(bcn_2);
275 cdf_mem_free(wsc_prb_res);
276 return eSIR_FAILURE;
277 } else if (DOT11F_WARNED(n_status)) {
278 sch_log(mac_ctx, LOGE,
279 FL("Warnings while packing a tDot11fBeacon1(0x%08x.)."),
280 n_status);
281 }
282 /*changed to correct beacon corruption */
283 cdf_mem_set((uint8_t *) bcn_2, sizeof(tDot11fBeacon2), 0);
284 session->schBeaconOffsetBegin = offset + (uint16_t) n_bytes;
285 sch_log(mac_ctx, LOG1, FL("Initialized beacon begin, offset %d"),
286 offset);
287
288 /* Initialize the 'new' fields at the end of the beacon */
289
290 if ((session->limSystemRole == eLIM_AP_ROLE) &&
291 session->dfsIncludeChanSwIe == true)
292 populate_dot_11_f_ext_chann_switch_ann(mac_ctx,
293 &bcn_2->ext_chan_switch_ann,
294 session);
295
296 populate_dot11f_country(mac_ctx, &bcn_2->Country, session);
297 if (bcn_1->Capabilities.qos)
298 populate_dot11f_edca_param_set(mac_ctx, &bcn_2->EDCAParamSet,
299 session);
300
301 if (session->lim11hEnable) {
302 populate_dot11f_power_constraints(mac_ctx,
303 &bcn_2->PowerConstraints);
304 populate_dot11f_tpc_report(mac_ctx, &bcn_2->TPCReport, session);
305 /* Need to insert channel switch announcement here */
306 if ((LIM_IS_AP_ROLE(session)
307 || LIM_IS_P2P_DEVICE_GO(session))
308 && session->dfsIncludeChanSwIe == true) {
309 /*
310 * Channel switch announcement only if radar is detected
311 * and SAP has instructed to announce channel switch IEs
312 * in beacon and probe responses
313 */
314 populate_dot11f_chan_switch_ann(mac_ctx,
315 &bcn_2->ChanSwitchAnn, session);
316
317 /*
318 * TODO: depending the CB mode, extended channel switch
319 * announcement need to be called
320 */
321 /*
322 populate_dot11f_ext_chan_switch_ann(mac_ctx,
323 &bcn_2->ExtChanSwitchAnn, session);
324 */
325#ifdef WLAN_FEATURE_11AC
326 /*
327 * TODO: If in 11AC mode, wider bw channel switch
328 * announcement needs to be called
329 */
330 /*
331 populate_dot11f_wider_bw_chan_switch_ann(mac_ctx,
332 &bcn_2->WiderBWChanSwitchAnn, session);
333 */
334#endif
335 /*
336 * Populate the Channel Switch Wrapper Element if
337 * SAP operates in 40/80 Mhz Channel Width.
338 */
339 if (true == session->dfsIncludeChanWrapperIe)
340 populate_dot11f_chan_switch_wrapper(mac_ctx,
341 &bcn_2->ChannelSwitchWrapper, session);
342 }
343 }
344
345#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
346 /* populate proprietary IE for MDM device operating in AP-MCC */
347 populate_dot11f_avoid_channel_ie(mac_ctx, &bcn_2->QComVendorIE,
348 session);
349#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
350
351 if (session->dot11mode != WNI_CFG_DOT11_MODE_11B)
352 populate_dot11f_erp_info(mac_ctx, &bcn_2->ERPInfo, session);
353
354 if (session->htCapability) {
355 populate_dot11f_ht_caps(mac_ctx, session, &bcn_2->HTCaps);
356 populate_dot11f_ht_info(mac_ctx, &bcn_2->HTInfo, session);
357 }
358#ifdef WLAN_FEATURE_11AC
359 if (session->vhtCapability) {
360 sch_log(mac_ctx, LOGW, FL("Populate VHT IEs in Beacon"));
361 populate_dot11f_vht_caps(mac_ctx, session, &bcn_2->VHTCaps);
362 populate_dot11f_vht_operation(mac_ctx, session,
363 &bcn_2->VHTOperation);
364 is_vht_enabled = true;
365 /* following is for MU MIMO: we do not support it yet */
366 /*
367 populate_dot11f_vht_ext_bss_load( mac_ctx, &bcn2.VHTExtBssLoad);
368 */
369 if (session->gLimOperatingMode.present)
370 populate_dot11f_operating_mode(mac_ctx,
371 &bcn_2->OperatingMode, session);
372 }
373#endif
374 populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &bcn_2->ExtCap,
375 session);
376 populate_dot11f_ext_supp_rates(mac_ctx,
377 POPULATE_DOT11F_RATES_OPERATIONAL,
378 &bcn_2->ExtSuppRates, session);
379
380 if (session->pLimStartBssReq != NULL) {
381 populate_dot11f_wpa(mac_ctx, &session->pLimStartBssReq->rsnIE,
382 &bcn_2->WPA);
383 populate_dot11f_rsn_opaque(mac_ctx,
384 &session->pLimStartBssReq->rsnIE,
385 &bcn_2->RSNOpaque);
386 }
387
388 if (session->limWmeEnabled)
389 populate_dot11f_wmm(mac_ctx, &bcn_2->WMMInfoAp,
390 &bcn_2->WMMParams, &bcn_2->WMMCaps, session);
391 if (LIM_IS_AP_ROLE(session)) {
392 if (session->wps_state != SAP_WPS_DISABLED) {
393 populate_dot11f_beacon_wpsi_es(mac_ctx,
394 &bcn_2->WscBeacon, session);
395 }
396 } else {
397 if (wlan_cfg_get_int(mac_ctx,
398 (uint16_t) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS)
399 sch_log(mac_ctx, LOGP, FL("Failed to cfg get id %d"),
400 WNI_CFG_WPS_ENABLE);
401
402 wps_ap_enable = tmp & WNI_CFG_WPS_ENABLE_AP;
403
404 if (wps_ap_enable)
405 populate_dot11f_wsc(mac_ctx, &bcn_2->WscBeacon);
406
407 if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
408 eLIM_WSC_ENROLL_BEGIN) {
409 populate_dot11f_wsc_registrar_info(mac_ctx,
410 &bcn_2->WscBeacon);
411 mac_ctx->lim.wscIeInfo.wscEnrollmentState =
412 eLIM_WSC_ENROLL_IN_PROGRESS;
413 }
414
415 if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
416 eLIM_WSC_ENROLL_END) {
417 de_populate_dot11f_wsc_registrar_info(mac_ctx,
418 &bcn_2->WscBeacon);
419 mac_ctx->lim.wscIeInfo.wscEnrollmentState =
420 eLIM_WSC_ENROLL_NOOP;
421 }
422 }
423
424 if ((LIM_IS_AP_ROLE(session))) {
425 /*
426 * Can be efficiently updated whenever new IE added in Probe
427 * response in future
428 */
429 lim_update_probe_rsp_template_ie_bitmap_beacon2(mac_ctx, bcn_2,
430 &session->DefProbeRspIeBitmap[0],
431 &session->probeRespFrame);
432
433 /* update probe response WPS IE instead of beacon WPS IE */
434 if (session->wps_state != SAP_WPS_DISABLED) {
435 if (session->APWPSIEs.SirWPSProbeRspIE.FieldPresent)
436 populate_dot11f_probe_res_wpsi_es(mac_ctx,
437 wsc_prb_res, session);
438 else
439 wsc_prb_res->present = 0;
440 if (wsc_prb_res->present) {
441 set_probe_rsp_ie_bitmap(
442 &session->DefProbeRspIeBitmap[0],
443 SIR_MAC_WPA_EID);
444 cdf_mem_copy((void *)
445 &session->probeRespFrame.WscProbeRes,
446 (void *)wsc_prb_res,
447 sizeof(tDot11fIEWscProbeRes));
448 }
449 }
450
451 }
452
453 n_status = dot11f_pack_beacon2(mac_ctx, bcn_2,
454 session->pSchBeaconFrameEnd,
455 SCH_MAX_BEACON_SIZE, &n_bytes);
456 if (DOT11F_FAILED(n_status)) {
457 sch_log(mac_ctx, LOGE,
458 FL("Failed to packed a tDot11fBeacon2 (0x%08x.)."),
459 n_status);
460 cdf_mem_free(bcn_1);
461 cdf_mem_free(bcn_2);
462 cdf_mem_free(wsc_prb_res);
463 return eSIR_FAILURE;
464 } else if (DOT11F_WARNED(n_status)) {
465 sch_log(mac_ctx, LOGE,
466 FL("Warnings while packing a tDot11fBeacon2(0x%08x.)."),
467 n_status);
468 }
469
470 extra_ie = session->pSchBeaconFrameEnd + n_bytes;
471 extra_ie_offset = n_bytes;
472 /* TODO: Append additional IE here. */
473 sch_append_addn_ie(mac_ctx, session,
474 session->pSchBeaconFrameEnd + n_bytes,
475 SCH_MAX_BEACON_SIZE, &n_bytes);
476 session->schBeaconOffsetEnd = (uint16_t) n_bytes;
477 extra_ie_len = n_bytes - extra_ie_offset;
478 /* Get the p2p Ie Offset */
479 status = sch_get_p2p_ie_offset(extra_ie, extra_ie_len, &p2p_ie_offset);
480 if (eSIR_SUCCESS == status)
481 /* Update the P2P Ie Offset */
482 mac_ctx->sch.schObject.p2pIeOffset =
483 session->schBeaconOffsetBegin + TIM_IE_SIZE +
484 extra_ie_offset + p2p_ie_offset;
485 else
486 mac_ctx->sch.schObject.p2pIeOffset = 0;
487
488 sch_log(mac_ctx, LOG1, FL("Initialized beacon end, offset %d"),
489 session->schBeaconOffsetEnd);
490 mac_ctx->sch.schObject.fBeaconChanged = 1;
491 cdf_mem_free(bcn_1);
492 cdf_mem_free(bcn_2);
493 cdf_mem_free(wsc_prb_res);
494 return eSIR_SUCCESS;
495}
496
497tSirRetStatus lim_update_probe_rsp_template_ie_bitmap_beacon1(tpAniSirGlobal pMac,
498 tDot11fBeacon1 *beacon1,
499 tpPESession
500 psessionEntry)
501{
502 uint32_t *DefProbeRspIeBitmap;
503 tDot11fProbeResponse *prb_rsp;
504 if (!psessionEntry) {
505 sch_log(pMac, LOGE, FL("PESession is null!"));
506 return eSIR_FAILURE;
507 }
508 DefProbeRspIeBitmap = &psessionEntry->DefProbeRspIeBitmap[0];
509 prb_rsp = &psessionEntry->probeRespFrame;
510 prb_rsp->BeaconInterval = beacon1->BeaconInterval;
511 cdf_mem_copy((void *)&prb_rsp->Capabilities,
512 (void *)&beacon1->Capabilities,
513 sizeof(beacon1->Capabilities));
514
515 /* SSID */
516 if (beacon1->SSID.present) {
517 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_SSID_EID);
518 /* populating it, because probe response has to go with SSID even in hidden case */
519 populate_dot11f_ssid(pMac, &psessionEntry->ssId, &prb_rsp->SSID);
520 }
521 /* supported rates */
522 if (beacon1->SuppRates.present) {
523 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_RATESET_EID);
524 cdf_mem_copy((void *)&prb_rsp->SuppRates,
525 (void *)&beacon1->SuppRates,
526 sizeof(beacon1->SuppRates));
527
528 }
529 /* DS Parameter set */
530 if (beacon1->DSParams.present) {
531 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
532 SIR_MAC_DS_PARAM_SET_EID);
533 cdf_mem_copy((void *)&prb_rsp->DSParams,
534 (void *)&beacon1->DSParams,
535 sizeof(beacon1->DSParams));
536
537 }
538
539 /* IBSS params will not be present in the Beacons transmitted by AP */
540 return eSIR_SUCCESS;
541}
542
543void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal pMac,
544 tDot11fBeacon2 *beacon2,
545 uint32_t *DefProbeRspIeBitmap,
546 tDot11fProbeResponse *prb_rsp)
547{
548 /* IBSS parameter set - will not be present in probe response tx by AP */
549 /* country */
550 if (beacon2->Country.present) {
551 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_COUNTRY_EID);
552 cdf_mem_copy((void *)&prb_rsp->Country,
553 (void *)&beacon2->Country,
554 sizeof(beacon2->Country));
555
556 }
557 /* Power constraint */
558 if (beacon2->PowerConstraints.present) {
559 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
560 SIR_MAC_PWR_CONSTRAINT_EID);
561 cdf_mem_copy((void *)&prb_rsp->PowerConstraints,
562 (void *)&beacon2->PowerConstraints,
563 sizeof(beacon2->PowerConstraints));
564
565 }
566 /* Channel Switch Annoouncement SIR_MAC_CHNL_SWITCH_ANN_EID */
567 if (beacon2->ChanSwitchAnn.present) {
568 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
569 SIR_MAC_CHNL_SWITCH_ANN_EID);
570 cdf_mem_copy((void *)&prb_rsp->ChanSwitchAnn,
571 (void *)&beacon2->ChanSwitchAnn,
572 sizeof(beacon2->ChanSwitchAnn));
573
574 }
575
576#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
577 if (beacon2->QComVendorIE.present) {
578 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
579 SIR_MAC_QCOM_VENDOR_EID);
580 cdf_mem_copy((void *)&prb_rsp->QComVendorIE,
581 (void *)&beacon2->QComVendorIE,
582 sizeof(beacon2->QComVendorIE));
583 }
584#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
585
586 /* ERP information */
587 if (beacon2->ERPInfo.present) {
588 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_ERP_INFO_EID);
589 cdf_mem_copy((void *)&prb_rsp->ERPInfo,
590 (void *)&beacon2->ERPInfo,
591 sizeof(beacon2->ERPInfo));
592
593 }
594 /* Extended supported rates */
595 if (beacon2->ExtSuppRates.present) {
596 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
597 SIR_MAC_EXTENDED_RATE_EID);
598 cdf_mem_copy((void *)&prb_rsp->ExtSuppRates,
599 (void *)&beacon2->ExtSuppRates,
600 sizeof(beacon2->ExtSuppRates));
601
602 }
603
604 /* WPA */
605 if (beacon2->WPA.present) {
606 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
607 cdf_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA,
608 sizeof(beacon2->WPA));
609
610 }
611
612 /* RSN */
613 if (beacon2->RSNOpaque.present) {
614 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_RSN_EID);
615 cdf_mem_copy((void *)&prb_rsp->RSNOpaque,
616 (void *)&beacon2->RSNOpaque,
617 sizeof(beacon2->RSNOpaque));
618 }
619
620 /* EDCA Parameter set */
621 if (beacon2->EDCAParamSet.present) {
622 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
623 SIR_MAC_EDCA_PARAM_SET_EID);
624 cdf_mem_copy((void *)&prb_rsp->EDCAParamSet,
625 (void *)&beacon2->EDCAParamSet,
626 sizeof(beacon2->EDCAParamSet));
627
628 }
629 /* Vendor specific - currently no vendor specific IEs added */
630 /* Requested IEs - currently we are not processing this will be added later */
631 /* HT capability IE */
632 if (beacon2->HTCaps.present) {
633 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
634 SIR_MAC_HT_CAPABILITIES_EID);
635 cdf_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps,
636 sizeof(beacon2->HTCaps));
637 }
638 /* HT Info IE */
639 if (beacon2->HTInfo.present) {
640 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_HT_INFO_EID);
641 cdf_mem_copy((void *)&prb_rsp->HTInfo, (void *)&beacon2->HTInfo,
642 sizeof(beacon2->HTInfo));
643 }
644#ifdef WLAN_FEATURE_11AC
645 if (beacon2->VHTCaps.present) {
646 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
647 SIR_MAC_VHT_CAPABILITIES_EID);
648 cdf_mem_copy((void *)&prb_rsp->VHTCaps,
649 (void *)&beacon2->VHTCaps,
650 sizeof(beacon2->VHTCaps));
651 }
652 if (beacon2->VHTOperation.present) {
653 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
654 SIR_MAC_VHT_OPERATION_EID);
655 cdf_mem_copy((void *)&prb_rsp->VHTOperation,
656 (void *)&beacon2->VHTOperation,
657 sizeof(beacon2->VHTOperation));
658 }
659 if (beacon2->VHTExtBssLoad.present) {
660 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
661 SIR_MAC_VHT_EXT_BSS_LOAD_EID);
662 cdf_mem_copy((void *)&prb_rsp->VHTExtBssLoad,
663 (void *)&beacon2->VHTExtBssLoad,
664 sizeof(beacon2->VHTExtBssLoad));
665 }
666#endif
667
668 /* WMM IE */
669 if (beacon2->WMMParams.present) {
670 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
671 cdf_mem_copy((void *)&prb_rsp->WMMParams,
672 (void *)&beacon2->WMMParams,
673 sizeof(beacon2->WMMParams));
674 }
675 /* WMM capability - most of the case won't be present */
676 if (beacon2->WMMCaps.present) {
677 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
678 cdf_mem_copy((void *)&prb_rsp->WMMCaps,
679 (void *)&beacon2->WMMCaps,
680 sizeof(beacon2->WMMCaps));
681 }
682
683 /* Extended Capability */
684 if (beacon2->ExtCap.present) {
685 set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP);
686 cdf_mem_copy((void *)&prb_rsp->ExtCap,
687 (void *)&beacon2->ExtCap,
688 sizeof(beacon2->ExtCap));
689 }
690
691}
692
693void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos)
694{
695 uint32_t index, temp;
696
697 index = pos >> 5;
698 if (index >= 8) {
699 return;
700 }
701 temp = IeBitmap[index];
702
703 temp |= 1 << (pos & 0x1F);
704
705 IeBitmap[index] = temp;
706}
707
708/* -------------------------------------------------------------------- */
709/**
710 * write_beacon_to_memory
711 *
712 * FUNCTION:
713 *
714 * LOGIC:
715 *
716 * ASSUMPTIONS:
717 *
718 * NOTE:
719 *
720 * @param None
721 * @param size Size of the beacon to write to memory
722 * @param length Length field of the beacon to write to memory
723 * @return None
724 */
725
726void write_beacon_to_memory(tpAniSirGlobal pMac, uint16_t size, uint16_t length,
727 tpPESession psessionEntry)
728{
729 uint16_t i;
730 tpAniBeaconStruct pBeacon;
731
732 /* copy end of beacon only if length > 0 */
733 if (length > 0) {
734 for (i = 0; i < psessionEntry->schBeaconOffsetEnd; i++)
735 psessionEntry->pSchBeaconFrameBegin[size++] =
736 psessionEntry->pSchBeaconFrameEnd[i];
737 }
738 /* Update the beacon length */
739 pBeacon = (tpAniBeaconStruct) psessionEntry->pSchBeaconFrameBegin;
740 /* Do not include the beaconLength indicator itself */
741 if (length == 0) {
742 pBeacon->beaconLength = 0;
743 /* Dont copy entire beacon, Copy length field alone */
744 size = 4;
745 } else
746 pBeacon->beaconLength = (uint32_t) size - sizeof(uint32_t);
747
748 /* write size bytes from pSchBeaconFrameBegin */
749 PELOG2(sch_log(pMac, LOG2, FL("Beacon size - %d bytes"), size);)
750 PELOG2(sir_dump_buf
751 (pMac, SIR_SCH_MODULE_ID, LOG2,
752 psessionEntry->pSchBeaconFrameBegin, size);
753 )
754
755 if (!pMac->sch.schObject.fBeaconChanged)
756 return;
757
758 pMac->sch.gSchGenBeacon = 1;
759 if (pMac->sch.gSchGenBeacon) {
760 pMac->sch.gSchBeaconsSent++;
761
762 /* */
763 /* Copy beacon data to SoftMAC shared memory... */
764 /* Do this by sending a message to HAL */
765 /* */
766
767 size = (size + 3) & (~3);
768 if (eSIR_SUCCESS !=
769 sch_send_beacon_req(pMac, psessionEntry->pSchBeaconFrameBegin,
770 size, psessionEntry))
771 PELOGE(sch_log
772 (pMac, LOGE,
773 FL
774 ("sch_send_beacon_req() returned an error (zsize %d)"),
775 size);
776 )
777 else {
778 pMac->sch.gSchBeaconsWritten++;
779 }
780 }
781 pMac->sch.schObject.fBeaconChanged = 0;
782}
783
784/**
785 * sch_generate_tim
786 *
787 * FUNCTION:
788 * Generate TIM
789 *
790 * LOGIC:
791 *
792 * ASSUMPTIONS:
793 *
794 * NOTE:
795 *
796 * @param pMac pointer to global mac structure
797 * @param **pPtr pointer to the buffer, where the TIM bit is to be written.
798 * @param *timLength pointer to limLength, which needs to be returned.
799 * @return None
800 */
801void sch_generate_tim(tpAniSirGlobal pMac, uint8_t **pPtr, uint16_t *timLength,
802 uint8_t dtimPeriod)
803{
804 uint8_t *ptr = *pPtr;
805 uint32_t val = 0;
806 uint32_t minAid = 1; /* Always start with AID 1 as minimum */
807 uint32_t maxAid = HAL_NUM_STA;
808
809 /* Generate partial virtual bitmap */
810 uint8_t N1 = minAid / 8;
811 uint8_t N2 = maxAid / 8;
812 if (N1 & 1)
813 N1--;
814
815 *timLength = N2 - N1 + 4;
816 val = dtimPeriod;
817
818 /*
819 * Write 0xFF to firmware's field to detect firmware's mal-function
820 * early. DTIM count and bitmap control usually cannot be 0xFF, so it
821 * is easy to know that firmware never updated DTIM count/bitmap control
822 * field after host driver downloaded beacon template if end-user complaints
823 * that DTIM count and bitmapControl is 0xFF.
824 */
825 *ptr++ = SIR_MAC_TIM_EID;
826 *ptr++ = (uint8_t) (*timLength);
827 /* location for dtimCount. will be filled in by FW. */
828 *ptr++ = 0xFF;
829 *ptr++ = (uint8_t) val;
830 /* location for bitmap control. will be filled in by FW. */
831 *ptr++ = 0xFF;
832 ptr += (N2 - N1 + 1);
833
834 PELOG2(sir_dump_buf
835 (pMac, SIR_SCH_MODULE_ID, LOG2, *pPtr, (*timLength) + 2);
836 )
837 * pPtr = ptr;
838}
839/* -------------------------------------------------------------------- */
840/**
841 * @function: SchProcessPreBeaconInd
842 *
843 * @brief : Process the PreBeacon Indication from the Lim
844 *
845 * ASSUMPTIONS:
846 *
847 * NOTE:
848 *
849 * @param : pMac - tpAniSirGlobal
850 *
851 * @return None
852 */
853
854void sch_process_pre_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
855{
856 tpBeaconGenParams pMsg = (tpBeaconGenParams) limMsg->bodyptr;
857 uint32_t beaconSize;
858 tpPESession psessionEntry;
859 uint8_t sessionId;
860
861 if ((psessionEntry =
862 pe_find_session_by_bssid(pMac, pMsg->bssId, &sessionId)) == NULL) {
863 PELOGE(sch_log(pMac, LOGE, FL("session lookup fails"));)
864 goto end;
865 }
866
867 beaconSize = psessionEntry->schBeaconOffsetBegin;
868
869 /* If SME is not in normal mode, no need to generate beacon */
870 if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) {
871 PELOGE(sch_log
872 (pMac, LOG1,
873 FL("PreBeaconInd received in invalid state: %d"),
874 psessionEntry->limSmeState);
875 )
876 goto end;
877 }
878
879 switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
880
881 case eLIM_STA_IN_IBSS_ROLE:
882 case eLIM_BT_AMP_AP_ROLE:
883 case eLIM_BT_AMP_STA_ROLE:
884 /* generate IBSS parameter set */
885 if (psessionEntry->statypeForBss == STA_ENTRY_SELF)
886 write_beacon_to_memory(pMac, (uint16_t) beaconSize,
887 (uint16_t) beaconSize,
888 psessionEntry);
889 else
890 PELOGE(sch_log
891 (pMac, LOGE,
892 FL
893 ("can not send beacon for PEER session entry"));
894 )
895 break;
896
897 case eLIM_AP_ROLE: {
898 uint8_t *ptr =
899 &psessionEntry->pSchBeaconFrameBegin[psessionEntry->
900 schBeaconOffsetBegin];
901 uint16_t timLength = 0;
902 if (psessionEntry->statypeForBss == STA_ENTRY_SELF) {
903 sch_generate_tim(pMac, &ptr, &timLength,
904 psessionEntry->dtimPeriod);
905 beaconSize += 2 + timLength;
906 write_beacon_to_memory(pMac, (uint16_t) beaconSize,
907 (uint16_t) beaconSize,
908 psessionEntry);
909 } else
910 PELOGE(sch_log
911 (pMac, LOGE,
912 FL
913 ("can not send beacon for PEER session entry"));
914 )
915 }
916 break;
917
918 default:
919 PELOGE(sch_log
920 (pMac, LOGE,
921 FL
922 ("Error-PE has Receive PreBeconGenIndication when System is in %d role"),
923 GET_LIM_SYSTEM_ROLE(psessionEntry));
924 )
925 }
926
927end:
928 cdf_mem_free(pMsg);
929
930 }