blob: 7100c0ef5dfca2e68345da637a07871f2b081bce [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
krunal soni2a6a9062014-02-11 14:14:23 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
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.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
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
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**========================================================================
29
30 \file wlan_hdd_scan.c
31
32 \brief WLAN Host Device Driver implementation
33
34 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
35
36 Qualcomm Confidential and Proprietary.
37
38 ========================================================================*/
39
40/**=========================================================================
41
42 EDIT HISTORY FOR FILE
43
44
45 This section contains comments describing changes made to the module.
46 Notice that changes are listed in reverse chronological order.
47
48
49 $Header:$ $DateTime: $ $Author: $
50
51
52 when who what, where, why
53 -------- --- --------------------------------------------------------
54 04/5/09 Shailender Created module.
55
56 ==========================================================================*/
57 /* To extract the Scan results */
58
59/* Add a stream event */
60
61#include <wlan_qct_driver.h>
62#include <wlan_hdd_includes.h>
63#include <vos_api.h>
64#include <palTypes.h>
65#include <aniGlobal.h>
66#include <dot11f.h>
67#ifdef WLAN_BTAMP_FEATURE
68#include "bap_hdd_misc.h"
69#endif
70
Jeff Johnson295189b2012-06-20 16:38:30 -070071#include <linux/wireless.h>
72#include <net/cfg80211.h>
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053073#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
76#define WEXT_CSCAN_HEADER_SIZE 12
77#define WEXT_CSCAN_SSID_SECTION 'S'
78#define WEXT_CSCAN_CHANNEL_SECTION 'C'
79#define WEXT_CSCAN_NPROBE_SECTION 'N'
80#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
81#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
82#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
83#define WEXT_CSCAN_TYPE_SECTION 'T'
84#define WEXT_CSCAN_PENDING_SECTION 'O'
85#define WEXT_CSCAN_TYPE_DEFAULT 0
86#define WEXT_CSCAN_TYPE_PASSIVE 1
87#define WEXT_CSCAN_PASV_DWELL_TIME 130
88#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
89#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
90#define WEXT_CSCAN_HOME_DWELL_TIME 130
91#define MAX_RATES 12
92
93#define WEXT_CSCAN_SCAN_DONE_WAIT_TIME 2000
94
95typedef struct hdd_scan_info{
96 struct net_device *dev;
97 struct iw_request_info *info;
98 char *start;
99 char *end;
100} hdd_scan_info_t, *hdd_scan_info_tp;
101
102static v_S31_t hdd_TranslateABGRateToMbpsRate(v_U8_t *pFcRate)
103{
104
105 /** Slightly more sophisticated processing has to take place here.
106 Basic rates are rounded DOWN. HT rates are rounded UP.*/
107 return ( (( ((v_S31_t) *pFcRate) & 0x007f) * 1000000) / 2);
108}
109
110
111static eHalStatus hdd_AddIwStreamEvent(int cmd, int length, char* data, hdd_scan_info_t *pscanInfo, char **last_event, char **current_event )
112{
113 struct iw_event event;
114
115 *last_event = *current_event;
116 vos_mem_zero(&event, sizeof (struct iw_event));
117 event.cmd = cmd;
118 event.u.data.flags = 1;
119 event.u.data.length = length;
120 *current_event = iwe_stream_add_point (pscanInfo->info,*current_event, pscanInfo->end, &event, data);
121
122 if(*last_event == *current_event)
123 {
124 /* no space to add event */
c_hpothu7f63e882013-10-02 19:13:35 +0530125 hddLog( LOGW, "%s: no space left to add event", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700126 return -E2BIG; /* Error code, may be E2BIG */
127 }
128
129 return 0;
130}
131
132/**---------------------------------------------------------------------------
133
134 \brief hdd_GetWPARSNIEs() -
135
136 This function extract the WPA/RSN IE from the Bss descriptor IEs fields
137
138 \param - ieFields - Pointer to the Bss Descriptor IEs.
139 - ie_length - IE Length.
140 - last_event -Points to the last event.
141 - current_event - Points to the
142 \return - 0 for success, non zero for failure
143
144 --------------------------------------------------------------------------*/
145
146
147/* Extract the WPA and/or RSN IEs */
148static eHalStatus hdd_GetWPARSNIEs( v_U8_t *ieFields, v_U16_t ie_length, char **last_event, char **current_event, hdd_scan_info_t *pscanInfo )
149{
150 v_U8_t eid, elen, *element;
151 v_U16_t tie_length=0;
152
153 ENTER();
154
155 element = ieFields;
156 tie_length = ie_length;
157
158 while( tie_length > 2 && element != NULL )
159 {
160 eid = element[0];
161 elen = element[1];
162
163 /*If element length is greater than total remaining ie length,
164 *break the loop*/
165 if ((elen+2) > tie_length)
166 break;
167
168 switch(eid)
169 {
170 case DOT11F_EID_WPA:
171 case DOT11F_EID_RSN:
172#ifdef FEATURE_WLAN_WAPI
173 case DOT11F_EID_WAPI:
174#endif
175 if(hdd_AddIwStreamEvent( IWEVGENIE, elen+2, (char*)element, pscanInfo, last_event, current_event ) < 0 )
176 return -E2BIG;
177 break;
178
179 default:
180 break;
181 }
182
183 /* Next element */
184 tie_length -= (2 + elen);
185 element += 2 + elen;
186 }
187
188 return 0;
189}
190
191/**---------------------------------------------------------------------------
192
193 \brief hdd_IndicateScanResult() -
194
195 This function returns the scan results to the wpa_supplicant
196
197 \param - scanInfo - Pointer to the scan info structure.
198 - descriptor - Pointer to the Bss Descriptor.
199
200 \return - 0 for success, non zero for failure
201
202 --------------------------------------------------------------------------*/
203#define MAX_CUSTOM_LEN 64
204static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result)
205{
206 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ;
207 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
208 tSirBssDescription *descriptor = &scan_result->BssDescriptor;
209 struct iw_event event;
210 char *current_event = scanInfo->start;
211 char *end = scanInfo->end;
212 char *last_event;
213 char *current_pad;
214 v_U16_t ie_length = 0;
215 v_U16_t capabilityInfo;
216 char *modestr;
217 int error;
218 char custom[MAX_CUSTOM_LEN];
219 char *p;
220
Arif Hussain24bafea2013-11-15 15:10:03 -0800221 hddLog( LOG1, "hdd_IndicateScanResult " MAC_ADDRESS_STR,
222 MAC_ADDR_ARRAY(descriptor->bssId));
Jeff Johnson295189b2012-06-20 16:38:30 -0700223
224 error = 0;
225 last_event = current_event;
226 vos_mem_zero(&event, sizeof (event));
227
228 /* BSSID */
229 event.cmd = SIOCGIWAP;
230 event.u.ap_addr.sa_family = ARPHRD_ETHER;
231 vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId,
232 sizeof (descriptor->bssId));
233 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
234 &event, IW_EV_ADDR_LEN);
235
236 if (last_event == current_event)
237 {
238 /* no space to add event */
239 /* Error code may be E2BIG */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530240 hddLog(LOGE, "hdd_IndicateScanResult: no space for SIOCGIWAP ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700241 return -E2BIG;
242 }
243
244 last_event = current_event;
245 vos_mem_zero(&event, sizeof (struct iw_event));
246
247 /* Protocol Name */
248 event.cmd = SIOCGIWNAME;
249
250 switch (descriptor->nwType)
251 {
252 case eSIR_11A_NW_TYPE:
253 modestr = "a";
254 break;
255 case eSIR_11B_NW_TYPE:
256 modestr = "b";
257 break;
258 case eSIR_11G_NW_TYPE:
259 modestr = "g";
260 break;
261 case eSIR_11N_NW_TYPE:
262 modestr = "n";
263 break;
264 default:
265 hddLog( LOGW, "%s: Unknown network type [%d]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700266 __func__, descriptor->nwType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 modestr = "?";
268 break;
269 }
270 snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr);
271 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
272 &event, IW_EV_CHAR_LEN);
273
274 if (last_event == current_event)
275 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530276 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWNAME");
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 /* Error code, may be E2BIG */
278 return -E2BIG;
279 }
280
281 last_event = current_event;
282 vos_mem_zero( &event, sizeof (struct iw_event));
283
284 /*Freq*/
285 event.cmd = SIOCGIWFREQ;
286
287 event.u.freq.m = descriptor->channelId;
288 event.u.freq.e = 0;
289 event.u.freq.i = 0;
290 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
291 &event, IW_EV_FREQ_LEN);
292
293 if (last_event == current_event)
294 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530295 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWFREQ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 return -E2BIG;
297 }
298
299 last_event = current_event;
300 vos_mem_zero( &event, sizeof (struct iw_event));
301
302 /* BSS Mode */
303 event.cmd = SIOCGIWMODE;
304
305 capabilityInfo = descriptor->capabilityInfo;
306
307 if (SIR_MAC_GET_ESS(capabilityInfo))
308 {
309 event.u.mode = IW_MODE_INFRA;
310 }
311 else if (SIR_MAC_GET_IBSS(capabilityInfo))
312 {
313 event.u.mode = IW_MODE_ADHOC;
314 }
315 else
316 {
317 /* neither ESS or IBSS */
318 event.u.mode = IW_MODE_AUTO;
319 }
320
321 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
322 &event, IW_EV_UINT_LEN);
323
324 if (last_event == current_event)
325 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530326 hddLog(LOGE, "hdd_IndicateScanResult: no space for SIOCGIWMODE");
Jeff Johnson295189b2012-06-20 16:38:30 -0700327 return -E2BIG;
328 }
329 /* To extract SSID */
330 ie_length = GET_IE_LEN_IN_BSS( descriptor->length );
331
332 if (ie_length > 0)
333 {
Madan Mohan Koyyalamudi729972c2012-10-21 12:39:24 -0700334 /* dot11BeaconIEs is a large struct, so we make it static to
335 avoid stack overflow. This API is only invoked via ioctl,
336 so it is serialized by the kernel rtnl_lock and hence does
337 not need to be reentrant */
338 static tDot11fBeaconIEs dot11BeaconIEs;
Jeff Johnson295189b2012-06-20 16:38:30 -0700339 tDot11fIESSID *pDot11SSID;
340 tDot11fIESuppRates *pDot11SuppRates;
341 tDot11fIEExtSuppRates *pDot11ExtSuppRates;
342 tDot11fIEHTCaps *pDot11IEHTCaps;
343 int numBasicRates = 0;
344 int maxNumRates = 0;
345
346 pDot11IEHTCaps = NULL;
347
348 dot11fUnpackBeaconIEs ((tpAniSirGlobal)
349 hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs);
350
351 pDot11SSID = &dot11BeaconIEs.SSID;
352
353
354 if (pDot11SSID->present ) {
355 last_event = current_event;
356 vos_mem_zero (&event, sizeof (struct iw_event));
357
358 event.cmd = SIOCGIWESSID;
359 event.u.data.flags = 1;
360 event.u.data.length = scan_result->ssId.length;
361 current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
362 &event, (char *)scan_result->ssId.ssId);
363
364 if(last_event == current_event)
365 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530366 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
Jeff Johnson295189b2012-06-20 16:38:30 -0700367 return -E2BIG;
368 }
369 }
370
371 if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, &current_event, scanInfo ) < 0 )
372 {
Sushant Kaushik125ae692014-11-25 17:38:48 +0530373 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
Jeff Johnson295189b2012-06-20 16:38:30 -0700374 return -E2BIG;
375 }
376
377 last_event = current_event;
378 current_pad = current_event + IW_EV_LCP_LEN;
379 vos_mem_zero( &event, sizeof (struct iw_event));
380
381 /*Rates*/
382 event.cmd = SIOCGIWRATE;
383
384
385 pDot11SuppRates = &dot11BeaconIEs.SuppRates;
386
387 if (pDot11SuppRates->present )
388 {
389 int i;
390
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700391 numBasicRates = pDot11SuppRates->num_rates;
Jeff Johnson295189b2012-06-20 16:38:30 -0700392 for (i=0; i<pDot11SuppRates->num_rates; i++)
393 {
394 if (0 != (pDot11SuppRates->rates[i] & 0x7F))
395 {
396 event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
397 &pDot11SuppRates->rates[i]);
398
399 current_pad = iwe_stream_add_value (scanInfo->info,current_event,
400 current_pad, end, &event, IW_EV_PARAM_LEN);
401 }
402 }
403
404 }
405
406 pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates;
407
408 if (pDot11ExtSuppRates->present )
409 {
410 int i,no_of_rates;
411 maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates;
412
413 /* Check to make sure the total number of rates
414 doesn't exceed IW_MAX_BITRATES */
415
416 maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES);
417
418 if((maxNumRates - numBasicRates) > MAX_RATES)
419 {
420 no_of_rates = MAX_RATES;
421 hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates ");
422 }
423 else
424 {
425 no_of_rates = maxNumRates - numBasicRates;
426 }
427 for ( i=0; i< no_of_rates ; i++ )
428 {
429 if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F))
430 {
431 event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
432 &pDot11ExtSuppRates->rates[i]);
433
434 current_pad = iwe_stream_add_value (scanInfo->info,current_event,
435 current_pad, end, &event, IW_EV_PARAM_LEN);
436 }
437 }
438 }
439
440
441 if ((current_pad - current_event) >= IW_EV_LCP_LEN)
442 {
443 current_event = current_pad;
444 }
445 else
446 {
447 if (last_event == current_event)
448 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530449 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWRATE");
Jeff Johnson295189b2012-06-20 16:38:30 -0700450 return -E2BIG;
451 }
452 }
453
454 last_event = current_event;
455 vos_mem_zero (&event, sizeof (struct iw_event));
456
457
458 event.cmd = SIOCGIWENCODE;
459
460 if (SIR_MAC_GET_PRIVACY(capabilityInfo))
461 {
462 event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
463 }
464 else
465 {
466 event.u.data.flags = IW_ENCODE_DISABLED;
467 }
468 event.u.data.length = 0;
469
470 current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid);
471
472
473 if(last_event == current_event)
474 { /* no space to add event
475 Error code, may be E2BIG */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530476 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWENCODE");
Jeff Johnson295189b2012-06-20 16:38:30 -0700477 return -E2BIG;
478 }
479 }
480
481 last_event = current_event;
482 vos_mem_zero( &event, sizeof (struct iw_event));
483
484 /*RSSI*/
485 event.cmd = IWEVQUAL;
486 event.u.qual.qual = descriptor->rssi;
487 event.u.qual.noise = descriptor->sinr;
488
489 /*To keep the rssi icon of the connected AP in the scan window
490 *and the rssi icon of the wireless networks in sync */
491 if (( eConnectionState_Associated ==
492 pAdapter->sessionCtx.station.conn_info.connState ) &&
493 ( VOS_TRUE == vos_mem_compare(descriptor->bssId,
494 pAdapter->sessionCtx.station.conn_info.bssId,
495 WNI_CFG_BSSID_LEN)))
496 {
497 event.u.qual.level = pAdapter->rssi;
498 }
499 else
500 {
501 event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0);
502 }
503
504 event.u.qual.updated = IW_QUAL_ALL_UPDATED;
505
506 current_event = iwe_stream_add_event(scanInfo->info,current_event,
507 end, &event, IW_EV_QUAL_LEN);
508
509 if(last_event == current_event)
510 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530511 hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVQUAL");
Jeff Johnson295189b2012-06-20 16:38:30 -0700512 return -E2BIG;
513 }
514
515
516 /* AGE */
517 event.cmd = IWEVCUSTOM;
518 p = custom;
Sameer Thalappilb0a30232013-09-27 15:37:48 -0700519 p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu",
Jeff Johnson295189b2012-06-20 16:38:30 -0700520 vos_timer_get_system_ticks() - descriptor->nReceivedTime);
521 event.u.data.length = p - custom;
522 current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
523 &event, custom);
524 if(last_event == current_event)
525 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530526 hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)");
Jeff Johnson295189b2012-06-20 16:38:30 -0700527 return -E2BIG;
528 }
529
530 scanInfo->start = current_event;
531
532 return 0;
533}
534
535/**---------------------------------------------------------------------------
536
Siddharth Bhal76972212014-10-15 16:22:51 +0530537 \brief hdd_processSpoofMacAddrRequest() -
538
539 The function is called from scan completion callback and from
540 cfg80211 vendor command
541
542 \param - pHddCtx - Pointer to the HDD Context.
543
544 \return - 0 for success, non zero for failure
545
546 --------------------------------------------------------------------------*/
547
548VOS_STATUS hdd_processSpoofMacAddrRequest(hdd_context_t *pHddCtx)
549{
550
551 ENTER();
552
553 mutex_lock(&pHddCtx->spoofMacAddr.macSpoofingLock);
554
555 if (pHddCtx->spoofMacAddr.isEnabled) {
556 if (VOS_STATUS_SUCCESS != vos_randomize_n_bytes(
557 (void *)(&pHddCtx->spoofMacAddr.randomMacAddr.bytes[3]),
558 VOS_MAC_ADDR_LAST_3_BYTES)) {
559 hddLog(LOGE, FL("Failed to generate random Mac Addr"));
560 pHddCtx->spoofMacAddr.isEnabled = FALSE;
561 mutex_unlock(&pHddCtx->spoofMacAddr.macSpoofingLock);
562 return VOS_STATUS_E_FAILURE;
563 }
564 }
565
566 hddLog(LOG1, FL("New Mac Addr Generated "MAC_ADDRESS_STR),
567 MAC_ADDR_ARRAY(pHddCtx->spoofMacAddr.randomMacAddr.bytes));
568
569 if (pHddCtx->scan_info.mScanPending != TRUE)
570 {
571 pHddCtx->spoofMacAddr.isReqDeferred = FALSE;
572 hddLog(LOG1, FL("Processing Spoof request now"));
573 /* Inform SME about spoof mac addr request*/
574 if ( eHAL_STATUS_SUCCESS != sme_SpoofMacAddrReq(pHddCtx->hHal,
575 &pHddCtx->spoofMacAddr.randomMacAddr))
576 {
577 hddLog(LOGE, FL("Sending Spoof request failed - Disable spoofing"));
578 pHddCtx->spoofMacAddr.isEnabled = FALSE;
579 }
580 } else
581 {
582 hddLog(LOG1, FL("Scan in Progress. Spoofing Deferred"));
583 pHddCtx->spoofMacAddr.isReqDeferred = TRUE;
584 }
585
586 mutex_unlock(&pHddCtx->spoofMacAddr.macSpoofingLock);
587
588 EXIT();
589
590 return VOS_STATUS_SUCCESS;
591}
592
593/**---------------------------------------------------------------------------
594
Jeff Johnson295189b2012-06-20 16:38:30 -0700595 \brief hdd_ScanRequestCallback() -
596
597 The sme module calls this callback function once it finish the scan request
598 and this function notifies the scan complete event to the wpa_supplicant.
599
600 \param - halHandle - Pointer to the Hal Handle.
601 - pContext - Pointer to the data context.
602 - scanId - Scan ID.
603 - status - CSR Status.
604 \return - 0 for success, non zero for failure
605
606 --------------------------------------------------------------------------*/
607
608static eHalStatus hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext,
609 tANI_U32 scanId, eCsrScanStatus status)
610{
611 struct net_device *dev = (struct net_device *) pContext;
612 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700613 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700614 union iwreq_data wrqu;
615 int we_event;
616 char *msg;
617
618 ENTER();
619
620 hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700621 " returned status = %d", __func__, halHandle, pContext,
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 (int) scanId, (int) status);
623
624 /* if there is a scan request pending when the wlan driver is unloaded
625 we may be invoked as SME flushes its pending queue. If that is the
626 case, the underlying net_device may have already been destroyed, so
627 do some quick sanity before proceeding */
628 if (pAdapter->dev != dev)
629 {
630 hddLog(LOGW, "%s: device mismatch %p vs %p",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700631 __func__, pAdapter->dev, dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700632 return eHAL_STATUS_SUCCESS;
633 }
634
635 /* Check the scanId */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700636 if (pHddCtx->scan_info.scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -0700637 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700638 hddLog(LOGW, "%s called with mismatched scanId pHddCtx->scan_info.scanId = %d "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700639 "scanId = %d ", __func__, (int) pHddCtx->scan_info.scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -0700640 (int) scanId);
641 }
642
643 /* Scan is no longer pending */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700644 pHddCtx->scan_info.mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700645
646 // notify any applications that may be interested
647 memset(&wrqu, '\0', sizeof(wrqu));
648 we_event = SIOCGIWSCAN;
649 msg = NULL;
650 wireless_send_event(dev, we_event, &wrqu, msg);
651
652 EXIT();
653
654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
655
656 return eHAL_STATUS_SUCCESS;
657}
658
659/**---------------------------------------------------------------------------
660
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530661 \brief __iw_set_scan() -
Jeff Johnson295189b2012-06-20 16:38:30 -0700662
663 This function process the scan request from the wpa_supplicant
664 and set the scan request to the SME
665
666 \param - dev - Pointer to the net device.
667 - info - Pointer to the iw_request_info.
668 - wrqu - Pointer to the iwreq_data.
669 - extra - Pointer to the data.
670 \return - 0 for success, non zero for failure
671
672 --------------------------------------------------------------------------*/
673
674
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530675int __iw_set_scan(struct net_device *dev, struct iw_request_info *info,
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 union iwreq_data *wrqu, char *extra)
677{
678 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700679 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700680 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
681 tCsrScanRequest scanRequest;
682 v_U32_t scanId = 0;
683 eHalStatus status = eHAL_STATUS_SUCCESS;
684 struct iw_scan_req *scanReq = (struct iw_scan_req *)extra;
685
686 ENTER();
687
688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
689
690#ifdef WLAN_BTAMP_FEATURE
691 //Scan not supported when AMP traffic is on.
692 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
693 {
694 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
695 return eHAL_STATUS_SUCCESS;
696 }
697#endif
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700698 if(pHddCtx->scan_info.mScanPending == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700699 {
700 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
701 return eHAL_STATUS_SUCCESS;
702 }
703
704 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
705 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
706 return eHAL_STATUS_SUCCESS;
707 }
708 vos_mem_zero( &scanRequest, sizeof(scanRequest));
709
710 if (NULL != wrqu->data.pointer)
711 {
712 /* set scanType, active or passive */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700713 if ((IW_SCAN_TYPE_ACTIVE == scanReq->scan_type) || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -0700714 {
715 scanRequest.scanType = eSIR_ACTIVE_SCAN;
716 }
717 else
718 {
719 scanRequest.scanType = eSIR_PASSIVE_SCAN;
720 }
721
722 /* set bssid using sockaddr from iw_scan_req */
723 vos_mem_copy(scanRequest.bssid,
724 &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) );
725
726 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
727
728 if(scanReq->essid_len) {
729 scanRequest.SSIDs.numOfSSIDs = 1;
730 scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
731 if(scanRequest.SSIDs.SSIDList) {
732 scanRequest.SSIDs.SSIDList->SSID.length = scanReq->essid_len;
733 vos_mem_copy(scanRequest.SSIDs.SSIDList-> SSID.ssId,scanReq->essid,scanReq->essid_len);
734 }
735 else
736 {
737 scanRequest.SSIDs.numOfSSIDs = 0;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700739 VOS_ASSERT(0);
740 }
741 }
742 }
743
744 /* set min and max channel time */
745 scanRequest.minChnTime = scanReq->min_channel_time;
746 scanRequest.maxChnTime = scanReq->max_channel_time;
747
748 }
749 else
750 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700751 if(pHddCtx->scan_info.scan_mode == eSIR_ACTIVE_SCAN) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700752 /* set the scan type to active */
753 scanRequest.scanType = eSIR_ACTIVE_SCAN;
754 } else {
755 scanRequest.scanType = eSIR_PASSIVE_SCAN;
756 }
757
758 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
759
760 /* set min and max channel time to zero */
761 scanRequest.minChnTime = 0;
762 scanRequest.maxChnTime = 0;
763 }
764
765 /* set BSSType to default type */
766 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
767
768 /*Scan all the channels */
769 scanRequest.ChannelInfo.numOfChannels = 0;
770
771 scanRequest.ChannelInfo.ChannelList = NULL;
772
773 /* set requestType to full scan */
774 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
775
776 /* if previous genIE is not NULL, update ScanIE */
777 if (0 != pwextBuf->genIE.length)
778 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700779 memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
780 memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 pwextBuf->genIE.length );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700782 pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
Agarwal Ashish4f616132013-12-30 23:32:50 +0530783 /* Maximum length of each IE is SIR_MAC_MAX_IE_LENGTH */
784 if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length)
785 {
786 memcpy( pwextBuf->roamProfile.addIEScan,
787 pHddCtx->scan_info.scanAddIE.addIEdata,
788 pHddCtx->scan_info.scanAddIE.length);
789 pwextBuf->roamProfile.nAddIEScanLength =
790 pHddCtx->scan_info.scanAddIE.length;
791 }
792 else
793 {
794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
795 "Invalid ScanIE, Length is %d", pwextBuf->genIE.length);
796 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700797 /* clear previous genIE after use it */
798 memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
799 }
800
801 /* push addIEScan in scanRequset if exist */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700802 if (pHddCtx->scan_info.scanAddIE.addIEdata &&
803 pHddCtx->scan_info.scanAddIE.length)
Jeff Johnson295189b2012-06-20 16:38:30 -0700804 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700805 scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
806 scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
Jeff Johnson295189b2012-06-20 16:38:30 -0700807 }
808
809 status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
810 if (!HAL_STATUS_SUCCESS(status))
811 {
812 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest fail %d!!!",__func__, status);
813 goto error;
814 }
815
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700816 pHddCtx->scan_info.mScanPending = TRUE;
Kaushik, Sushantdedd4ea2014-11-06 11:55:14 +0530817 pHddCtx->scan_info.sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700818
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700819 pHddCtx->scan_info.scanId = scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700820
821error:
822 if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len))
823 vos_mem_free(scanRequest.SSIDs.SSIDList);
824
825 EXIT();
826
827 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
828 return status;
829}
830
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530831int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
832 union iwreq_data *wrqu, char *extra)
833{
834 int ret;
835
836 vos_ssr_protect(__func__);
837 ret = __iw_set_scan(dev, info, wrqu, extra);
838 vos_ssr_unprotect(__func__);
839
840 return ret;
841}
842
Jeff Johnson295189b2012-06-20 16:38:30 -0700843/**---------------------------------------------------------------------------
844
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530845 \brief __iw_get_scan() -
Jeff Johnson295189b2012-06-20 16:38:30 -0700846
847 This function returns the scan results to the wpa_supplicant
848
849 \param - dev - Pointer to the net device.
850 - info - Pointer to the iw_request_info.
851 - wrqu - Pointer to the iwreq_data.
852 - extra - Pointer to the data.
853 \return - 0 for success, non zero for failure
854
855 --------------------------------------------------------------------------*/
856
857
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530858int __iw_get_scan(struct net_device *dev,
859 struct iw_request_info *info,
860 union iwreq_data *wrqu, char *extra)
Jeff Johnson295189b2012-06-20 16:38:30 -0700861{
862 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700863 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700864 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
865 tCsrScanResultInfo *pScanResult;
866 eHalStatus status = eHAL_STATUS_SUCCESS;
867 hdd_scan_info_t scanInfo;
868 tScanResultHandle pResult;
869 int i = 0;
870
871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!",
872 __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA);
873 ENTER();
874
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700875 if (TRUE == pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -0700876 {
877 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
878 return -EAGAIN;
879 }
880
881 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
883 return -EAGAIN;
884 }
885
886 scanInfo.dev = dev;
887 scanInfo.start = extra;
888 scanInfo.info = info;
889
890 if (0 == wrqu->data.length)
891 {
892 scanInfo.end = extra + IW_SCAN_MAX_DATA;
893 }
894 else
895 {
896 scanInfo.end = extra + wrqu->data.length;
897 }
898
899 status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult);
900
901 if (NULL == pResult)
902 {
903 // no scan results
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530904 hddLog(LOG1,"__iw_get_scan: NULL Scan Result ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700905 return 0;
906 }
907
908 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
909
910 while (pScanResult)
911 {
912 status = hdd_IndicateScanResult(&scanInfo, pScanResult);
913 if (0 != status)
914 {
915 break;
916 }
917 i++;
918 pScanResult = sme_ScanResultGetNext(hHal, pResult);
919 }
920
921 sme_ScanResultPurge(hHal, pResult);
922
923 EXIT();
924 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i);
925 return status;
926}
927
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530928int iw_get_scan(struct net_device *dev,
929 struct iw_request_info *info,
930 union iwreq_data *wrqu, char *extra)
931{
932 int ret;
933
934 vos_ssr_protect(__func__);
935 ret = __iw_get_scan(dev, info, wrqu, extra);
936 vos_ssr_unprotect(__func__);
937
938 return ret;
939}
940
Jeff Johnson295189b2012-06-20 16:38:30 -0700941#if 0
942static eHalStatus hdd_CscanRequestCallback(tHalHandle halHandle, void *pContext,
943 tANI_U32 scanId, eCsrScanStatus status)
944{
945 struct net_device *dev = (struct net_device *) pContext;
946 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
947 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
948 union iwreq_data wrqu;
949 int we_event;
950 char *msg;
951 VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
952 ENTER();
953
954 hddLog(LOG1,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700955 " returned status = %d", __func__, halHandle, pContext,
Jeff Johnson295189b2012-06-20 16:38:30 -0700956 (int) scanId, (int) status);
957
958 /* Check the scanId */
959 if (pwextBuf->scanId != scanId)
960 {
961 hddLog(LOGW, "%s called with mismatched scanId pWextState->scanId = %d "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700962 "scanId = %d ", __func__, (int) pwextBuf->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -0700963 (int) scanId);
964 }
965
966 /* Scan is no longer pending */
967 pwextBuf->mScanPending = VOS_FALSE;
968
969 // notify any applications that may be interested
970 memset(&wrqu, '\0', sizeof(wrqu));
971 we_event = SIOCGIWSCAN;
972 msg = NULL;
973 wireless_send_event(dev, we_event, &wrqu, msg);
974
975 vos_status = vos_event_set(&pwextBuf->vosevent);
976
977 if (!VOS_IS_STATUS_SUCCESS(vos_status))
978 {
979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos_event_set failed!!"));
980 return VOS_STATUS_E_FAILURE;
981 }
982
983 EXIT();
984 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
985
986 return eHAL_STATUS_SUCCESS;
987}
988#endif
989
990int iw_set_cscan(struct net_device *dev, struct iw_request_info *info,
991 union iwreq_data *wrqu, char *extra)
992{
993 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700994 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
996 tCsrScanRequest scanRequest;
997 v_U32_t scanId = 0;
998 eHalStatus status = eHAL_STATUS_SUCCESS;
999 v_U8_t channelIdx;
1000
1001 ENTER();
1002 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
1003
1004#ifdef WLAN_BTAMP_FEATURE
1005 //Scan not supported when AMP traffic is on.
1006 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
1007 {
1008 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
1009 return eHAL_STATUS_SUCCESS;
1010 }
1011#endif
1012
1013 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1014 {
1015 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1016 return eHAL_STATUS_SUCCESS;
1017 }
1018
1019 vos_mem_zero( &scanRequest, sizeof(scanRequest));
1020 if (NULL != wrqu->data.pointer)
1021 {
1022 char *str_ptr = NULL;
1023 tCsrSSIDInfo *SsidInfo = NULL;
1024 int num_ssid = 0;
1025 int i, j, ssid_start;
1026 hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP;
1027
Rajeev Kumarbe97df02013-10-24 18:30:39 -07001028 str_ptr = extra;
Jeff Johnson295189b2012-06-20 16:38:30 -07001029
1030 i = WEXT_CSCAN_HEADER_SIZE;
1031
1032 if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] )
1033 {
1034 scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i];
1035 ++i;
1036 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001037 pHddCtx->scan_info.scan_pending_option = scanPendingOption;
Jeff Johnson295189b2012-06-20 16:38:30 -07001038
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001039 if(pHddCtx->scan_info.mScanPending == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07001040 {
1041 hddLog(LOG1,"%s: mScanPending is TRUE",__func__);
1042 /* If any scan is pending, just giveup this scan request */
1043 if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption)
1044 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001045 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001046 return eHAL_STATUS_SUCCESS;
1047 }
1048 /* If any scan pending, wait till finish current scan,
1049 and try this scan request when previous scan finish */
1050 else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption)
1051 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001052 pHddCtx->scan_info.waitScanResult = TRUE;
1053 vos_event_reset(&pHddCtx->scan_info.scan_finished_event);
1054 if(vos_wait_single_event(&pHddCtx->scan_info.scan_finished_event,
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 WEXT_CSCAN_SCAN_DONE_WAIT_TIME))
1056 {
1057 hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__);
1058 return eHAL_STATUS_SUCCESS;
1059 }
1060 }
1061 /* Piggyback previous scan result */
1062 else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption)
1063 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001064 pHddCtx->scan_info.waitScanResult = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001065 return eHAL_STATUS_SUCCESS;
1066 }
1067 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001068 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001069
1070 /* Check for scan IE */
1071 while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] )
1072 {
1073 /* ssid_len */
1074 if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION)
1075 {
1076 /* total number of ssid's */
1077 num_ssid++;
1078 /* increment length filed */
1079 i += str_ptr[i] + 1;
1080 }
1081 /* i should be saved and it will be pointing to 'C' */
1082 }
1083
1084 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid);
1085 if( num_ssid )
1086 {
1087 /* To be fixed in SME and PE: override the number of ssid with 1,
1088 * as SME and PE does not handle multiple SSID in scan request
1089 * */
1090 scanRequest.SSIDs.numOfSSIDs = num_ssid;
1091 /* Allocate num_ssid tCsrSSIDInfo structure */
1092 SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo));
1093 if(NULL == scanRequest.SSIDs.SSIDList) {
1094 hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer");
1095 return -ENOMEM;
1096 }
1097
1098 /* copy all the ssid's and their length */
1099 ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;/* skipping 'S' */
1100 for(j = 0; j < num_ssid; j++) {
1101 if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){
1102 scanRequest.SSIDs.numOfSSIDs -= 1;
1103 } else{
1104 /* get the ssid length */
1105 SsidInfo->SSID.length = str_ptr[ssid_start++];
1106 vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length);
Arif Hussain6d2a3322013-11-17 19:50:10 -08001107 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s", j, SsidInfo->SSID.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 }
1109 /* skipping length */
1110 ssid_start += str_ptr[ssid_start - 1] + 1;
1111 /* Store next ssid info */
1112 SsidInfo++;
1113 }
1114 }
1115
1116 /* Check for Channel IE */
1117 if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i])
1118 {
1119 if( str_ptr[++i] == 0 )
1120 {
1121 scanRequest.ChannelInfo.numOfChannels = 0;
1122 scanRequest.ChannelInfo.ChannelList = NULL;
1123 i++;
1124 }
1125 else {
1126
1127 /* increment the counter */
1128 scanRequest.ChannelInfo.numOfChannels = str_ptr[i++];
1129 /* store temp channel list */
1130 /* SME expects 1 byte channel content */
1131 scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t));
1132 if(NULL == scanRequest.ChannelInfo.ChannelList)
1133 {
c_hpothu7f63e882013-10-02 19:13:35 +05301134 hddLog(LOGE, "memory alloc failed for channel list creation");
Jeff Johnson295189b2012-06-20 16:38:30 -07001135 status = -ENOMEM;
1136 goto exit_point;
1137 }
1138
1139 for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++)
1140 {
1141 /* SCAN request from upper layer has 2 bytes channel */
1142 scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i];
1143 i += sizeof(v_U16_t);
1144 }
1145 }
1146 }
1147
1148 /* Set default */
1149 scanRequest.scanType = eSIR_ACTIVE_SCAN;
1150 scanRequest.minChnTime = 0;
1151 scanRequest.maxChnTime = 0;
1152
1153 /* Now i is pointing to passive dwell dwell time */
1154 /* 'P',min dwell time, max dwell time */
1155 /* next two offsets contain min and max channel time */
1156 if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) )
1157 {
1158 /* No SSID specified, num_ssid == 0, then start paasive scan */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001159 if (!num_ssid || (eSIR_PASSIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001160 {
1161 scanRequest.scanType = eSIR_PASSIVE_SCAN;
1162 scanRequest.minChnTime = (v_U8_t)str_ptr[++i];//scanReq->min_channel_time;
1163 scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];//scanReq->max_channel_time;
1164 i++;
1165 }
1166 else
1167 {
1168 i += 3;
1169 }
1170 }
1171
1172 /* H indicates active channel time */
1173 if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) )
1174 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001175 if (num_ssid || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 {
1177 scanRequest.scanType = eSIR_ACTIVE_SCAN;
1178 scanRequest.minChnTime = str_ptr[++i];//scanReq->min_channel_time;
1179 scanRequest.maxChnTime = str_ptr[++i];//scanReq->max_channel_time;
1180 i++;
1181 }
1182 else
1183 {
1184 i +=3;
1185 }
1186 }
1187 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
1188 /* set requestType to full scan */
1189 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001190 pHddCtx->scan_info.mScanPending = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001191
1192 /* if previous genIE is not NULL, update ScanIE */
1193 if(0 != pwextBuf->genIE.length)
1194 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001195 memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
1196 memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
Jeff Johnson295189b2012-06-20 16:38:30 -07001197 pwextBuf->genIE.length );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001198 pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
Agarwal Ashish4f616132013-12-30 23:32:50 +05301199 if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length)
1200 {
1201 memcpy( pwextBuf->roamProfile.addIEScan,
1202 pHddCtx->scan_info.scanAddIE.addIEdata,
1203 pHddCtx->scan_info.scanAddIE.length);
1204 pwextBuf->roamProfile.nAddIEScanLength =
1205 pHddCtx->scan_info.scanAddIE.length;
1206 }
1207 else
1208 {
1209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1210 "Invalid ScanIE, Length is %d",
1211 pwextBuf->genIE.length);
1212 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001213
1214 /* clear previous genIE after use it */
1215 memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
1216 }
1217
1218 /* push addIEScan in scanRequset if exist */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001219 if (pHddCtx->scan_info.scanAddIE.addIEdata &&
1220 pHddCtx->scan_info.scanAddIE.length)
Jeff Johnson295189b2012-06-20 16:38:30 -07001221 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001222 scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
1223 scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
Jeff Johnson295189b2012-06-20 16:38:30 -07001224 }
1225
1226 status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal,
1227 pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
1228 if( !HAL_STATUS_SUCCESS(status) )
1229 {
1230 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: SME scan fail status %d !!!",__func__, status);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001231 pHddCtx->scan_info.mScanPending = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001232 status = -EINVAL;
1233 goto exit_point;
1234 }
1235
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001236 pHddCtx->scan_info.scanId = scanId;
Kaushik, Sushantdedd4ea2014-11-06 11:55:14 +05301237 pHddCtx->scan_info.sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -07001238
1239 } //end of data->pointer
1240 else {
1241 status = -1;
1242 }
1243
1244exit_point:
1245
1246 /* free ssidlist */
1247 if (scanRequest.SSIDs.SSIDList)
1248 {
1249 vos_mem_free(scanRequest.SSIDs.SSIDList);
1250 }
1251 /* free the channel list */
1252 if(scanRequest.ChannelInfo.ChannelList)
1253 {
1254 vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList);
1255 }
1256
1257 EXIT();
1258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
1259 return status;
1260}
1261
1262/* Abort any MAC scan if in progress */
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05301263void hdd_abort_mac_scan(hdd_context_t* pHddCtx, tANI_U8 sessionId,
1264 eCsrAbortReason reason)
Jeff Johnson295189b2012-06-20 16:38:30 -07001265{
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05301266 sme_AbortMacScan(pHddCtx->hHal, sessionId, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07001267}
1268