blob: 39e2f394e5641642fee064ab7f83490331fab1a7 [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
Padma, Santhosh Kumardb2d75b2015-11-17 12:18:10 +0530545void __hdd_processSpoofMacAddrRequest(struct work_struct *work)
Siddharth Bhal76972212014-10-15 16:22:51 +0530546{
Padma, Santhosh Kumardb2d75b2015-11-17 12:18:10 +0530547 hdd_context_t *pHddCtx =
548 container_of(to_delayed_work(work), hdd_context_t, spoof_mac_addr_work);
Siddharth Bhal76972212014-10-15 16:22:51 +0530549
550 ENTER();
551
Padma, Santhosh Kumardb2d75b2015-11-17 12:18:10 +0530552 if (wlan_hdd_validate_context(pHddCtx))
553 return;
554
Siddharth Bhal76972212014-10-15 16:22:51 +0530555 mutex_lock(&pHddCtx->spoofMacAddr.macSpoofingLock);
556
557 if (pHddCtx->spoofMacAddr.isEnabled) {
558 if (VOS_STATUS_SUCCESS != vos_randomize_n_bytes(
559 (void *)(&pHddCtx->spoofMacAddr.randomMacAddr.bytes[3]),
560 VOS_MAC_ADDR_LAST_3_BYTES)) {
Siddharth Bhal76972212014-10-15 16:22:51 +0530561 pHddCtx->spoofMacAddr.isEnabled = FALSE;
562 mutex_unlock(&pHddCtx->spoofMacAddr.macSpoofingLock);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +0530563 hddLog(LOGE, FL("Failed to generate random Mac Addr"));
Padma, Santhosh Kumardb2d75b2015-11-17 12:18:10 +0530564 return;
Siddharth Bhal76972212014-10-15 16:22:51 +0530565 }
566 }
567
568 hddLog(LOG1, FL("New Mac Addr Generated "MAC_ADDRESS_STR),
569 MAC_ADDR_ARRAY(pHddCtx->spoofMacAddr.randomMacAddr.bytes));
570
571 if (pHddCtx->scan_info.mScanPending != TRUE)
572 {
573 pHddCtx->spoofMacAddr.isReqDeferred = FALSE;
574 hddLog(LOG1, FL("Processing Spoof request now"));
575 /* Inform SME about spoof mac addr request*/
576 if ( eHAL_STATUS_SUCCESS != sme_SpoofMacAddrReq(pHddCtx->hHal,
577 &pHddCtx->spoofMacAddr.randomMacAddr))
578 {
579 hddLog(LOGE, FL("Sending Spoof request failed - Disable spoofing"));
580 pHddCtx->spoofMacAddr.isEnabled = FALSE;
581 }
582 } else
583 {
584 hddLog(LOG1, FL("Scan in Progress. Spoofing Deferred"));
585 pHddCtx->spoofMacAddr.isReqDeferred = TRUE;
586 }
587
588 mutex_unlock(&pHddCtx->spoofMacAddr.macSpoofingLock);
589
590 EXIT();
591
Padma, Santhosh Kumardb2d75b2015-11-17 12:18:10 +0530592 return;
593}
594
595void hdd_processSpoofMacAddrRequest(struct work_struct *work)
596{
597 vos_ssr_protect(__func__);
598 __hdd_processSpoofMacAddrRequest(work);
599 vos_ssr_unprotect(__func__);
Siddharth Bhal76972212014-10-15 16:22:51 +0530600}
601
602/**---------------------------------------------------------------------------
603
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 \brief hdd_ScanRequestCallback() -
605
606 The sme module calls this callback function once it finish the scan request
607 and this function notifies the scan complete event to the wpa_supplicant.
608
609 \param - halHandle - Pointer to the Hal Handle.
610 - pContext - Pointer to the data context.
611 - scanId - Scan ID.
612 - status - CSR Status.
613 \return - 0 for success, non zero for failure
614
615 --------------------------------------------------------------------------*/
616
617static eHalStatus hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext,
618 tANI_U32 scanId, eCsrScanStatus status)
619{
620 struct net_device *dev = (struct net_device *) pContext;
621 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700622 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 union iwreq_data wrqu;
624 int we_event;
625 char *msg;
626
627 ENTER();
628
629 hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700630 " returned status = %d", __func__, halHandle, pContext,
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 (int) scanId, (int) status);
632
633 /* if there is a scan request pending when the wlan driver is unloaded
634 we may be invoked as SME flushes its pending queue. If that is the
635 case, the underlying net_device may have already been destroyed, so
636 do some quick sanity before proceeding */
637 if (pAdapter->dev != dev)
638 {
639 hddLog(LOGW, "%s: device mismatch %p vs %p",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700640 __func__, pAdapter->dev, dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700641 return eHAL_STATUS_SUCCESS;
642 }
643
644 /* Check the scanId */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700645 if (pHddCtx->scan_info.scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -0700646 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700647 hddLog(LOGW, "%s called with mismatched scanId pHddCtx->scan_info.scanId = %d "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700648 "scanId = %d ", __func__, (int) pHddCtx->scan_info.scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -0700649 (int) scanId);
650 }
651
652 /* Scan is no longer pending */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700653 pHddCtx->scan_info.mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700654
655 // notify any applications that may be interested
656 memset(&wrqu, '\0', sizeof(wrqu));
657 we_event = SIOCGIWSCAN;
658 msg = NULL;
659 wireless_send_event(dev, we_event, &wrqu, msg);
660
661 EXIT();
662
663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
664
665 return eHAL_STATUS_SUCCESS;
666}
667
668/**---------------------------------------------------------------------------
669
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530670 \brief __iw_set_scan() -
Jeff Johnson295189b2012-06-20 16:38:30 -0700671
672 This function process the scan request from the wpa_supplicant
673 and set the scan request to the SME
674
675 \param - dev - Pointer to the net device.
676 - info - Pointer to the iw_request_info.
677 - wrqu - Pointer to the iwreq_data.
678 - extra - Pointer to the data.
679 \return - 0 for success, non zero for failure
680
681 --------------------------------------------------------------------------*/
682
683
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530684int __iw_set_scan(struct net_device *dev, struct iw_request_info *info,
Jeff Johnson295189b2012-06-20 16:38:30 -0700685 union iwreq_data *wrqu, char *extra)
686{
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530687 hdd_adapter_t *pAdapter;
688 hdd_context_t *pHddCtx;
689 hdd_wext_state_t *pwextBuf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700690 tCsrScanRequest scanRequest;
691 v_U32_t scanId = 0;
692 eHalStatus status = eHAL_STATUS_SUCCESS;
693 struct iw_scan_req *scanReq = (struct iw_scan_req *)extra;
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530694 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700695
696 ENTER();
697
698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
699
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530700 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
701 if (NULL == pAdapter)
702 {
703 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
704 "%s: Adapter is NULL",__func__);
705 return -EINVAL;
706 }
707
708 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
709 ret = wlan_hdd_validate_context(pHddCtx);
710 if (0 != ret)
711 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530712 return ret;
713 }
714 pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
715 if (NULL == pwextBuf)
716 {
717 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
718 "%s: pwextBuf is NULL",__func__);
719 return -EINVAL;
720 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700721#ifdef WLAN_BTAMP_FEATURE
722 //Scan not supported when AMP traffic is on.
723 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
724 {
725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
726 return eHAL_STATUS_SUCCESS;
727 }
728#endif
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700729 if(pHddCtx->scan_info.mScanPending == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700730 {
731 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
732 return eHAL_STATUS_SUCCESS;
733 }
734
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 vos_mem_zero( &scanRequest, sizeof(scanRequest));
736
737 if (NULL != wrqu->data.pointer)
738 {
739 /* set scanType, active or passive */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700740 if ((IW_SCAN_TYPE_ACTIVE == scanReq->scan_type) || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 {
742 scanRequest.scanType = eSIR_ACTIVE_SCAN;
743 }
744 else
745 {
746 scanRequest.scanType = eSIR_PASSIVE_SCAN;
747 }
748
749 /* set bssid using sockaddr from iw_scan_req */
750 vos_mem_copy(scanRequest.bssid,
751 &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) );
752
753 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
754
Arun Khandavallif138bd92015-11-09 10:28:18 +0530755 if(scanReq->essid_len &&
756 (scanReq->essid_len <= SIR_MAC_MAX_SSID_LENGTH)) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700757 scanRequest.SSIDs.numOfSSIDs = 1;
758 scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
759 if(scanRequest.SSIDs.SSIDList) {
760 scanRequest.SSIDs.SSIDList->SSID.length = scanReq->essid_len;
761 vos_mem_copy(scanRequest.SSIDs.SSIDList-> SSID.ssId,scanReq->essid,scanReq->essid_len);
762 }
763 else
764 {
765 scanRequest.SSIDs.numOfSSIDs = 0;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700767 VOS_ASSERT(0);
768 }
769 }
Arun Khandavallif138bd92015-11-09 10:28:18 +0530770 else
771 {
772 hddLog(LOGE, FL("Invalid essid length : %d"), scanReq->essid_len);
773 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700774 }
775
776 /* set min and max channel time */
777 scanRequest.minChnTime = scanReq->min_channel_time;
778 scanRequest.maxChnTime = scanReq->max_channel_time;
779
780 }
781 else
782 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700783 if(pHddCtx->scan_info.scan_mode == eSIR_ACTIVE_SCAN) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700784 /* set the scan type to active */
785 scanRequest.scanType = eSIR_ACTIVE_SCAN;
786 } else {
787 scanRequest.scanType = eSIR_PASSIVE_SCAN;
788 }
789
790 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
791
792 /* set min and max channel time to zero */
793 scanRequest.minChnTime = 0;
794 scanRequest.maxChnTime = 0;
795 }
796
797 /* set BSSType to default type */
798 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
799
800 /*Scan all the channels */
801 scanRequest.ChannelInfo.numOfChannels = 0;
802
803 scanRequest.ChannelInfo.ChannelList = NULL;
804
805 /* set requestType to full scan */
806 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
807
808 /* if previous genIE is not NULL, update ScanIE */
809 if (0 != pwextBuf->genIE.length)
810 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700811 memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
812 memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 pwextBuf->genIE.length );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700814 pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
Agarwal Ashish4f616132013-12-30 23:32:50 +0530815 /* Maximum length of each IE is SIR_MAC_MAX_IE_LENGTH */
816 if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length)
817 {
818 memcpy( pwextBuf->roamProfile.addIEScan,
819 pHddCtx->scan_info.scanAddIE.addIEdata,
820 pHddCtx->scan_info.scanAddIE.length);
821 pwextBuf->roamProfile.nAddIEScanLength =
822 pHddCtx->scan_info.scanAddIE.length;
823 }
824 else
825 {
826 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
827 "Invalid ScanIE, Length is %d", pwextBuf->genIE.length);
828 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 /* clear previous genIE after use it */
830 memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
831 }
832
833 /* push addIEScan in scanRequset if exist */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700834 if (pHddCtx->scan_info.scanAddIE.addIEdata &&
835 pHddCtx->scan_info.scanAddIE.length)
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700837 scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
838 scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
Jeff Johnson295189b2012-06-20 16:38:30 -0700839 }
840
841 status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
842 if (!HAL_STATUS_SUCCESS(status))
843 {
844 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest fail %d!!!",__func__, status);
845 goto error;
846 }
847
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700848 pHddCtx->scan_info.mScanPending = TRUE;
Kaushik, Sushantdedd4ea2014-11-06 11:55:14 +0530849 pHddCtx->scan_info.sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700850
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700851 pHddCtx->scan_info.scanId = scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700852
853error:
854 if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len))
855 vos_mem_free(scanRequest.SSIDs.SSIDList);
856
857 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 return status;
859}
860
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530861int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
862 union iwreq_data *wrqu, char *extra)
863{
864 int ret;
865
866 vos_ssr_protect(__func__);
867 ret = __iw_set_scan(dev, info, wrqu, extra);
868 vos_ssr_unprotect(__func__);
869
870 return ret;
871}
872
Jeff Johnson295189b2012-06-20 16:38:30 -0700873/**---------------------------------------------------------------------------
874
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530875 \brief __iw_get_scan() -
Jeff Johnson295189b2012-06-20 16:38:30 -0700876
877 This function returns the scan results to the wpa_supplicant
878
879 \param - dev - Pointer to the net device.
880 - info - Pointer to the iw_request_info.
881 - wrqu - Pointer to the iwreq_data.
882 - extra - Pointer to the data.
883 \return - 0 for success, non zero for failure
884
885 --------------------------------------------------------------------------*/
886
887
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530888int __iw_get_scan(struct net_device *dev,
889 struct iw_request_info *info,
890 union iwreq_data *wrqu, char *extra)
Jeff Johnson295189b2012-06-20 16:38:30 -0700891{
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530892 hdd_adapter_t *pAdapter;
893 hdd_context_t *pHddCtx;
894 tHalHandle hHal;
Jeff Johnson295189b2012-06-20 16:38:30 -0700895 tCsrScanResultInfo *pScanResult;
896 eHalStatus status = eHAL_STATUS_SUCCESS;
897 hdd_scan_info_t scanInfo;
898 tScanResultHandle pResult;
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530899 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700900
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530901 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700902 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!",
903 __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA);
Jeff Johnson295189b2012-06-20 16:38:30 -0700904
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530905 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
906 if (NULL == pAdapter)
907 {
908 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
909 "%s: Adapter is NULL",__func__);
910 return -EINVAL;
911 }
912
913 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
914 ret = wlan_hdd_validate_context(pHddCtx);
915 if (0 != ret)
916 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530917 return ret;
918 }
919 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
920 if (NULL == hHal)
921 {
922 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
923 "%s: Hal Context is NULL",__func__);
924 return -EINVAL;
925 }
926
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700927 if (TRUE == pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -0700928 {
929 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
930 return -EAGAIN;
931 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700932 scanInfo.dev = dev;
933 scanInfo.start = extra;
934 scanInfo.info = info;
935
936 if (0 == wrqu->data.length)
937 {
938 scanInfo.end = extra + IW_SCAN_MAX_DATA;
939 }
940 else
941 {
942 scanInfo.end = extra + wrqu->data.length;
943 }
944
945 status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult);
946
947 if (NULL == pResult)
948 {
949 // no scan results
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530950 hddLog(LOG1,"__iw_get_scan: NULL Scan Result ");
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 return 0;
952 }
953
954 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
955
956 while (pScanResult)
957 {
958 status = hdd_IndicateScanResult(&scanInfo, pScanResult);
959 if (0 != status)
960 {
961 break;
962 }
963 i++;
964 pScanResult = sme_ScanResultGetNext(hHal, pResult);
965 }
966
967 sme_ScanResultPurge(hHal, pResult);
968
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 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 +0530970 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700971 return status;
972}
973
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530974int iw_get_scan(struct net_device *dev,
975 struct iw_request_info *info,
976 union iwreq_data *wrqu, char *extra)
977{
978 int ret;
979
980 vos_ssr_protect(__func__);
981 ret = __iw_get_scan(dev, info, wrqu, extra);
982 vos_ssr_unprotect(__func__);
983
984 return ret;
985}
986
Jeff Johnson295189b2012-06-20 16:38:30 -0700987#if 0
988static eHalStatus hdd_CscanRequestCallback(tHalHandle halHandle, void *pContext,
989 tANI_U32 scanId, eCsrScanStatus status)
990{
991 struct net_device *dev = (struct net_device *) pContext;
992 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
993 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
994 union iwreq_data wrqu;
995 int we_event;
996 char *msg;
997 VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
998 ENTER();
999
1000 hddLog(LOG1,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001001 " returned status = %d", __func__, halHandle, pContext,
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 (int) scanId, (int) status);
1003
1004 /* Check the scanId */
1005 if (pwextBuf->scanId != scanId)
1006 {
1007 hddLog(LOGW, "%s called with mismatched scanId pWextState->scanId = %d "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001008 "scanId = %d ", __func__, (int) pwextBuf->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 (int) scanId);
1010 }
1011
1012 /* Scan is no longer pending */
1013 pwextBuf->mScanPending = VOS_FALSE;
1014
1015 // notify any applications that may be interested
1016 memset(&wrqu, '\0', sizeof(wrqu));
1017 we_event = SIOCGIWSCAN;
1018 msg = NULL;
1019 wireless_send_event(dev, we_event, &wrqu, msg);
1020
1021 vos_status = vos_event_set(&pwextBuf->vosevent);
1022
1023 if (!VOS_IS_STATUS_SUCCESS(vos_status))
1024 {
1025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos_event_set failed!!"));
1026 return VOS_STATUS_E_FAILURE;
1027 }
1028
1029 EXIT();
1030 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
1031
1032 return eHAL_STATUS_SUCCESS;
1033}
1034#endif
1035
1036int iw_set_cscan(struct net_device *dev, struct iw_request_info *info,
1037 union iwreq_data *wrqu, char *extra)
1038{
1039 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001040 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001041 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1042 tCsrScanRequest scanRequest;
1043 v_U32_t scanId = 0;
1044 eHalStatus status = eHAL_STATUS_SUCCESS;
1045 v_U8_t channelIdx;
1046
1047 ENTER();
1048 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
1049
1050#ifdef WLAN_BTAMP_FEATURE
1051 //Scan not supported when AMP traffic is on.
1052 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
1053 {
1054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
1055 return eHAL_STATUS_SUCCESS;
1056 }
1057#endif
1058
1059 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1060 {
1061 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1062 return eHAL_STATUS_SUCCESS;
1063 }
1064
1065 vos_mem_zero( &scanRequest, sizeof(scanRequest));
1066 if (NULL != wrqu->data.pointer)
1067 {
1068 char *str_ptr = NULL;
1069 tCsrSSIDInfo *SsidInfo = NULL;
1070 int num_ssid = 0;
1071 int i, j, ssid_start;
1072 hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP;
1073
Rajeev Kumarbe97df02013-10-24 18:30:39 -07001074 str_ptr = extra;
Jeff Johnson295189b2012-06-20 16:38:30 -07001075
1076 i = WEXT_CSCAN_HEADER_SIZE;
1077
1078 if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] )
1079 {
1080 scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i];
1081 ++i;
1082 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001083 pHddCtx->scan_info.scan_pending_option = scanPendingOption;
Jeff Johnson295189b2012-06-20 16:38:30 -07001084
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001085 if(pHddCtx->scan_info.mScanPending == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07001086 {
1087 hddLog(LOG1,"%s: mScanPending is TRUE",__func__);
1088 /* If any scan is pending, just giveup this scan request */
1089 if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption)
1090 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001091 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 return eHAL_STATUS_SUCCESS;
1093 }
1094 /* If any scan pending, wait till finish current scan,
1095 and try this scan request when previous scan finish */
1096 else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption)
1097 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001098 pHddCtx->scan_info.waitScanResult = TRUE;
1099 vos_event_reset(&pHddCtx->scan_info.scan_finished_event);
1100 if(vos_wait_single_event(&pHddCtx->scan_info.scan_finished_event,
Jeff Johnson295189b2012-06-20 16:38:30 -07001101 WEXT_CSCAN_SCAN_DONE_WAIT_TIME))
1102 {
1103 hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__);
1104 return eHAL_STATUS_SUCCESS;
1105 }
1106 }
1107 /* Piggyback previous scan result */
1108 else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption)
1109 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001110 pHddCtx->scan_info.waitScanResult = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 return eHAL_STATUS_SUCCESS;
1112 }
1113 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001114 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001115
1116 /* Check for scan IE */
1117 while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] )
1118 {
1119 /* ssid_len */
1120 if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION)
1121 {
1122 /* total number of ssid's */
1123 num_ssid++;
1124 /* increment length filed */
1125 i += str_ptr[i] + 1;
1126 }
1127 /* i should be saved and it will be pointing to 'C' */
1128 }
1129
1130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid);
1131 if( num_ssid )
1132 {
1133 /* To be fixed in SME and PE: override the number of ssid with 1,
1134 * as SME and PE does not handle multiple SSID in scan request
1135 * */
1136 scanRequest.SSIDs.numOfSSIDs = num_ssid;
1137 /* Allocate num_ssid tCsrSSIDInfo structure */
1138 SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo));
1139 if(NULL == scanRequest.SSIDs.SSIDList) {
1140 hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer");
1141 return -ENOMEM;
1142 }
1143
1144 /* copy all the ssid's and their length */
1145 ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;/* skipping 'S' */
1146 for(j = 0; j < num_ssid; j++) {
1147 if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){
1148 scanRequest.SSIDs.numOfSSIDs -= 1;
1149 } else{
1150 /* get the ssid length */
1151 SsidInfo->SSID.length = str_ptr[ssid_start++];
1152 vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length);
Arif Hussain6d2a3322013-11-17 19:50:10 -08001153 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s", j, SsidInfo->SSID.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 }
1155 /* skipping length */
1156 ssid_start += str_ptr[ssid_start - 1] + 1;
1157 /* Store next ssid info */
1158 SsidInfo++;
1159 }
1160 }
1161
1162 /* Check for Channel IE */
1163 if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i])
1164 {
1165 if( str_ptr[++i] == 0 )
1166 {
1167 scanRequest.ChannelInfo.numOfChannels = 0;
1168 scanRequest.ChannelInfo.ChannelList = NULL;
1169 i++;
1170 }
1171 else {
1172
1173 /* increment the counter */
1174 scanRequest.ChannelInfo.numOfChannels = str_ptr[i++];
1175 /* store temp channel list */
1176 /* SME expects 1 byte channel content */
1177 scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t));
1178 if(NULL == scanRequest.ChannelInfo.ChannelList)
1179 {
c_hpothu7f63e882013-10-02 19:13:35 +05301180 hddLog(LOGE, "memory alloc failed for channel list creation");
Jeff Johnson295189b2012-06-20 16:38:30 -07001181 status = -ENOMEM;
1182 goto exit_point;
1183 }
1184
1185 for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++)
1186 {
1187 /* SCAN request from upper layer has 2 bytes channel */
1188 scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i];
1189 i += sizeof(v_U16_t);
1190 }
1191 }
1192 }
1193
1194 /* Set default */
1195 scanRequest.scanType = eSIR_ACTIVE_SCAN;
1196 scanRequest.minChnTime = 0;
1197 scanRequest.maxChnTime = 0;
1198
1199 /* Now i is pointing to passive dwell dwell time */
1200 /* 'P',min dwell time, max dwell time */
1201 /* next two offsets contain min and max channel time */
1202 if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) )
1203 {
1204 /* No SSID specified, num_ssid == 0, then start paasive scan */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001205 if (!num_ssid || (eSIR_PASSIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 {
1207 scanRequest.scanType = eSIR_PASSIVE_SCAN;
1208 scanRequest.minChnTime = (v_U8_t)str_ptr[++i];//scanReq->min_channel_time;
1209 scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];//scanReq->max_channel_time;
1210 i++;
1211 }
1212 else
1213 {
1214 i += 3;
1215 }
1216 }
1217
1218 /* H indicates active channel time */
1219 if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) )
1220 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001221 if (num_ssid || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001222 {
1223 scanRequest.scanType = eSIR_ACTIVE_SCAN;
1224 scanRequest.minChnTime = str_ptr[++i];//scanReq->min_channel_time;
1225 scanRequest.maxChnTime = str_ptr[++i];//scanReq->max_channel_time;
1226 i++;
1227 }
1228 else
1229 {
1230 i +=3;
1231 }
1232 }
1233 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
1234 /* set requestType to full scan */
1235 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001236 pHddCtx->scan_info.mScanPending = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001237
1238 /* if previous genIE is not NULL, update ScanIE */
1239 if(0 != pwextBuf->genIE.length)
1240 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001241 memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
1242 memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
Jeff Johnson295189b2012-06-20 16:38:30 -07001243 pwextBuf->genIE.length );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001244 pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
Agarwal Ashish4f616132013-12-30 23:32:50 +05301245 if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length)
1246 {
1247 memcpy( pwextBuf->roamProfile.addIEScan,
1248 pHddCtx->scan_info.scanAddIE.addIEdata,
1249 pHddCtx->scan_info.scanAddIE.length);
1250 pwextBuf->roamProfile.nAddIEScanLength =
1251 pHddCtx->scan_info.scanAddIE.length;
1252 }
1253 else
1254 {
1255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1256 "Invalid ScanIE, Length is %d",
1257 pwextBuf->genIE.length);
1258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001259
1260 /* clear previous genIE after use it */
1261 memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
1262 }
1263
1264 /* push addIEScan in scanRequset if exist */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001265 if (pHddCtx->scan_info.scanAddIE.addIEdata &&
1266 pHddCtx->scan_info.scanAddIE.length)
Jeff Johnson295189b2012-06-20 16:38:30 -07001267 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001268 scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
1269 scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 }
1271
1272 status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal,
1273 pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
1274 if( !HAL_STATUS_SUCCESS(status) )
1275 {
1276 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 -07001277 pHddCtx->scan_info.mScanPending = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 status = -EINVAL;
1279 goto exit_point;
1280 }
1281
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001282 pHddCtx->scan_info.scanId = scanId;
Kaushik, Sushantdedd4ea2014-11-06 11:55:14 +05301283 pHddCtx->scan_info.sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -07001284
1285 } //end of data->pointer
1286 else {
1287 status = -1;
1288 }
1289
1290exit_point:
1291
1292 /* free ssidlist */
1293 if (scanRequest.SSIDs.SSIDList)
1294 {
1295 vos_mem_free(scanRequest.SSIDs.SSIDList);
1296 }
1297 /* free the channel list */
1298 if(scanRequest.ChannelInfo.ChannelList)
1299 {
1300 vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList);
1301 }
1302
1303 EXIT();
1304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
1305 return status;
1306}
1307
1308/* Abort any MAC scan if in progress */
c_hpothua3d45d52015-01-05 14:11:17 +05301309tSirAbortScanStatus hdd_abort_mac_scan(hdd_context_t* pHddCtx,
1310 tANI_U8 sessionId,
1311 eCsrAbortReason reason)
Jeff Johnson295189b2012-06-20 16:38:30 -07001312{
c_hpothua3d45d52015-01-05 14:11:17 +05301313 return sme_AbortMacScan(pHddCtx->hHal, sessionId, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07001314}
1315