blob: 7c79abef923a2430e3d4ea03211aab86d044cad3 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302 * Copyright (c) 2012-2015 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
Jeff Johnson295189b2012-06-20 16:38:30 -070034
35 ========================================================================*/
36
37/**=========================================================================
38
39 EDIT HISTORY FOR FILE
40
41
42 This section contains comments describing changes made to the module.
43 Notice that changes are listed in reverse chronological order.
44
45
46 $Header:$ $DateTime: $ $Author: $
47
48
49 when who what, where, why
50 -------- --- --------------------------------------------------------
51 04/5/09 Shailender Created module.
52
53 ==========================================================================*/
54 /* To extract the Scan results */
55
56/* Add a stream event */
57
58#include <wlan_qct_driver.h>
59#include <wlan_hdd_includes.h>
60#include <vos_api.h>
61#include <palTypes.h>
62#include <aniGlobal.h>
63#include <dot11f.h>
64#ifdef WLAN_BTAMP_FEATURE
65#include "bap_hdd_misc.h"
66#endif
67
Jeff Johnson295189b2012-06-20 16:38:30 -070068#include <linux/wireless.h>
69#include <net/cfg80211.h>
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053070#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071
72#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
73#define WEXT_CSCAN_HEADER_SIZE 12
74#define WEXT_CSCAN_SSID_SECTION 'S'
75#define WEXT_CSCAN_CHANNEL_SECTION 'C'
76#define WEXT_CSCAN_NPROBE_SECTION 'N'
77#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
78#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
79#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
80#define WEXT_CSCAN_TYPE_SECTION 'T'
81#define WEXT_CSCAN_PENDING_SECTION 'O'
82#define WEXT_CSCAN_TYPE_DEFAULT 0
83#define WEXT_CSCAN_TYPE_PASSIVE 1
84#define WEXT_CSCAN_PASV_DWELL_TIME 130
85#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
86#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
87#define WEXT_CSCAN_HOME_DWELL_TIME 130
88#define MAX_RATES 12
89
90#define WEXT_CSCAN_SCAN_DONE_WAIT_TIME 2000
91
92typedef struct hdd_scan_info{
93 struct net_device *dev;
94 struct iw_request_info *info;
95 char *start;
96 char *end;
97} hdd_scan_info_t, *hdd_scan_info_tp;
98
99static v_S31_t hdd_TranslateABGRateToMbpsRate(v_U8_t *pFcRate)
100{
101
102 /** Slightly more sophisticated processing has to take place here.
103 Basic rates are rounded DOWN. HT rates are rounded UP.*/
104 return ( (( ((v_S31_t) *pFcRate) & 0x007f) * 1000000) / 2);
105}
106
107
108static eHalStatus hdd_AddIwStreamEvent(int cmd, int length, char* data, hdd_scan_info_t *pscanInfo, char **last_event, char **current_event )
109{
110 struct iw_event event;
111
112 *last_event = *current_event;
113 vos_mem_zero(&event, sizeof (struct iw_event));
114 event.cmd = cmd;
115 event.u.data.flags = 1;
116 event.u.data.length = length;
117 *current_event = iwe_stream_add_point (pscanInfo->info,*current_event, pscanInfo->end, &event, data);
118
119 if(*last_event == *current_event)
120 {
121 /* no space to add event */
c_hpothu7f63e882013-10-02 19:13:35 +0530122 hddLog( LOGW, "%s: no space left to add event", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700123 return -E2BIG; /* Error code, may be E2BIG */
124 }
125
126 return 0;
127}
128
129/**---------------------------------------------------------------------------
130
131 \brief hdd_GetWPARSNIEs() -
132
133 This function extract the WPA/RSN IE from the Bss descriptor IEs fields
134
135 \param - ieFields - Pointer to the Bss Descriptor IEs.
136 - ie_length - IE Length.
137 - last_event -Points to the last event.
138 - current_event - Points to the
139 \return - 0 for success, non zero for failure
140
141 --------------------------------------------------------------------------*/
142
143
144/* Extract the WPA and/or RSN IEs */
145static eHalStatus hdd_GetWPARSNIEs( v_U8_t *ieFields, v_U16_t ie_length, char **last_event, char **current_event, hdd_scan_info_t *pscanInfo )
146{
147 v_U8_t eid, elen, *element;
148 v_U16_t tie_length=0;
149
150 ENTER();
151
152 element = ieFields;
153 tie_length = ie_length;
154
155 while( tie_length > 2 && element != NULL )
156 {
157 eid = element[0];
158 elen = element[1];
159
160 /*If element length is greater than total remaining ie length,
161 *break the loop*/
162 if ((elen+2) > tie_length)
163 break;
164
165 switch(eid)
166 {
167 case DOT11F_EID_WPA:
168 case DOT11F_EID_RSN:
169#ifdef FEATURE_WLAN_WAPI
170 case DOT11F_EID_WAPI:
171#endif
172 if(hdd_AddIwStreamEvent( IWEVGENIE, elen+2, (char*)element, pscanInfo, last_event, current_event ) < 0 )
173 return -E2BIG;
174 break;
175
176 default:
177 break;
178 }
179
180 /* Next element */
181 tie_length -= (2 + elen);
182 element += 2 + elen;
183 }
184
185 return 0;
186}
187
188/**---------------------------------------------------------------------------
189
190 \brief hdd_IndicateScanResult() -
191
192 This function returns the scan results to the wpa_supplicant
193
194 \param - scanInfo - Pointer to the scan info structure.
195 - descriptor - Pointer to the Bss Descriptor.
196
197 \return - 0 for success, non zero for failure
198
199 --------------------------------------------------------------------------*/
200#define MAX_CUSTOM_LEN 64
201static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result)
202{
203 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ;
204 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
205 tSirBssDescription *descriptor = &scan_result->BssDescriptor;
206 struct iw_event event;
207 char *current_event = scanInfo->start;
208 char *end = scanInfo->end;
209 char *last_event;
210 char *current_pad;
211 v_U16_t ie_length = 0;
212 v_U16_t capabilityInfo;
213 char *modestr;
214 int error;
215 char custom[MAX_CUSTOM_LEN];
216 char *p;
217
Arif Hussain24bafea2013-11-15 15:10:03 -0800218 hddLog( LOG1, "hdd_IndicateScanResult " MAC_ADDRESS_STR,
219 MAC_ADDR_ARRAY(descriptor->bssId));
Jeff Johnson295189b2012-06-20 16:38:30 -0700220
221 error = 0;
222 last_event = current_event;
223 vos_mem_zero(&event, sizeof (event));
224
225 /* BSSID */
226 event.cmd = SIOCGIWAP;
227 event.u.ap_addr.sa_family = ARPHRD_ETHER;
228 vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId,
229 sizeof (descriptor->bssId));
230 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
231 &event, IW_EV_ADDR_LEN);
232
233 if (last_event == current_event)
234 {
235 /* no space to add event */
236 /* Error code may be E2BIG */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530237 hddLog(LOGE, "hdd_IndicateScanResult: no space for SIOCGIWAP ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 return -E2BIG;
239 }
240
241 last_event = current_event;
242 vos_mem_zero(&event, sizeof (struct iw_event));
243
244 /* Protocol Name */
245 event.cmd = SIOCGIWNAME;
246
247 switch (descriptor->nwType)
248 {
249 case eSIR_11A_NW_TYPE:
250 modestr = "a";
251 break;
252 case eSIR_11B_NW_TYPE:
253 modestr = "b";
254 break;
255 case eSIR_11G_NW_TYPE:
256 modestr = "g";
257 break;
258 case eSIR_11N_NW_TYPE:
259 modestr = "n";
260 break;
261 default:
262 hddLog( LOGW, "%s: Unknown network type [%d]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700263 __func__, descriptor->nwType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700264 modestr = "?";
265 break;
266 }
267 snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr);
268 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
269 &event, IW_EV_CHAR_LEN);
270
271 if (last_event == current_event)
272 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530273 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWNAME");
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 /* Error code, may be E2BIG */
275 return -E2BIG;
276 }
277
278 last_event = current_event;
279 vos_mem_zero( &event, sizeof (struct iw_event));
280
281 /*Freq*/
282 event.cmd = SIOCGIWFREQ;
283
284 event.u.freq.m = descriptor->channelId;
285 event.u.freq.e = 0;
286 event.u.freq.i = 0;
287 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
288 &event, IW_EV_FREQ_LEN);
289
290 if (last_event == current_event)
291 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530292 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWFREQ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 return -E2BIG;
294 }
295
296 last_event = current_event;
297 vos_mem_zero( &event, sizeof (struct iw_event));
298
299 /* BSS Mode */
300 event.cmd = SIOCGIWMODE;
301
302 capabilityInfo = descriptor->capabilityInfo;
303
304 if (SIR_MAC_GET_ESS(capabilityInfo))
305 {
306 event.u.mode = IW_MODE_INFRA;
307 }
308 else if (SIR_MAC_GET_IBSS(capabilityInfo))
309 {
310 event.u.mode = IW_MODE_ADHOC;
311 }
312 else
313 {
314 /* neither ESS or IBSS */
315 event.u.mode = IW_MODE_AUTO;
316 }
317
318 current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
319 &event, IW_EV_UINT_LEN);
320
321 if (last_event == current_event)
322 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530323 hddLog(LOGE, "hdd_IndicateScanResult: no space for SIOCGIWMODE");
Jeff Johnson295189b2012-06-20 16:38:30 -0700324 return -E2BIG;
325 }
326 /* To extract SSID */
327 ie_length = GET_IE_LEN_IN_BSS( descriptor->length );
328
329 if (ie_length > 0)
330 {
Madan Mohan Koyyalamudi729972c2012-10-21 12:39:24 -0700331 /* dot11BeaconIEs is a large struct, so we make it static to
332 avoid stack overflow. This API is only invoked via ioctl,
333 so it is serialized by the kernel rtnl_lock and hence does
334 not need to be reentrant */
335 static tDot11fBeaconIEs dot11BeaconIEs;
Jeff Johnson295189b2012-06-20 16:38:30 -0700336 tDot11fIESSID *pDot11SSID;
337 tDot11fIESuppRates *pDot11SuppRates;
338 tDot11fIEExtSuppRates *pDot11ExtSuppRates;
339 tDot11fIEHTCaps *pDot11IEHTCaps;
340 int numBasicRates = 0;
341 int maxNumRates = 0;
342
343 pDot11IEHTCaps = NULL;
344
345 dot11fUnpackBeaconIEs ((tpAniSirGlobal)
346 hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs);
347
348 pDot11SSID = &dot11BeaconIEs.SSID;
349
350
351 if (pDot11SSID->present ) {
352 last_event = current_event;
353 vos_mem_zero (&event, sizeof (struct iw_event));
354
355 event.cmd = SIOCGIWESSID;
356 event.u.data.flags = 1;
357 event.u.data.length = scan_result->ssId.length;
358 current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
359 &event, (char *)scan_result->ssId.ssId);
360
361 if(last_event == current_event)
362 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530363 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
Jeff Johnson295189b2012-06-20 16:38:30 -0700364 return -E2BIG;
365 }
366 }
367
368 if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, &current_event, scanInfo ) < 0 )
369 {
Sushant Kaushik125ae692014-11-25 17:38:48 +0530370 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
Jeff Johnson295189b2012-06-20 16:38:30 -0700371 return -E2BIG;
372 }
373
374 last_event = current_event;
375 current_pad = current_event + IW_EV_LCP_LEN;
376 vos_mem_zero( &event, sizeof (struct iw_event));
377
378 /*Rates*/
379 event.cmd = SIOCGIWRATE;
380
381
382 pDot11SuppRates = &dot11BeaconIEs.SuppRates;
383
384 if (pDot11SuppRates->present )
385 {
386 int i;
387
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700388 numBasicRates = pDot11SuppRates->num_rates;
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 for (i=0; i<pDot11SuppRates->num_rates; i++)
390 {
391 if (0 != (pDot11SuppRates->rates[i] & 0x7F))
392 {
393 event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
394 &pDot11SuppRates->rates[i]);
395
396 current_pad = iwe_stream_add_value (scanInfo->info,current_event,
397 current_pad, end, &event, IW_EV_PARAM_LEN);
398 }
399 }
400
401 }
402
403 pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates;
404
405 if (pDot11ExtSuppRates->present )
406 {
407 int i,no_of_rates;
408 maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates;
409
410 /* Check to make sure the total number of rates
411 doesn't exceed IW_MAX_BITRATES */
412
413 maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES);
414
415 if((maxNumRates - numBasicRates) > MAX_RATES)
416 {
417 no_of_rates = MAX_RATES;
418 hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates ");
419 }
420 else
421 {
422 no_of_rates = maxNumRates - numBasicRates;
423 }
424 for ( i=0; i< no_of_rates ; i++ )
425 {
426 if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F))
427 {
428 event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
429 &pDot11ExtSuppRates->rates[i]);
430
431 current_pad = iwe_stream_add_value (scanInfo->info,current_event,
432 current_pad, end, &event, IW_EV_PARAM_LEN);
433 }
434 }
435 }
436
437
438 if ((current_pad - current_event) >= IW_EV_LCP_LEN)
439 {
440 current_event = current_pad;
441 }
442 else
443 {
444 if (last_event == current_event)
445 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530446 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWRATE");
Jeff Johnson295189b2012-06-20 16:38:30 -0700447 return -E2BIG;
448 }
449 }
450
451 last_event = current_event;
452 vos_mem_zero (&event, sizeof (struct iw_event));
453
454
455 event.cmd = SIOCGIWENCODE;
456
457 if (SIR_MAC_GET_PRIVACY(capabilityInfo))
458 {
459 event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
460 }
461 else
462 {
463 event.u.data.flags = IW_ENCODE_DISABLED;
464 }
465 event.u.data.length = 0;
466
467 current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid);
468
469
470 if(last_event == current_event)
471 { /* no space to add event
472 Error code, may be E2BIG */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530473 hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWENCODE");
Jeff Johnson295189b2012-06-20 16:38:30 -0700474 return -E2BIG;
475 }
476 }
477
478 last_event = current_event;
479 vos_mem_zero( &event, sizeof (struct iw_event));
480
481 /*RSSI*/
482 event.cmd = IWEVQUAL;
483 event.u.qual.qual = descriptor->rssi;
484 event.u.qual.noise = descriptor->sinr;
485
486 /*To keep the rssi icon of the connected AP in the scan window
487 *and the rssi icon of the wireless networks in sync */
488 if (( eConnectionState_Associated ==
489 pAdapter->sessionCtx.station.conn_info.connState ) &&
490 ( VOS_TRUE == vos_mem_compare(descriptor->bssId,
491 pAdapter->sessionCtx.station.conn_info.bssId,
492 WNI_CFG_BSSID_LEN)))
493 {
494 event.u.qual.level = pAdapter->rssi;
495 }
496 else
497 {
498 event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0);
499 }
500
501 event.u.qual.updated = IW_QUAL_ALL_UPDATED;
502
503 current_event = iwe_stream_add_event(scanInfo->info,current_event,
504 end, &event, IW_EV_QUAL_LEN);
505
506 if(last_event == current_event)
507 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530508 hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVQUAL");
Jeff Johnson295189b2012-06-20 16:38:30 -0700509 return -E2BIG;
510 }
511
512
513 /* AGE */
514 event.cmd = IWEVCUSTOM;
515 p = custom;
Sameer Thalappilb0a30232013-09-27 15:37:48 -0700516 p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu",
Jeff Johnson295189b2012-06-20 16:38:30 -0700517 vos_timer_get_system_ticks() - descriptor->nReceivedTime);
518 event.u.data.length = p - custom;
519 current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
520 &event, custom);
521 if(last_event == current_event)
522 { /* no space to add event */
Sushant Kaushik125ae692014-11-25 17:38:48 +0530523 hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)");
Jeff Johnson295189b2012-06-20 16:38:30 -0700524 return -E2BIG;
525 }
526
527 scanInfo->start = current_event;
528
529 return 0;
530}
531
532/**---------------------------------------------------------------------------
533
Siddharth Bhal76972212014-10-15 16:22:51 +0530534 \brief hdd_processSpoofMacAddrRequest() -
535
536 The function is called from scan completion callback and from
537 cfg80211 vendor command
538
539 \param - pHddCtx - Pointer to the HDD Context.
540
541 \return - 0 for success, non zero for failure
542
543 --------------------------------------------------------------------------*/
544
545VOS_STATUS hdd_processSpoofMacAddrRequest(hdd_context_t *pHddCtx)
546{
547
548 ENTER();
549
550 mutex_lock(&pHddCtx->spoofMacAddr.macSpoofingLock);
551
552 if (pHddCtx->spoofMacAddr.isEnabled) {
553 if (VOS_STATUS_SUCCESS != vos_randomize_n_bytes(
554 (void *)(&pHddCtx->spoofMacAddr.randomMacAddr.bytes[3]),
555 VOS_MAC_ADDR_LAST_3_BYTES)) {
556 hddLog(LOGE, FL("Failed to generate random Mac Addr"));
557 pHddCtx->spoofMacAddr.isEnabled = FALSE;
558 mutex_unlock(&pHddCtx->spoofMacAddr.macSpoofingLock);
559 return VOS_STATUS_E_FAILURE;
560 }
561 }
562
563 hddLog(LOG1, FL("New Mac Addr Generated "MAC_ADDRESS_STR),
564 MAC_ADDR_ARRAY(pHddCtx->spoofMacAddr.randomMacAddr.bytes));
565
566 if (pHddCtx->scan_info.mScanPending != TRUE)
567 {
568 pHddCtx->spoofMacAddr.isReqDeferred = FALSE;
569 hddLog(LOG1, FL("Processing Spoof request now"));
570 /* Inform SME about spoof mac addr request*/
571 if ( eHAL_STATUS_SUCCESS != sme_SpoofMacAddrReq(pHddCtx->hHal,
572 &pHddCtx->spoofMacAddr.randomMacAddr))
573 {
574 hddLog(LOGE, FL("Sending Spoof request failed - Disable spoofing"));
575 pHddCtx->spoofMacAddr.isEnabled = FALSE;
576 }
577 } else
578 {
579 hddLog(LOG1, FL("Scan in Progress. Spoofing Deferred"));
580 pHddCtx->spoofMacAddr.isReqDeferred = TRUE;
581 }
582
583 mutex_unlock(&pHddCtx->spoofMacAddr.macSpoofingLock);
584
585 EXIT();
586
587 return VOS_STATUS_SUCCESS;
588}
589
590/**---------------------------------------------------------------------------
591
Jeff Johnson295189b2012-06-20 16:38:30 -0700592 \brief hdd_ScanRequestCallback() -
593
594 The sme module calls this callback function once it finish the scan request
595 and this function notifies the scan complete event to the wpa_supplicant.
596
597 \param - halHandle - Pointer to the Hal Handle.
598 - pContext - Pointer to the data context.
599 - scanId - Scan ID.
600 - status - CSR Status.
601 \return - 0 for success, non zero for failure
602
603 --------------------------------------------------------------------------*/
604
605static eHalStatus hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext,
606 tANI_U32 scanId, eCsrScanStatus status)
607{
608 struct net_device *dev = (struct net_device *) pContext;
609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700610 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 union iwreq_data wrqu;
612 int we_event;
613 char *msg;
614
615 ENTER();
616
617 hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700618 " returned status = %d", __func__, halHandle, pContext,
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 (int) scanId, (int) status);
620
621 /* if there is a scan request pending when the wlan driver is unloaded
622 we may be invoked as SME flushes its pending queue. If that is the
623 case, the underlying net_device may have already been destroyed, so
624 do some quick sanity before proceeding */
625 if (pAdapter->dev != dev)
626 {
627 hddLog(LOGW, "%s: device mismatch %p vs %p",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700628 __func__, pAdapter->dev, dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 return eHAL_STATUS_SUCCESS;
630 }
631
632 /* Check the scanId */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700633 if (pHddCtx->scan_info.scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -0700634 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700635 hddLog(LOGW, "%s called with mismatched scanId pHddCtx->scan_info.scanId = %d "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700636 "scanId = %d ", __func__, (int) pHddCtx->scan_info.scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -0700637 (int) scanId);
638 }
639
640 /* Scan is no longer pending */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700641 pHddCtx->scan_info.mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700642
643 // notify any applications that may be interested
644 memset(&wrqu, '\0', sizeof(wrqu));
645 we_event = SIOCGIWSCAN;
646 msg = NULL;
647 wireless_send_event(dev, we_event, &wrqu, msg);
648
649 EXIT();
650
651 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
652
653 return eHAL_STATUS_SUCCESS;
654}
655
656/**---------------------------------------------------------------------------
657
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530658 \brief __iw_set_scan() -
Jeff Johnson295189b2012-06-20 16:38:30 -0700659
660 This function process the scan request from the wpa_supplicant
661 and set the scan request to the SME
662
663 \param - dev - Pointer to the net device.
664 - info - Pointer to the iw_request_info.
665 - wrqu - Pointer to the iwreq_data.
666 - extra - Pointer to the data.
667 \return - 0 for success, non zero for failure
668
669 --------------------------------------------------------------------------*/
670
671
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530672int __iw_set_scan(struct net_device *dev, struct iw_request_info *info,
Jeff Johnson295189b2012-06-20 16:38:30 -0700673 union iwreq_data *wrqu, char *extra)
674{
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530675 hdd_adapter_t *pAdapter;
676 hdd_context_t *pHddCtx;
677 hdd_wext_state_t *pwextBuf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700678 tCsrScanRequest scanRequest;
679 v_U32_t scanId = 0;
680 eHalStatus status = eHAL_STATUS_SUCCESS;
681 struct iw_scan_req *scanReq = (struct iw_scan_req *)extra;
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530682 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700683
684 ENTER();
685
686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
687
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530688 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
689 if (NULL == pAdapter)
690 {
691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
692 "%s: Adapter is NULL",__func__);
693 return -EINVAL;
694 }
695
696 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
697 ret = wlan_hdd_validate_context(pHddCtx);
698 if (0 != ret)
699 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530700 return ret;
701 }
702 pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
703 if (NULL == pwextBuf)
704 {
705 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
706 "%s: pwextBuf is NULL",__func__);
707 return -EINVAL;
708 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700709#ifdef WLAN_BTAMP_FEATURE
710 //Scan not supported when AMP traffic is on.
711 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
712 {
713 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
714 return eHAL_STATUS_SUCCESS;
715 }
716#endif
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700717 if(pHddCtx->scan_info.mScanPending == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700718 {
719 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
720 return eHAL_STATUS_SUCCESS;
721 }
722
Jeff Johnson295189b2012-06-20 16:38:30 -0700723 vos_mem_zero( &scanRequest, sizeof(scanRequest));
724
725 if (NULL != wrqu->data.pointer)
726 {
727 /* set scanType, active or passive */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700728 if ((IW_SCAN_TYPE_ACTIVE == scanReq->scan_type) || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -0700729 {
730 scanRequest.scanType = eSIR_ACTIVE_SCAN;
731 }
732 else
733 {
734 scanRequest.scanType = eSIR_PASSIVE_SCAN;
735 }
736
737 /* set bssid using sockaddr from iw_scan_req */
738 vos_mem_copy(scanRequest.bssid,
739 &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) );
740
741 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
742
743 if(scanReq->essid_len) {
744 scanRequest.SSIDs.numOfSSIDs = 1;
745 scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
746 if(scanRequest.SSIDs.SSIDList) {
747 scanRequest.SSIDs.SSIDList->SSID.length = scanReq->essid_len;
748 vos_mem_copy(scanRequest.SSIDs.SSIDList-> SSID.ssId,scanReq->essid,scanReq->essid_len);
749 }
750 else
751 {
752 scanRequest.SSIDs.numOfSSIDs = 0;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 VOS_ASSERT(0);
755 }
756 }
757 }
758
759 /* set min and max channel time */
760 scanRequest.minChnTime = scanReq->min_channel_time;
761 scanRequest.maxChnTime = scanReq->max_channel_time;
762
763 }
764 else
765 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700766 if(pHddCtx->scan_info.scan_mode == eSIR_ACTIVE_SCAN) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700767 /* set the scan type to active */
768 scanRequest.scanType = eSIR_ACTIVE_SCAN;
769 } else {
770 scanRequest.scanType = eSIR_PASSIVE_SCAN;
771 }
772
773 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
774
775 /* set min and max channel time to zero */
776 scanRequest.minChnTime = 0;
777 scanRequest.maxChnTime = 0;
778 }
779
780 /* set BSSType to default type */
781 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
782
783 /*Scan all the channels */
784 scanRequest.ChannelInfo.numOfChannels = 0;
785
786 scanRequest.ChannelInfo.ChannelList = NULL;
787
788 /* set requestType to full scan */
789 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
790
791 /* if previous genIE is not NULL, update ScanIE */
792 if (0 != pwextBuf->genIE.length)
793 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700794 memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
795 memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 pwextBuf->genIE.length );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700797 pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
Agarwal Ashish4f616132013-12-30 23:32:50 +0530798 /* Maximum length of each IE is SIR_MAC_MAX_IE_LENGTH */
799 if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length)
800 {
801 memcpy( pwextBuf->roamProfile.addIEScan,
802 pHddCtx->scan_info.scanAddIE.addIEdata,
803 pHddCtx->scan_info.scanAddIE.length);
804 pwextBuf->roamProfile.nAddIEScanLength =
805 pHddCtx->scan_info.scanAddIE.length;
806 }
807 else
808 {
809 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
810 "Invalid ScanIE, Length is %d", pwextBuf->genIE.length);
811 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700812 /* clear previous genIE after use it */
813 memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
814 }
815
816 /* push addIEScan in scanRequset if exist */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700817 if (pHddCtx->scan_info.scanAddIE.addIEdata &&
818 pHddCtx->scan_info.scanAddIE.length)
Jeff Johnson295189b2012-06-20 16:38:30 -0700819 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700820 scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
821 scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
Jeff Johnson295189b2012-06-20 16:38:30 -0700822 }
823
824 status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
825 if (!HAL_STATUS_SUCCESS(status))
826 {
827 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest fail %d!!!",__func__, status);
828 goto error;
829 }
830
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700831 pHddCtx->scan_info.mScanPending = TRUE;
Kaushik, Sushantdedd4ea2014-11-06 11:55:14 +0530832 pHddCtx->scan_info.sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700833
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700834 pHddCtx->scan_info.scanId = scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700835
836error:
837 if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len))
838 vos_mem_free(scanRequest.SSIDs.SSIDList);
839
840 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700841 return status;
842}
843
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530844int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
845 union iwreq_data *wrqu, char *extra)
846{
847 int ret;
848
849 vos_ssr_protect(__func__);
850 ret = __iw_set_scan(dev, info, wrqu, extra);
851 vos_ssr_unprotect(__func__);
852
853 return ret;
854}
855
Jeff Johnson295189b2012-06-20 16:38:30 -0700856/**---------------------------------------------------------------------------
857
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530858 \brief __iw_get_scan() -
Jeff Johnson295189b2012-06-20 16:38:30 -0700859
860 This function returns the scan results to the wpa_supplicant
861
862 \param - dev - Pointer to the net device.
863 - info - Pointer to the iw_request_info.
864 - wrqu - Pointer to the iwreq_data.
865 - extra - Pointer to the data.
866 \return - 0 for success, non zero for failure
867
868 --------------------------------------------------------------------------*/
869
870
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530871int __iw_get_scan(struct net_device *dev,
872 struct iw_request_info *info,
873 union iwreq_data *wrqu, char *extra)
Jeff Johnson295189b2012-06-20 16:38:30 -0700874{
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530875 hdd_adapter_t *pAdapter;
876 hdd_context_t *pHddCtx;
877 tHalHandle hHal;
Jeff Johnson295189b2012-06-20 16:38:30 -0700878 tCsrScanResultInfo *pScanResult;
879 eHalStatus status = eHAL_STATUS_SUCCESS;
880 hdd_scan_info_t scanInfo;
881 tScanResultHandle pResult;
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530882 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700883
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530884 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700885 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!",
886 __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA);
Jeff Johnson295189b2012-06-20 16:38:30 -0700887
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530888 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
889 if (NULL == pAdapter)
890 {
891 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
892 "%s: Adapter is NULL",__func__);
893 return -EINVAL;
894 }
895
896 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
897 ret = wlan_hdd_validate_context(pHddCtx);
898 if (0 != ret)
899 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530900 return ret;
901 }
902 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
903 if (NULL == hHal)
904 {
905 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
906 "%s: Hal Context is NULL",__func__);
907 return -EINVAL;
908 }
909
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700910 if (TRUE == pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -0700911 {
912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
913 return -EAGAIN;
914 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700915 scanInfo.dev = dev;
916 scanInfo.start = extra;
917 scanInfo.info = info;
918
919 if (0 == wrqu->data.length)
920 {
921 scanInfo.end = extra + IW_SCAN_MAX_DATA;
922 }
923 else
924 {
925 scanInfo.end = extra + wrqu->data.length;
926 }
927
928 status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult);
929
930 if (NULL == pResult)
931 {
932 // no scan results
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530933 hddLog(LOG1,"__iw_get_scan: NULL Scan Result ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700934 return 0;
935 }
936
937 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
938
939 while (pScanResult)
940 {
941 status = hdd_IndicateScanResult(&scanInfo, pScanResult);
942 if (0 != status)
943 {
944 break;
945 }
946 i++;
947 pScanResult = sme_ScanResultGetNext(hHal, pResult);
948 }
949
950 sme_ScanResultPurge(hHal, pResult);
951
Jeff Johnson295189b2012-06-20 16:38:30 -0700952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530953 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 return status;
955}
956
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530957int iw_get_scan(struct net_device *dev,
958 struct iw_request_info *info,
959 union iwreq_data *wrqu, char *extra)
960{
961 int ret;
962
963 vos_ssr_protect(__func__);
964 ret = __iw_get_scan(dev, info, wrqu, extra);
965 vos_ssr_unprotect(__func__);
966
967 return ret;
968}
969
Jeff Johnson295189b2012-06-20 16:38:30 -0700970#if 0
971static eHalStatus hdd_CscanRequestCallback(tHalHandle halHandle, void *pContext,
972 tANI_U32 scanId, eCsrScanStatus status)
973{
974 struct net_device *dev = (struct net_device *) pContext;
975 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
976 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
977 union iwreq_data wrqu;
978 int we_event;
979 char *msg;
980 VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
981 ENTER();
982
983 hddLog(LOG1,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700984 " returned status = %d", __func__, halHandle, pContext,
Jeff Johnson295189b2012-06-20 16:38:30 -0700985 (int) scanId, (int) status);
986
987 /* Check the scanId */
988 if (pwextBuf->scanId != scanId)
989 {
990 hddLog(LOGW, "%s called with mismatched scanId pWextState->scanId = %d "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700991 "scanId = %d ", __func__, (int) pwextBuf->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -0700992 (int) scanId);
993 }
994
995 /* Scan is no longer pending */
996 pwextBuf->mScanPending = VOS_FALSE;
997
998 // notify any applications that may be interested
999 memset(&wrqu, '\0', sizeof(wrqu));
1000 we_event = SIOCGIWSCAN;
1001 msg = NULL;
1002 wireless_send_event(dev, we_event, &wrqu, msg);
1003
1004 vos_status = vos_event_set(&pwextBuf->vosevent);
1005
1006 if (!VOS_IS_STATUS_SUCCESS(vos_status))
1007 {
1008 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos_event_set failed!!"));
1009 return VOS_STATUS_E_FAILURE;
1010 }
1011
1012 EXIT();
1013 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
1014
1015 return eHAL_STATUS_SUCCESS;
1016}
1017#endif
1018
1019int iw_set_cscan(struct net_device *dev, struct iw_request_info *info,
1020 union iwreq_data *wrqu, char *extra)
1021{
1022 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001023 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001024 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1025 tCsrScanRequest scanRequest;
1026 v_U32_t scanId = 0;
1027 eHalStatus status = eHAL_STATUS_SUCCESS;
1028 v_U8_t channelIdx;
1029
1030 ENTER();
1031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
1032
1033#ifdef WLAN_BTAMP_FEATURE
1034 //Scan not supported when AMP traffic is on.
1035 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
1036 {
1037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
1038 return eHAL_STATUS_SUCCESS;
1039 }
1040#endif
1041
1042 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1043 {
1044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1045 return eHAL_STATUS_SUCCESS;
1046 }
1047
1048 vos_mem_zero( &scanRequest, sizeof(scanRequest));
1049 if (NULL != wrqu->data.pointer)
1050 {
1051 char *str_ptr = NULL;
1052 tCsrSSIDInfo *SsidInfo = NULL;
1053 int num_ssid = 0;
1054 int i, j, ssid_start;
1055 hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP;
1056
Rajeev Kumarbe97df02013-10-24 18:30:39 -07001057 str_ptr = extra;
Jeff Johnson295189b2012-06-20 16:38:30 -07001058
1059 i = WEXT_CSCAN_HEADER_SIZE;
1060
1061 if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] )
1062 {
1063 scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i];
1064 ++i;
1065 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001066 pHddCtx->scan_info.scan_pending_option = scanPendingOption;
Jeff Johnson295189b2012-06-20 16:38:30 -07001067
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001068 if(pHddCtx->scan_info.mScanPending == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07001069 {
1070 hddLog(LOG1,"%s: mScanPending is TRUE",__func__);
1071 /* If any scan is pending, just giveup this scan request */
1072 if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption)
1073 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001074 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 return eHAL_STATUS_SUCCESS;
1076 }
1077 /* If any scan pending, wait till finish current scan,
1078 and try this scan request when previous scan finish */
1079 else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption)
1080 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001081 pHddCtx->scan_info.waitScanResult = TRUE;
1082 vos_event_reset(&pHddCtx->scan_info.scan_finished_event);
1083 if(vos_wait_single_event(&pHddCtx->scan_info.scan_finished_event,
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 WEXT_CSCAN_SCAN_DONE_WAIT_TIME))
1085 {
1086 hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__);
1087 return eHAL_STATUS_SUCCESS;
1088 }
1089 }
1090 /* Piggyback previous scan result */
1091 else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption)
1092 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001093 pHddCtx->scan_info.waitScanResult = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 return eHAL_STATUS_SUCCESS;
1095 }
1096 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001097 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001098
1099 /* Check for scan IE */
1100 while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] )
1101 {
1102 /* ssid_len */
1103 if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION)
1104 {
1105 /* total number of ssid's */
1106 num_ssid++;
1107 /* increment length filed */
1108 i += str_ptr[i] + 1;
1109 }
1110 /* i should be saved and it will be pointing to 'C' */
1111 }
1112
1113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid);
1114 if( num_ssid )
1115 {
1116 /* To be fixed in SME and PE: override the number of ssid with 1,
1117 * as SME and PE does not handle multiple SSID in scan request
1118 * */
1119 scanRequest.SSIDs.numOfSSIDs = num_ssid;
1120 /* Allocate num_ssid tCsrSSIDInfo structure */
1121 SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo));
1122 if(NULL == scanRequest.SSIDs.SSIDList) {
1123 hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer");
1124 return -ENOMEM;
1125 }
1126
1127 /* copy all the ssid's and their length */
1128 ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;/* skipping 'S' */
1129 for(j = 0; j < num_ssid; j++) {
1130 if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){
1131 scanRequest.SSIDs.numOfSSIDs -= 1;
1132 } else{
1133 /* get the ssid length */
1134 SsidInfo->SSID.length = str_ptr[ssid_start++];
1135 vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length);
Arif Hussain6d2a3322013-11-17 19:50:10 -08001136 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s", j, SsidInfo->SSID.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001137 }
1138 /* skipping length */
1139 ssid_start += str_ptr[ssid_start - 1] + 1;
1140 /* Store next ssid info */
1141 SsidInfo++;
1142 }
1143 }
1144
1145 /* Check for Channel IE */
1146 if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i])
1147 {
1148 if( str_ptr[++i] == 0 )
1149 {
1150 scanRequest.ChannelInfo.numOfChannels = 0;
1151 scanRequest.ChannelInfo.ChannelList = NULL;
1152 i++;
1153 }
1154 else {
1155
1156 /* increment the counter */
1157 scanRequest.ChannelInfo.numOfChannels = str_ptr[i++];
1158 /* store temp channel list */
1159 /* SME expects 1 byte channel content */
1160 scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t));
1161 if(NULL == scanRequest.ChannelInfo.ChannelList)
1162 {
c_hpothu7f63e882013-10-02 19:13:35 +05301163 hddLog(LOGE, "memory alloc failed for channel list creation");
Jeff Johnson295189b2012-06-20 16:38:30 -07001164 status = -ENOMEM;
1165 goto exit_point;
1166 }
1167
1168 for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++)
1169 {
1170 /* SCAN request from upper layer has 2 bytes channel */
1171 scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i];
1172 i += sizeof(v_U16_t);
1173 }
1174 }
1175 }
1176
1177 /* Set default */
1178 scanRequest.scanType = eSIR_ACTIVE_SCAN;
1179 scanRequest.minChnTime = 0;
1180 scanRequest.maxChnTime = 0;
1181
1182 /* Now i is pointing to passive dwell dwell time */
1183 /* 'P',min dwell time, max dwell time */
1184 /* next two offsets contain min and max channel time */
1185 if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) )
1186 {
1187 /* No SSID specified, num_ssid == 0, then start paasive scan */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001188 if (!num_ssid || (eSIR_PASSIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001189 {
1190 scanRequest.scanType = eSIR_PASSIVE_SCAN;
1191 scanRequest.minChnTime = (v_U8_t)str_ptr[++i];//scanReq->min_channel_time;
1192 scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];//scanReq->max_channel_time;
1193 i++;
1194 }
1195 else
1196 {
1197 i += 3;
1198 }
1199 }
1200
1201 /* H indicates active channel time */
1202 if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) )
1203 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001204 if (num_ssid || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001205 {
1206 scanRequest.scanType = eSIR_ACTIVE_SCAN;
1207 scanRequest.minChnTime = str_ptr[++i];//scanReq->min_channel_time;
1208 scanRequest.maxChnTime = str_ptr[++i];//scanReq->max_channel_time;
1209 i++;
1210 }
1211 else
1212 {
1213 i +=3;
1214 }
1215 }
1216 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
1217 /* set requestType to full scan */
1218 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001219 pHddCtx->scan_info.mScanPending = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001220
1221 /* if previous genIE is not NULL, update ScanIE */
1222 if(0 != pwextBuf->genIE.length)
1223 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001224 memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
1225 memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
Jeff Johnson295189b2012-06-20 16:38:30 -07001226 pwextBuf->genIE.length );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001227 pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
Agarwal Ashish4f616132013-12-30 23:32:50 +05301228 if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length)
1229 {
1230 memcpy( pwextBuf->roamProfile.addIEScan,
1231 pHddCtx->scan_info.scanAddIE.addIEdata,
1232 pHddCtx->scan_info.scanAddIE.length);
1233 pwextBuf->roamProfile.nAddIEScanLength =
1234 pHddCtx->scan_info.scanAddIE.length;
1235 }
1236 else
1237 {
1238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1239 "Invalid ScanIE, Length is %d",
1240 pwextBuf->genIE.length);
1241 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001242
1243 /* clear previous genIE after use it */
1244 memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
1245 }
1246
1247 /* push addIEScan in scanRequset if exist */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001248 if (pHddCtx->scan_info.scanAddIE.addIEdata &&
1249 pHddCtx->scan_info.scanAddIE.length)
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001251 scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
1252 scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 }
1254
1255 status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal,
1256 pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
1257 if( !HAL_STATUS_SUCCESS(status) )
1258 {
1259 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 -07001260 pHddCtx->scan_info.mScanPending = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001261 status = -EINVAL;
1262 goto exit_point;
1263 }
1264
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001265 pHddCtx->scan_info.scanId = scanId;
Kaushik, Sushantdedd4ea2014-11-06 11:55:14 +05301266 pHddCtx->scan_info.sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -07001267
1268 } //end of data->pointer
1269 else {
1270 status = -1;
1271 }
1272
1273exit_point:
1274
1275 /* free ssidlist */
1276 if (scanRequest.SSIDs.SSIDList)
1277 {
1278 vos_mem_free(scanRequest.SSIDs.SSIDList);
1279 }
1280 /* free the channel list */
1281 if(scanRequest.ChannelInfo.ChannelList)
1282 {
1283 vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList);
1284 }
1285
1286 EXIT();
1287 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
1288 return status;
1289}
1290
1291/* Abort any MAC scan if in progress */
c_hpothua3d45d52015-01-05 14:11:17 +05301292tSirAbortScanStatus hdd_abort_mac_scan(hdd_context_t* pHddCtx,
1293 tANI_U8 sessionId,
1294 eCsrAbortReason reason)
Jeff Johnson295189b2012-06-20 16:38:30 -07001295{
c_hpothua3d45d52015-01-05 14:11:17 +05301296 return sme_AbortMacScan(pHddCtx->hHal, sessionId, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07001297}
1298