blob: 2700a91c609df69aa4f4dc3234b61698b3a68dc0 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**========================================================================
23
24 \file wlan_hdd_hostapd.c
25 \brief WLAN Host Device Driver implementation
26
27 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
28
29 Qualcomm Confidential and Proprietary.
30
31 ========================================================================*/
32/**=========================================================================
33 EDIT HISTORY FOR FILE
34
35
36 This section contains comments describing changes made to the module.
37 Notice that changes are listed in reverse chronological order.
38
39 $Header:$ $DateTime: $ $Author: $
40
41
42 when who what, where, why
43 -------- --- --------------------------------------------------------
44 04/5/09 Shailender Created module.
45 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
46 ==========================================================================*/
47/*--------------------------------------------------------------------------
48 Include Files
49 ------------------------------------------------------------------------*/
50
51#include <linux/version.h>
52#include <linux/module.h>
53#include <linux/kernel.h>
54#include <linux/init.h>
55#include <linux/wireless.h>
56#include <linux/semaphore.h>
57#include <vos_api.h>
58#include <vos_sched.h>
59#include <linux/etherdevice.h>
60#include <wlan_hdd_includes.h>
61#include <qc_sap_ioctl.h>
62#include <wlan_hdd_hostapd.h>
63#include <sapApi.h>
64#include <sapInternal.h>
65#include <wlan_qct_tl.h>
66#include <wlan_hdd_softap_tx_rx.h>
67#include <wlan_hdd_main.h>
68#include <linux/netdevice.h>
69#include <linux/mmc/sdio_func.h>
70#include "wlan_nlink_common.h"
71#include "wlan_btc_svc.h"
72#include <bap_hdd_main.h>
73#if defined CONFIG_CFG80211
74#include "wlan_hdd_p2p.h"
75#endif
76
77#define IS_UP(_dev) \
78 (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
79#define IS_UP_AUTO(_ic) \
80 (IS_UP((_ic)->ic_dev) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
81#define WE_WLAN_VERSION 1
82#define STATS_CONTEXT_MAGIC 0x53544154
83
84struct statsContext
85{
86 struct completion completion;
87 hdd_adapter_t *pAdapter;
88 unsigned int magic;
89};
90#define SAP_24GHZ_CH_COUNT (14)
91/*---------------------------------------------------------------------------
92 * Function definitions
93 *-------------------------------------------------------------------------*/
94/**---------------------------------------------------------------------------
95
96 \brief hdd_hostapd_open() - HDD Open function for hostapd interface
97
98 This is called in response to ifconfig up
99
100 \param - dev Pointer to net_device structure
101
102 \return - 0 for success non-zero for failure
103
104 --------------------------------------------------------------------------*/
105int hdd_hostapd_open (struct net_device *dev)
106{
107 ENTER();
108
109 //Turn ON carrier state
110 netif_carrier_on(dev);
111 //Enable all Tx queues
112 netif_tx_start_all_queues(dev);
113
114 EXIT();
115 return 0;
116}
117/**---------------------------------------------------------------------------
118
119 \brief hdd_hostapd_stop() - HDD stop function for hostapd interface
120
121 This is called in response to ifconfig down
122
123 \param - dev Pointer to net_device structure
124
125 \return - 0 for success non-zero for failure
126
127 --------------------------------------------------------------------------*/
128int hdd_hostapd_stop (struct net_device *dev)
129{
130 ENTER();
131
132 //Stop all tx queues
133 netif_tx_disable(dev);
134
135 //Turn OFF carrier state
136 netif_carrier_off(dev);
137
138 EXIT();
139 return 0;
140}
141/**---------------------------------------------------------------------------
142
143 \brief hdd_hostapd_uninit() - HDD uninit function
144
145 This is called during the netdev unregister to uninitialize all data
146associated with the device
147
148 \param - dev Pointer to net_device structure
149
150 \return - void
151
152 --------------------------------------------------------------------------*/
153static void hdd_hostapd_uninit (struct net_device *dev)
154{
155 hdd_adapter_t *pHostapdAdapter = netdev_priv(dev);
156
157 ENTER();
158
159 if (pHostapdAdapter && pHostapdAdapter->pHddCtx)
160 {
161 hdd_deinit_adapter(pHostapdAdapter->pHddCtx, pHostapdAdapter);
162
163 /* after uninit our adapter structure will no longer be valid */
164 pHostapdAdapter->dev = NULL;
165 }
166
167 EXIT();
168}
169
170
171/**============================================================================
172 @brief hdd_hostapd_hard_start_xmit() - Function registered with the Linux OS for
173 transmitting packets. There are 2 versions of this function. One that uses
174 locked queue and other that uses lockless queues. Both have been retained to
175 do some performance testing
176 @param skb : [in] pointer to OS packet (sk_buff)
177 @param dev : [in] pointer to Libra network device
178
179 @return : NET_XMIT_DROP if packets are dropped
180 : NET_XMIT_SUCCESS if packet is enqueued succesfully
181 ===========================================================================*/
182int hdd_hostapd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
183{
184 return 0;
185}
186int hdd_hostapd_change_mtu(struct net_device *dev, int new_mtu)
187{
188 return 0;
189}
190
191int hdd_hostapd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
192{
193 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
194 hdd_priv_data_t priv_data;
195 tANI_U8 *command = NULL;
196 int ret = 0;
197
198 if (NULL == pAdapter)
199 {
200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
201 "%s: HDD adapter context is Null", __FUNCTION__);
202 ret = -ENODEV;
203 goto exit;
204 }
205
Jeff Johnsone7245742012-09-05 17:12:55 -0700206 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700207 {
208 ret = -EINVAL;
209 goto exit;
210 }
211
212 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
213 {
214 ret = -EFAULT;
215 goto exit;
216 }
217
218 command = kmalloc(priv_data.total_len, GFP_KERNEL);
219 if (!command)
220 {
221 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
222 "%s: failed to allocate memory\n", __FUNCTION__);
223 ret = -ENOMEM;
224 goto exit;
225 }
226
227 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
228 {
229 ret = -EFAULT;
230 goto exit;
231 }
232
233 if ((SIOCDEVPRIVATE + 1) == cmd)
234 {
235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
236 "***HOSTAPD*** : Received %s cmd from Wi-Fi GUI***", command);
237
238#ifdef WLAN_FEATURE_P2P
239 if(strncmp(command, "P2P_SET_NOA", 11) == 0 )
240 {
241 hdd_setP2pNoa(dev, command);
242 }
243 else if( strncmp(command, "P2P_SET_PS", 10) == 0 )
244 {
245 hdd_setP2pOpps(dev, command);
246 }
247#endif
248 }
249exit:
250 if (command)
251 {
252 kfree(command);
253 }
254 return ret;
255}
256
257/**---------------------------------------------------------------------------
258
259 \brief hdd_hostapd_set_mac_address() -
260 This function sets the user specified mac address using
261 the command ifconfig wlanX hw ether <mac adress>.
262
263 \param - dev - Pointer to the net device.
264 - addr - Pointer to the sockaddr.
265 \return - 0 for success, non zero for failure
266
267 --------------------------------------------------------------------------*/
268
269static int hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
270{
271 struct sockaddr *psta_mac_addr = addr;
272 ENTER();
273 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
274 EXIT();
275 return 0;
276}
277void hdd_hostapd_inactivity_timer_cb(v_PVOID_t usrDataForCallback)
278{
279 struct net_device *dev = (struct net_device *)usrDataForCallback;
280 v_BYTE_t we_custom_event[64];
281 union iwreq_data wrqu;
282#ifdef DISABLE_CONCURRENCY_AUTOSAVE
283 VOS_STATUS vos_status;
284 hdd_adapter_t *pHostapdAdapter;
285 hdd_ap_ctx_t *pHddApCtx;
286#endif /*DISABLE_CONCURRENCY_AUTOSAVE */
287
288 /* event_name space-delimiter driver_module_name */
289 /* Format of the event is "AUTO-SHUT.indication" " " "module_name" */
290 char * autoShutEvent = "AUTO-SHUT.indication" " " KBUILD_MODNAME;
291 int event_len = strlen(autoShutEvent) + 1; /* For the NULL at the end */
292
293 ENTER();
294
295#ifdef DISABLE_CONCURRENCY_AUTOSAVE
296 if (vos_concurrent_sessions_running())
297 {
298 /*
299 This timer routine is going to be called only when AP
300 persona is up.
301 If there are concurrent sessions running we do not want
302 to shut down the Bss.Instead we run the timer again so
303 that if Autosave is enabled next time and other session
304 was down only then we bring down AP
305 */
306 pHostapdAdapter = netdev_priv(dev);
307 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
308 vos_status = vos_timer_start(
309 &pHddApCtx->hdd_ap_inactivity_timer,
310 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff
311 * 1000);
312 if (!VOS_IS_STATUS_SUCCESS(vos_status))
313 {
314 hddLog(LOGE, FL("Failed to init AP inactivity timer"));
315 }
316 EXIT();
317 return;
318 }
319#endif /*DISABLE_CONCURRENCY_AUTOSAVE */
320 memset(&we_custom_event, '\0', sizeof(we_custom_event));
321 memcpy(&we_custom_event, autoShutEvent, event_len);
322
323 memset(&wrqu, 0, sizeof(wrqu));
324 wrqu.data.length = event_len;
325
326 hddLog(LOG1, FL("Shutting down AP interface due to inactivity"));
327 wireless_send_event(dev, IWEVCUSTOM, &wrqu, (char *)we_custom_event);
328
329 EXIT();
330}
331
332
333VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback)
334{
335 hdd_adapter_t *pHostapdAdapter;
336 hdd_ap_ctx_t *pHddApCtx;
337 hdd_hostapd_state_t *pHostapdState;
338 struct net_device *dev;
339 eSapHddEvent sapEvent;
340 union iwreq_data wrqu;
341 v_BYTE_t *we_custom_event_generic = NULL;
342 int we_event = 0;
343 int i = 0;
344 v_U8_t staId;
345 VOS_STATUS vos_status;
346 v_BOOL_t bWPSState;
347 v_BOOL_t bApActive = FALSE;
348 v_BOOL_t bAuthRequired = TRUE;
349 tpSap_AssocMacAddr pAssocStasArray = NULL;
350 char unknownSTAEvent[IW_CUSTOM_MAX+1];
351 char maxAssocExceededEvent[IW_CUSTOM_MAX+1];
352 v_BYTE_t we_custom_start_event[64];
353 char *startBssEvent;
354
355 dev = (struct net_device *)usrDataForCallback;
356 pHostapdAdapter = netdev_priv(dev);
357 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
358 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
359 sapEvent = pSapEvent->sapHddEventCode;
360 memset(&wrqu, '\0', sizeof(wrqu));
361
362 switch(sapEvent)
363 {
364 case eSAP_START_BSS_EVENT :
365 hddLog(LOG1, FL("BSS configured status = %s, channel = %lu, bc sta Id = %d\n"),
366 pSapEvent->sapevt.sapStartBssCompleteEvent.status ? "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS",
367 pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel,
368 pSapEvent->sapevt.sapStartBssCompleteEvent.staId);
369
370 pHostapdState->vosStatus = pSapEvent->sapevt.sapStartBssCompleteEvent.status;
371 vos_status = vos_event_set(&pHostapdState->vosEvent);
372
373 if (!VOS_IS_STATUS_SUCCESS(vos_status) || pHostapdState->vosStatus)
374 {
375 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: startbss event failed!!\n"));
376 goto stopbss;
377 }
378 else
379 {
380 pHddApCtx->uBCStaId = pSapEvent->sapevt.sapStartBssCompleteEvent.staId;
381 //@@@ need wep logic here to set privacy bit
382 hdd_softap_Register_BC_STA(pHostapdAdapter, pHddApCtx->uPrivacy);
383 }
384
385 if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff)
386 {
387 // AP Inactivity timer init and start
388 vos_status = vos_timer_init( &pHddApCtx->hdd_ap_inactivity_timer, VOS_TIMER_TYPE_SW,
389 hdd_hostapd_inactivity_timer_cb, (v_PVOID_t)dev );
390 if (!VOS_IS_STATUS_SUCCESS(vos_status))
391 hddLog(LOGE, FL("Failed to init AP inactivity timer\n"));
392
393 vos_status = vos_timer_start( &pHddApCtx->hdd_ap_inactivity_timer, (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff * 1000);
394 if (!VOS_IS_STATUS_SUCCESS(vos_status))
395 hddLog(LOGE, FL("Failed to init AP inactivity timer\n"));
396
397 }
398 pHddApCtx->operatingChannel = pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel;
399 pHostapdState->bssState = BSS_START;
400
401 // Send current operating channel of SoftAP to BTC-ES
402 send_btc_nlink_msg(WLAN_BTC_SOFTAP_BSS_START, 0);
403
404#ifdef CONFIG_CFG80211
405 //Check if there is any group key pending to set.
406 if( pHddApCtx->groupKey.keyLength )
407 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700408 if( VOS_STATUS_SUCCESS != WLANSAP_SetKeySta(
Jeff Johnson295189b2012-06-20 16:38:30 -0700409 (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext,
410 &pHddApCtx->groupKey ) )
411 {
412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
413 "%s: WLANSAP_SetKeySta failed", __func__);
414 }
415 pHddApCtx->groupKey.keyLength = 0;
416 }
417 else if ( pHddApCtx->wepKey[0].keyLength )
418 {
419 int i=0;
420 for ( i = 0; i < CSR_MAX_NUM_KEY; i++ )
421 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700422 if( VOS_STATUS_SUCCESS != WLANSAP_SetKeySta(
Jeff Johnson295189b2012-06-20 16:38:30 -0700423 (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext,
424 &pHddApCtx->wepKey[i] ) )
425 {
426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
427 "%s: WLANSAP_SetKeySta failed idx %d", __func__, i);
428 }
429 pHddApCtx->wepKey[i].keyLength = 0;
430 }
431 }
432#endif
433 //Fill the params for sending IWEVCUSTOM Event with SOFTAP.enabled
434 startBssEvent = "SOFTAP.enabled";
435 memset(&we_custom_start_event, '\0', sizeof(we_custom_start_event));
436 memcpy(&we_custom_start_event, startBssEvent, strlen(startBssEvent));
437 memset(&wrqu, 0, sizeof(wrqu));
438 wrqu.data.length = strlen(startBssEvent);
439 we_event = IWEVCUSTOM;
440 we_custom_event_generic = we_custom_start_event;
441
442 break; //Event will be sent after Switch-Case stmt
443
444 case eSAP_STOP_BSS_EVENT:
445 hddLog(LOG1, FL("BSS stop status = %s\n"),pSapEvent->sapevt.sapStopBssCompleteEvent.status ?
446 "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS");
447
448 pHddApCtx->operatingChannel = 0; //Invalidate the channel info.
449 vos_event_set(&pHostapdState->vosEvent);
450 goto stopbss;
451 case eSAP_STA_SET_KEY_EVENT:
452 //TODO: forward the message to hostapd once implementtation is done for now just print
453 hddLog(LOG1, FL("SET Key: configured status = %s\n"),pSapEvent->sapevt.sapStationSetKeyCompleteEvent.status ?
454 "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS");
455 return VOS_STATUS_SUCCESS;
456 case eSAP_STA_DEL_KEY_EVENT:
457 //TODO: forward the message to hostapd once implementtation is done for now just print
458 hddLog(LOG1, FL("Event received %s\n"),"eSAP_STA_DEL_KEY_EVENT");
459 return VOS_STATUS_SUCCESS;
460 case eSAP_STA_MIC_FAILURE_EVENT:
461 {
462 struct iw_michaelmicfailure msg;
463 memset(&msg, '\0', sizeof(msg));
464 msg.src_addr.sa_family = ARPHRD_ETHER;
465 memcpy(msg.src_addr.sa_data, &pSapEvent->sapevt.sapStationMICFailureEvent.staMac, sizeof(msg.src_addr.sa_data));
466 hddLog(LOG1, "MIC MAC "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(msg.src_addr.sa_data));
Jeff Johnson43971f52012-07-17 12:26:56 -0700467 if(pSapEvent->sapevt.sapStationMICFailureEvent.multicast == eSAP_TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 msg.flags = IW_MICFAILURE_GROUP;
469 else
470 msg.flags = IW_MICFAILURE_PAIRWISE;
471 memset(&wrqu, 0, sizeof(wrqu));
472 wrqu.data.length = sizeof(msg);
473 we_event = IWEVMICHAELMICFAILURE;
474 we_custom_event_generic = (v_BYTE_t *)&msg;
475 }
476#ifdef CONFIG_CFG80211
477 /* inform mic failure to nl80211 */
478 cfg80211_michael_mic_failure(dev,
479 pSapEvent->sapevt.
480 sapStationMICFailureEvent.staMac.bytes,
Jeff Johnson43971f52012-07-17 12:26:56 -0700481 ((pSapEvent->sapevt.sapStationMICFailureEvent.multicast == eSAP_TRUE) ?
Jeff Johnson295189b2012-06-20 16:38:30 -0700482 NL80211_KEYTYPE_GROUP :
483 NL80211_KEYTYPE_PAIRWISE),
484 pSapEvent->sapevt.sapStationMICFailureEvent.keyId,
485 pSapEvent->sapevt.sapStationMICFailureEvent.TSC,
486 GFP_KERNEL);
487#endif
488 break;
489
490 case eSAP_STA_ASSOC_EVENT:
491 case eSAP_STA_REASSOC_EVENT:
492 wrqu.addr.sa_family = ARPHRD_ETHER;
493 memcpy(wrqu.addr.sa_data, &pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac,
494 sizeof(wrqu.addr.sa_data));
495 hddLog(LOG1, " associated "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(wrqu.addr.sa_data));
496 we_event = IWEVREGISTERED;
497
498 WLANSAP_Get_WPS_State((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &bWPSState);
499
500 if ( (eCSR_ENCRYPT_TYPE_NONE == pHddApCtx->ucEncryptType) ||
501 ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddApCtx->ucEncryptType ) ||
502 ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddApCtx->ucEncryptType ) )
503 {
504 bAuthRequired = FALSE;
505 }
506
507 if (bAuthRequired || bWPSState == eANI_BOOLEAN_TRUE )
508 {
509 hdd_softap_RegisterSTA( pHostapdAdapter,
510 TRUE,
511 pHddApCtx->uPrivacy,
512 pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId,
513 0,
514 0,
515 (v_MACADDR_t *)wrqu.addr.sa_data,
516 pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled);
517 }
518 else
519 {
520 hdd_softap_RegisterSTA( pHostapdAdapter,
521 FALSE,
522 pHddApCtx->uPrivacy,
523 pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId,
524 0,
525 0,
526 (v_MACADDR_t *)wrqu.addr.sa_data,
527 pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled);
528 }
529
530 // Stop AP inactivity timer
531 if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_RUNNING)
532 {
533 vos_status = vos_timer_stop(&pHddApCtx->hdd_ap_inactivity_timer);
534 if (!VOS_IS_STATUS_SUCCESS(vos_status))
535 hddLog(LOGE, FL("Failed to start AP inactivity timer\n"));
536 }
537#ifdef CONFIG_CFG80211
538#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
539 {
540 struct station_info staInfo;
541 v_U16_t iesLen = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.iesLen;
542
543 memset(&staInfo, 0, sizeof(staInfo));
544 if (iesLen <= MAX_ASSOC_IND_IE_LEN )
545 {
546 staInfo.assoc_req_ies =
547 (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0];
548 staInfo.assoc_req_ies_len = iesLen;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700549#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
550 staInfo.filled |= STATION_INFO_ASSOC_REQ_IES;
551#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700552 cfg80211_new_sta(dev,
553 (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes[0],
554 &staInfo, GFP_KERNEL);
555 }
556 else
557 {
558 hddLog(LOGE, FL(" Assoc Ie length is too long \n"));
559 }
560 }
561#endif
562#endif
563
564 break;
565 case eSAP_STA_DISASSOC_EVENT:
566 memcpy(wrqu.addr.sa_data, &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac,
567 sizeof(wrqu.addr.sa_data));
568 hddLog(LOG1, " disassociated "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(wrqu.addr.sa_data));
569 if (pSapEvent->sapevt.sapStationDisassocCompleteEvent.reason == eSAP_USR_INITATED_DISASSOC)
570 hddLog(LOG1," User initiated disassociation");
571 else
572 hddLog(LOG1," MAC initiated disassociation");
573 we_event = IWEVEXPIRED;
574 vos_status = hdd_softap_GetStaId(pHostapdAdapter, &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac, &staId);
575 if (!VOS_IS_STATUS_SUCCESS(vos_status))
576 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700578 return VOS_STATUS_E_FAILURE;
579 }
580 hdd_softap_DeregisterSTA(pHostapdAdapter, staId);
581
582 if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff)
583 {
584 spin_lock_bh( &pHostapdAdapter->staInfo_lock );
585 // Start AP inactivity timer if no stations associated with it
586 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
587 {
588 if (pHostapdAdapter->aStaInfo[i].isUsed && i != (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uBCStaId)
589 {
590 bApActive = TRUE;
591 break;
592 }
593 }
594 spin_unlock_bh( &pHostapdAdapter->staInfo_lock );
595
596 if (bApActive == FALSE)
597 {
598 if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_STOPPED)
599 {
600 vos_status = vos_timer_start(&pHddApCtx->hdd_ap_inactivity_timer, (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff * 1000);
601 if (!VOS_IS_STATUS_SUCCESS(vos_status))
602 hddLog(LOGE, FL("Failed to init AP inactivity timer\n"));
603 }
604 else
605 VOS_ASSERT(vos_timer_getCurrentState(&pHddApCtx->hdd_ap_inactivity_timer) == VOS_TIMER_STATE_STOPPED);
606 }
607 }
608#ifdef CONFIG_CFG80211
609#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
610 cfg80211_del_sta(dev,
611 (const u8 *)&pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac.bytes[0],
612 GFP_KERNEL);
613#endif
614#endif
615 break;
616 case eSAP_WPS_PBC_PROBE_REQ_EVENT:
617 {
618 static const char * message ="MLMEWPSPBCPROBEREQ.indication";
619 union iwreq_data wreq;
620
621 down(&pHddApCtx->semWpsPBCOverlapInd);
622 pHddApCtx->WPSPBCProbeReq.probeReqIELen = pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.probeReqIELen;
623
624 vos_mem_copy(pHddApCtx->WPSPBCProbeReq.probeReqIE, pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.probeReqIE,
625 pHddApCtx->WPSPBCProbeReq.probeReqIELen);
626
627 vos_mem_copy(pHddApCtx->WPSPBCProbeReq.peerMacAddr, pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.peerMacAddr, sizeof(v_MACADDR_t));
628 hddLog(LOG1, "WPS PBC probe req "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(pHddApCtx->WPSPBCProbeReq.peerMacAddr));
629 memset(&wreq, 0, sizeof(wreq));
630 wreq.data.length = strlen(message); // This is length of message
631 wireless_send_event(dev, IWEVCUSTOM, &wreq, (char *)message);
632
633 return VOS_STATUS_SUCCESS;
634 }
635 case eSAP_ASSOC_STA_CALLBACK_EVENT:
636 pAssocStasArray = pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas;
637 if (pSapEvent->sapevt.sapAssocStaListEvent.noOfAssocSta != 0)
638 { // List of associated stations
639 for (i = 0; i < pSapEvent->sapevt.sapAssocStaListEvent.noOfAssocSta; i++)
640 {
641 hddLog(LOG1,"Associated Sta Num %d:assocId=%d, staId=%d, staMac="MAC_ADDRESS_STR,
642 i+1,
643 pAssocStasArray->assocId,
644 pAssocStasArray->staId,
645 MAC_ADDR_ARRAY(pAssocStasArray->staMac.bytes));
646 pAssocStasArray++;
647 }
648 }
649 vos_mem_free(pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas);// Release caller allocated memory here
650 return VOS_STATUS_SUCCESS;
651#ifdef WLAN_FEATURE_P2P
652 case eSAP_INDICATE_MGMT_FRAME:
653 hdd_indicateMgmtFrame( pHostapdAdapter,
654 pSapEvent->sapevt.sapManagementFrameInfo.nFrameLength,
655 pSapEvent->sapevt.sapManagementFrameInfo.pbFrames,
656 pSapEvent->sapevt.sapManagementFrameInfo.frameType,
657 pSapEvent->sapevt.sapManagementFrameInfo.rxChan);
658 return VOS_STATUS_SUCCESS;
659 case eSAP_REMAIN_CHAN_READY:
660 hdd_remainChanReadyHandler( pHostapdAdapter );
661 return VOS_STATUS_SUCCESS;
662 case eSAP_SEND_ACTION_CNF:
663 hdd_sendActionCnf( pHostapdAdapter,
664 ( eSAP_STATUS_SUCCESS ==
665 pSapEvent->sapevt.sapActionCnf.actionSendSuccess ) ?
666 TRUE : FALSE );
667 return VOS_STATUS_SUCCESS;
668#endif
669 case eSAP_UNKNOWN_STA_JOIN:
670 snprintf(unknownSTAEvent, IW_CUSTOM_MAX, "JOIN_UNKNOWN_STA-%02x:%02x:%02x:%02x:%02x:%02x",
671 pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[0],
672 pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[1],
673 pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[2],
674 pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[3],
675 pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[4],
676 pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[5]);
677 we_event = IWEVCUSTOM; /* Discovered a new node (AP mode). */
678 wrqu.data.pointer = unknownSTAEvent;
679 wrqu.data.length = strlen(unknownSTAEvent);
680 we_custom_event_generic = (v_BYTE_t *)unknownSTAEvent;
681 hddLog(LOG1,"%s\n", unknownSTAEvent);
682 break;
683
684 case eSAP_MAX_ASSOC_EXCEEDED:
685 snprintf(maxAssocExceededEvent, IW_CUSTOM_MAX, "Peer %02x:%02x:%02x:%02x:%02x:%02x denied"
686 " assoc due to Maximum Mobile Hotspot connections reached. Please disconnect"
687 " one or more devices to enable the new device connection",
688 pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[0],
689 pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[1],
690 pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[2],
691 pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[3],
692 pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[4],
693 pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[5]);
694 we_event = IWEVCUSTOM; /* Discovered a new node (AP mode). */
695 wrqu.data.pointer = maxAssocExceededEvent;
696 wrqu.data.length = strlen(maxAssocExceededEvent);
697 we_custom_event_generic = (v_BYTE_t *)maxAssocExceededEvent;
698 hddLog(LOG1,"%s\n", maxAssocExceededEvent);
699 break;
700 case eSAP_STA_ASSOC_IND:
701 return VOS_STATUS_SUCCESS;
702 default:
703 hddLog(LOG1,"SAP message is not handled\n");
704 goto stopbss;
705 return VOS_STATUS_SUCCESS;
706 }
707 wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic);
708 return VOS_STATUS_SUCCESS;
709
710stopbss :
711 {
712 v_BYTE_t we_custom_event[64];
713 char *stopBssEvent = "STOP-BSS.response";//17
714 int event_len = strlen(stopBssEvent);
715
716 hddLog(LOG1, FL("BSS stop status = %s"),
717 pSapEvent->sapevt.sapStopBssCompleteEvent.status ?
718 "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS");
719
720 /* Change the BSS state now since, as we are shutting things down,
721 * we don't want interfaces to become re-enabled */
722 pHostapdState->bssState = BSS_STOP;
723
724 /* Stop the pkts from n/w stack as we are going to free all of
725 * the TX WMM queues for all STAID's */
726 hdd_hostapd_stop(dev);
727
728 /* reclaim all resources allocated to the BSS */
729 hdd_softap_stop_bss(pHostapdAdapter);
730
731 /* notify userspace that the BSS has stopped */
732 memset(&we_custom_event, '\0', sizeof(we_custom_event));
733 memcpy(&we_custom_event, stopBssEvent, event_len);
734 memset(&wrqu, 0, sizeof(wrqu));
735 wrqu.data.length = event_len;
736 we_event = IWEVCUSTOM;
737 we_custom_event_generic = we_custom_event;
738 wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic);
739 }
740 return VOS_STATUS_SUCCESS;
741}
742int hdd_softap_unpackIE(
743 tHalHandle halHandle,
744 eCsrEncryptionType *pEncryptType,
745 eCsrEncryptionType *mcEncryptType,
746 eCsrAuthType *pAuthType,
747 u_int16_t gen_ie_len,
748 u_int8_t *gen_ie )
749{
750 tDot11fIERSN dot11RSNIE;
751 tDot11fIEWPA dot11WPAIE;
752
753 tANI_U8 *pRsnIe;
754 tANI_U16 RSNIeLen;
755
756 if (NULL == halHandle)
757 {
758 hddLog(LOGE, FL("Error haHandle returned NULL\n"));
759 return -EINVAL;
760 }
761
762 // Validity checks
763 if ((gen_ie_len < VOS_MIN(DOT11F_IE_RSN_MIN_LEN, DOT11F_IE_WPA_MIN_LEN)) ||
764 (gen_ie_len > VOS_MAX(DOT11F_IE_RSN_MAX_LEN, DOT11F_IE_WPA_MAX_LEN)) )
765 return -EINVAL;
766 // Type check
767 if ( gen_ie[0] == DOT11F_EID_RSN)
768 {
769 // Validity checks
770 if ((gen_ie_len < DOT11F_IE_RSN_MIN_LEN ) ||
771 (gen_ie_len > DOT11F_IE_RSN_MAX_LEN) )
772 {
773 return VOS_STATUS_E_FAILURE;
774 }
775 // Skip past the EID byte and length byte
776 pRsnIe = gen_ie + 2;
777 RSNIeLen = gen_ie_len - 2;
778 // Unpack the RSN IE
779 memset(&dot11RSNIE, 0, sizeof(tDot11fIERSN));
780 dot11fUnpackIeRSN((tpAniSirGlobal) halHandle,
781 pRsnIe,
782 RSNIeLen,
783 &dot11RSNIE);
784 // Copy out the encryption and authentication types
785 hddLog(LOG1, FL("%s: pairwise cipher suite count: %d\n"),
786 __FUNCTION__, dot11RSNIE.pwise_cipher_suite_count );
787 hddLog(LOG1, FL("%s: authentication suite count: %d\n"),
788 __FUNCTION__, dot11RSNIE.akm_suite_count);
789 /*Here we have followed the apple base code,
790 but probably I suspect we can do something different*/
791 //dot11RSNIE.akm_suite_count
792 // Just translate the FIRST one
793 *pAuthType = hdd_TranslateRSNToCsrAuthType(dot11RSNIE.akm_suites[0]);
794 //dot11RSNIE.pwise_cipher_suite_count
795 *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]);
796 //dot11RSNIE.gp_cipher_suite_count
797 *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite);
798 // Set the PMKSA ID Cache for this interface
799
800 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
801 } else
802 if (gen_ie[0] == DOT11F_EID_WPA)
803 {
804 // Validity checks
805 if ((gen_ie_len < DOT11F_IE_WPA_MIN_LEN ) ||
806 (gen_ie_len > DOT11F_IE_WPA_MAX_LEN))
807 {
808 return VOS_STATUS_E_FAILURE;
809 }
810 // Skip past the EID byte and length byte - and four byte WiFi OUI
811 pRsnIe = gen_ie + 2 + 4;
812 RSNIeLen = gen_ie_len - (2 + 4);
813 // Unpack the WPA IE
814 memset(&dot11WPAIE, 0, sizeof(tDot11fIEWPA));
815 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
816 pRsnIe,
817 RSNIeLen,
818 &dot11WPAIE);
819 // Copy out the encryption and authentication types
820 hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d\n"),
821 __FUNCTION__, dot11WPAIE.unicast_cipher_count );
822 hddLog(LOG1, FL("%s: WPA authentication suite count: %d\n"),
823 __FUNCTION__, dot11WPAIE.auth_suite_count);
824 //dot11WPAIE.auth_suite_count
825 // Just translate the FIRST one
826 *pAuthType = hdd_TranslateWPAToCsrAuthType(dot11WPAIE.auth_suites[0]);
827 //dot11WPAIE.unicast_cipher_count
828 *pEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.unicast_ciphers[0]);
829 //dot11WPAIE.unicast_cipher_count
830 *mcEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
831 }
832 else
833 {
834 hddLog(LOGW, FL("%s: gen_ie[0]: %d\n"), __FUNCTION__, gen_ie[0]);
835 return VOS_STATUS_E_FAILURE;
836 }
837 return VOS_STATUS_SUCCESS;
838}
839int
840static iw_softap_setparam(struct net_device *dev,
841 struct iw_request_info *info,
842 union iwreq_data *wrqu, char *extra)
843{
844 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
845 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
846 int *value = (int *)extra;
847 int sub_cmd = value[0];
848 int set_value = value[1];
849 eHalStatus status;
850 int ret = 0; /* success */
851 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
852
853 switch(sub_cmd)
854 {
855
856 case QCSAP_PARAM_CLR_ACL:
Jeff Johnson43971f52012-07-17 12:26:56 -0700857 if ( VOS_STATUS_SUCCESS != WLANSAP_ClearACL( pVosContext ))
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 {
859 ret = -EIO;
860 }
861 break;
862
863 case QCSAP_PARAM_ACL_MODE:
864 if ((eSAP_ALLOW_ALL < (eSapMacAddrACL)set_value) ||
865 (eSAP_ACCEPT_UNLESS_DENIED > (eSapMacAddrACL)set_value))
866 {
867 hddLog(LOGE, FL("Invalid ACL Mode value %d"), set_value);
868 ret = -EINVAL;
869 }
870 else
871 {
872 WLANSAP_SetMode(pVosContext, set_value);
873 }
874 break;
875 case QCSAP_PARAM_MAX_ASSOC:
876 if (WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value)
877 {
878 hddLog(LOGE, FL("Invalid setMaxAssoc value %d"), set_value);
879 ret = -EINVAL;
880 }
881 else
882 {
883 if (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value)
884 {
885 hddLog(LOGW, FL("setMaxAssoc value %d higher than max allowed %d."
886 "Setting it to max allowed and continuing"),
887 set_value, WNI_CFG_ASSOC_STA_LIMIT_STAMAX);
888 set_value = WNI_CFG_ASSOC_STA_LIMIT_STAMAX;
889 }
890 status = ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT,
891 set_value, NULL, eANI_BOOLEAN_FALSE);
892 if ( status != eHAL_STATUS_SUCCESS )
893 {
894 hddLog(LOGE, FL("setMaxAssoc failure, status %d"),
895 status);
896 ret = -EIO;
897 }
898 }
899 break;
900
901 case QCSAP_PARAM_HIDE_SSID:
902 {
903 eHalStatus status = eHAL_STATUS_SUCCESS;
904 status = sme_HideSSID(hHal, pHostapdAdapter->sessionId, set_value);
905 if(eHAL_STATUS_SUCCESS != status)
906 {
907 hddLog(VOS_TRACE_LEVEL_ERROR,
908 "%s: QCSAP_PARAM_HIDE_SSID failed",
909 __FUNCTION__);
910 return status;
911 }
912 break;
913 }
914
915 default:
916 hddLog(LOGE, FL("Invalid setparam command %d value %d"),
917 sub_cmd, set_value);
918 ret = -EINVAL;
919 break;
920 }
921
922 return ret;
923}
924
925
926int
927static iw_softap_getparam(struct net_device *dev,
928 struct iw_request_info *info,
929 union iwreq_data *wrqu, char *extra)
930{
931 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
932 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
933 int *value = (int *)extra;
934 int sub_cmd = value[0];
935 eHalStatus status;
936 int ret = 0; /* success */
937 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
938
939 switch (sub_cmd)
940 {
941 case QCSAP_PARAM_MAX_ASSOC:
942 status = ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value);
943 if (eHAL_STATUS_SUCCESS != status)
944 {
945 ret = -EIO;
946 }
947 break;
948
949 case QCSAP_PARAM_CLR_ACL:
Jeff Johnson43971f52012-07-17 12:26:56 -0700950 if ( VOS_STATUS_SUCCESS != WLANSAP_ClearACL( pVosContext ))
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 {
952 ret = -EIO;
953 }
954 *value = 0;
955 break;
956
957 case QCSAP_PARAM_MODULE_DOWN_IND:
958 {
959 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
960 "%s: sending WLAN_MODULE_DOWN_IND", __FUNCTION__);
961 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
962#ifdef WLAN_BTAMP_FEATURE
963 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
964 "%s: Take down AMP PAL", __FUNCTION__);
965 BSL_Deinit(vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
966#endif
967 *value = 0;
968 break;
Jeff Johnson43971f52012-07-17 12:26:56 -0700969 }
970
971 case QCSAP_PARAM_GET_WLAN_DBG:
972 {
973 vos_trace_display();
974 *value = 0;
975 break;
976 }
977
978 case QCSAP_PARAM_AUTO_CHANNEL:
979 {
980 *value = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apAutoChannelSelection;
981 break;
982 }
983
Jeff Johnson295189b2012-06-20 16:38:30 -0700984 default:
985 hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd);
986 ret = -EINVAL;
987 break;
988
989 }
990
991 return ret;
992}
993
994/* Usage:
995 BLACK_LIST = 0
996 WHITE_LIST = 1
997 ADD MAC = 0
998 REMOVE MAC = 1
999
1000 mac addr will be accepted as a 6 octet mac address with each octet inputted in hex
1001 for e.g. 00:0a:f5:11:22:33 will be represented as 0x00 0x0a 0xf5 0x11 0x22 0x33
1002 while using this ioctl
1003
1004 Syntax:
1005 iwpriv softap.0 modify_acl
1006 <6 octet mac addr> <list type> <cmd type>
1007
1008 Examples:
1009 eg 1. to add a mac addr 00:0a:f5:89:89:90 to the black list
1010 iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 0 0
1011 eg 2. to delete a mac addr 00:0a:f5:89:89:90 from white list
1012 iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 1 1
1013*/
1014int iw_softap_modify_acl(struct net_device *dev, struct iw_request_info *info,
1015 union iwreq_data *wrqu, char *extra)
1016{
1017 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1018 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1019 v_BYTE_t *value = (v_BYTE_t*)extra;
1020 v_U8_t pPeerStaMac[VOS_MAC_ADDR_SIZE];
1021 int listType, cmd, i;
1022 int ret = 0; /* success */
1023
1024 ENTER();
1025 for (i=0; i<VOS_MAC_ADDR_SIZE; i++)
1026 {
1027 pPeerStaMac[i] = *(value+i);
1028 }
1029 listType = (int)(*(value+i));
1030 i++;
1031 cmd = (int)(*(value+i));
1032
1033 hddLog(LOG1, "%s: SAP Modify ACL arg0 %02x:%02x:%02x:%02x:%02x:%02x arg1 %d arg2 %d\n",
1034 __FUNCTION__, pPeerStaMac[0], pPeerStaMac[1], pPeerStaMac[2],
1035 pPeerStaMac[3], pPeerStaMac[4], pPeerStaMac[5], listType, cmd);
1036
1037 if (WLANSAP_ModifyACL(pVosContext, pPeerStaMac,(eSapACLType)listType,(eSapACLCmdType)cmd)
1038 != VOS_STATUS_SUCCESS)
1039 {
1040 hddLog(LOGE, FL("Modify ACL failed\n"));
1041 ret = -EIO;
1042 }
1043 EXIT();
1044 return ret;
1045}
1046
1047int
1048static iw_softap_getchannel(struct net_device *dev,
1049 struct iw_request_info *info,
1050 union iwreq_data *wrqu, char *extra)
1051{
1052 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1053
Jeff Johnson43971f52012-07-17 12:26:56 -07001054 int *value = (int *)extra;
Jeff Johnson295189b2012-06-20 16:38:30 -07001055
Jeff Johnson43971f52012-07-17 12:26:56 -07001056 *value = (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->operatingChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07001057 return 0;
1058}
1059
Jeff Johnsone7245742012-09-05 17:12:55 -07001060int
1061static iw_softap_set_tx_power(struct net_device *dev,
1062 struct iw_request_info *info,
1063 union iwreq_data *wrqu, char *extra)
1064{
1065 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1066 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1067 int cmd_len = wrqu->data.length;
1068 int *value = (int *) kmalloc(cmd_len+1, GFP_KERNEL);
1069 int set_value;
1070 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
1071 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
1072
1073 if(value == NULL)
1074 return -ENOMEM;
1075
1076 if(copy_from_user((char *) value, (char*)(wrqu->data.pointer), cmd_len)) {
1077 hddLog(VOS_TRACE_LEVEL_FATAL, "%s -- copy_from_user --data pointer failed! bailing",
1078 __FUNCTION__);
1079 kfree(value);
1080 return -EFAULT;
1081 }
1082
1083 set_value = value[0];
1084 kfree(value);
1085
1086 if( sme_SetMaxTxPower(hHal, bssid, selfMac, set_value) !=
1087 eHAL_STATUS_SUCCESS )
1088 {
1089 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
1090 __func__);
1091 return -EIO;
1092 }
1093
1094 return 0;
1095}
1096
Jeff Johnson295189b2012-06-20 16:38:30 -07001097#define IS_BROADCAST_MAC(x) (((x[0] & x[1] & x[2] & x[3] & x[4] & x[5]) == 0xff) ? 1 : 0)
1098
1099int
1100static iw_softap_getassoc_stamacaddr(struct net_device *dev,
1101 struct iw_request_info *info,
1102 union iwreq_data *wrqu, char *extra)
1103{
1104 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1105 unsigned char *pmaclist;
1106 hdd_station_info_t *pStaInfo = pHostapdAdapter->aStaInfo;
1107 int cnt = 0, len;
1108
1109
1110 pmaclist = wrqu->data.pointer + sizeof(unsigned long int);
1111 len = wrqu->data.length;
1112
1113 spin_lock_bh( &pHostapdAdapter->staInfo_lock );
1114 while((cnt < WLAN_MAX_STA_COUNT) && (len > (sizeof(v_MACADDR_t)+1))) {
1115 if (TRUE == pStaInfo[cnt].isUsed) {
1116
1117 if(!IS_BROADCAST_MAC(pStaInfo[cnt].macAddrSTA.bytes)) {
1118 memcpy((void *)pmaclist, (void *)&(pStaInfo[cnt].macAddrSTA), sizeof(v_MACADDR_t));
1119 pmaclist += sizeof(v_MACADDR_t);
1120 len -= sizeof(v_MACADDR_t);
1121 }
1122 }
1123 cnt++;
1124 }
1125 spin_unlock_bh( &pHostapdAdapter->staInfo_lock );
1126
1127 *pmaclist = '\0';
1128
1129 wrqu->data.length -= len;
1130
1131 *(unsigned long int *)(wrqu->data.pointer) = wrqu->data.length;
1132
1133 return 0;
1134}
1135
1136/* Usage:
1137 mac addr will be accepted as a 6 octet mac address with each octet inputted in hex
1138 for e.g. 00:0a:f5:11:22:33 will be represented as 0x00 0x0a 0xf5 0x11 0x22 0x33
1139 while using this ioctl
1140
1141 Syntax:
1142 iwpriv softap.0 disassoc_sta <6 octet mac address>
1143
1144 e.g.
1145 disassociate sta with mac addr 00:0a:f5:11:22:33 from softap
1146 iwpriv softap.0 disassoc_sta 0x00 0x0a 0xf5 0x11 0x22 0x33
1147*/
1148
1149int
1150static iw_softap_disassoc_sta(struct net_device *dev,
1151 struct iw_request_info *info,
1152 union iwreq_data *wrqu, char *extra)
1153{
1154 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1155 v_U8_t *peerMacAddr;
1156
1157 ENTER();
1158 /* the comparison below is needed since if iwpriv tool is used for calling this ioctl
1159 * data is passed in extra (less than 16 octets); however in android wifi framework
1160 * data is placed in wrqu->data.pointer.
1161 */
1162 if ((v_U8_t*)wrqu == (v_U8_t*)extra)
1163 peerMacAddr = (v_U8_t *)(extra);
1164 else
1165 peerMacAddr = (v_U8_t *)(wrqu->data.pointer);
1166
1167 hddLog(LOG1, "data %02x:%02x:%02x:%02x:%02x:%02x",
1168 peerMacAddr[0], peerMacAddr[1], peerMacAddr[2],
1169 peerMacAddr[3], peerMacAddr[4], peerMacAddr[5]);
1170 hdd_softap_sta_disassoc(pHostapdAdapter, peerMacAddr);
1171 EXIT();
1172 return 0;
1173}
1174
1175int
1176static iw_softap_ap_stats(struct net_device *dev,
1177 struct iw_request_info *info,
1178 union iwreq_data *wrqu, char *extra)
1179{
1180 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1181 WLANTL_TRANSFER_STA_TYPE statBuffer;
1182 char *pstatbuf;
1183 int len = wrqu->data.length;
1184 pstatbuf = wrqu->data.pointer;
1185
1186 WLANSAP_GetStatistics((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &statBuffer, (v_BOOL_t)wrqu->data.flags);
1187
1188 len = snprintf(pstatbuf, len,
1189 "RUF=%d RMF=%d RBF=%d "
1190 "RUB=%d RMB=%d RBB=%d "
1191 "TUF=%d TMF=%d TBF=%d "
1192 "TUB=%d TMB=%d TBB=%d",
1193 (int)statBuffer.rxUCFcnt, (int)statBuffer.rxMCFcnt, (int)statBuffer.rxBCFcnt,
1194 (int)statBuffer.rxUCBcnt, (int)statBuffer.rxMCBcnt, (int)statBuffer.rxBCBcnt,
1195 (int)statBuffer.txUCFcnt, (int)statBuffer.txMCFcnt, (int)statBuffer.txBCFcnt,
1196 (int)statBuffer.txUCBcnt, (int)statBuffer.txMCBcnt, (int)statBuffer.txBCBcnt
1197 );
1198
1199 wrqu->data.length -= len;
1200 return 0;
1201}
1202
1203int
1204static iw_softap_commit(struct net_device *dev,
1205 struct iw_request_info *info,
1206 union iwreq_data *wrqu, char *extra)
1207{
1208 VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
1209 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1210 hdd_hostapd_state_t *pHostapdState;
1211 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1212 tpWLAN_SAPEventCB pSapEventCallback;
1213 tsap_Config_t *pConfig;
1214 s_CommitConfig_t *pCommitConfig;
1215 struct qc_mac_acl_entry *acl_entry = NULL;
1216 v_SINT_t i = 0, num_mac = 0;
1217 v_U32_t status = 0;
1218 eCsrAuthType RSNAuthType;
1219 eCsrEncryptionType RSNEncryptType;
1220 eCsrEncryptionType mcRSNEncryptType;
1221
1222 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1223 pCommitConfig = (s_CommitConfig_t *)extra;
1224
1225 pConfig = kmalloc(sizeof(tsap_Config_t), GFP_KERNEL);
1226 if(NULL == pConfig) {
1227 hddLog(LOG1, "VOS unable to allocate memory\n");
1228 return -ENOMEM;
1229 }
1230 pConfig->beacon_int = pCommitConfig->beacon_int;
1231 pConfig->channel = pCommitConfig->channel;
1232
1233 /*Protection parameter to enable or disable*/
1234 pConfig->protEnabled = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1235 pConfig->dtim_period = pCommitConfig->dtim_period;
1236 switch(pCommitConfig->hw_mode )
1237 {
1238 case eQC_DOT11_MODE_11A:
1239 pConfig->SapHw_mode = eSAP_DOT11_MODE_11a;
1240 break;
1241 case eQC_DOT11_MODE_11B:
1242 pConfig->SapHw_mode = eSAP_DOT11_MODE_11b;
1243 break;
1244 case eQC_DOT11_MODE_11G:
1245 pConfig->SapHw_mode = eSAP_DOT11_MODE_11g;
1246 break;
1247
1248 case eQC_DOT11_MODE_11N:
1249 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
1250 break;
1251 case eQC_DOT11_MODE_11G_ONLY:
1252 pConfig->SapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1253 break;
1254 case eQC_DOT11_MODE_11N_ONLY:
1255 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n_ONLY;
1256 break;
1257 default:
1258 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
1259 break;
1260
1261 }
1262
1263 pConfig->ieee80211d = pCommitConfig->qcsap80211d;
1264 vos_mem_copy(pConfig->countryCode, pCommitConfig->countryCode, 3);
1265 if(pCommitConfig->authType == eQC_AUTH_TYPE_SHARED_KEY)
1266 pConfig->authType = eSAP_SHARED_KEY;
1267 else if(pCommitConfig->authType == eQC_AUTH_TYPE_OPEN_SYSTEM)
1268 pConfig->authType = eSAP_OPEN_SYSTEM;
1269 else
1270 pConfig->authType = eSAP_AUTO_SWITCH;
1271
1272 pConfig->privacy = pCommitConfig->privacy;
1273 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pCommitConfig->privacy;
1274 pConfig->wps_state = pCommitConfig->wps_state;
1275 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1276 pConfig->RSNWPAReqIELength = pCommitConfig->RSNWPAReqIELength;
1277 if(pConfig->RSNWPAReqIELength){
1278 pConfig->pRSNWPAReqIE = &pCommitConfig->RSNWPAReqIE[0];
1279 if ((pConfig->pRSNWPAReqIE[0] == DOT11F_EID_RSN) || (pConfig->pRSNWPAReqIE[0] == DOT11F_EID_WPA)){
1280 // The actual processing may eventually be more extensive than this.
1281 // Right now, just consume any PMKIDs that are sent in by the app.
1282 status = hdd_softap_unpackIE(
1283#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
1284 vos_get_context( VOS_MODULE_ID_HAL, pVosContext),
1285#else
1286 vos_get_context( VOS_MODULE_ID_PE, pVosContext),
1287#endif
1288 &RSNEncryptType,
1289 &mcRSNEncryptType,
1290 &RSNAuthType,
1291 pConfig->pRSNWPAReqIE[1]+2,
1292 pConfig->pRSNWPAReqIE );
1293
1294 if( VOS_STATUS_SUCCESS == status )
1295 {
1296 // Now copy over all the security attributes you have parsed out
1297 //TODO: Need to handle mixed mode
1298 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1299 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1300 hddLog( LOG1, FL("%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d\n"),
1301 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1302 }
1303 }
1304 }
1305 else
1306 {
1307 /* If no RSNIE, set encrypt type to NONE*/
1308 pConfig->RSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
1309 pConfig->mcRSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
1310 hddLog( LOG1, FL("EncryptionType = %d mcEncryptionType = %d\n"),
1311 pConfig->RSNEncryptType, pConfig->mcRSNEncryptType);
1312 }
1313
1314 pConfig->SSIDinfo.ssidHidden = pCommitConfig->SSIDinfo.ssidHidden;
1315 pConfig->SSIDinfo.ssid.length = pCommitConfig->SSIDinfo.ssid.length;
1316 vos_mem_copy(pConfig->SSIDinfo.ssid.ssId, pCommitConfig->SSIDinfo.ssid.ssId, pConfig->SSIDinfo.ssid.length);
1317 vos_mem_copy(pConfig->self_macaddr.bytes, pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1318
1319 pConfig->SapMacaddr_acl = pCommitConfig->qc_macaddr_acl;
1320
1321 // ht_capab is not what the name conveys,this is used for protection bitmap
1322 pConfig->ht_capab = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1323
1324 if (pCommitConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1325 num_mac = pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1326 else
1327 num_mac = pConfig->num_accept_mac = pCommitConfig->num_accept_mac;
1328 acl_entry = pCommitConfig->accept_mac;
1329 for (i = 0; i < num_mac; i++)
1330 {
1331 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(v_MACADDR_t));
1332 acl_entry++;
1333 }
1334 if (pCommitConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1335 num_mac = pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1336 else
1337 num_mac = pConfig->num_deny_mac = pCommitConfig->num_deny_mac;
1338 acl_entry = pCommitConfig->deny_mac;
1339 for (i = 0; i < num_mac; i++)
1340 {
1341 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(v_MACADDR_t));
1342 acl_entry++;
1343 }
1344 //Uapsd Enabled Bit
1345 pConfig->UapsdEnable = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1346 //Enable OBSS protection
1347 pConfig->obssProtEnabled = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1348 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->apDisableIntraBssFwd = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apDisableIntraBssFwd;
1349
1350 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1351 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1352 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int, (int)pConfig->channel);
1353 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1354 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy, pConfig->authType);
1355 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1356 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1357 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),pConfig->protEnabled, pConfig->obssProtEnabled);
1358 hddLog(LOGW,FL("DisableIntraBssFwd = %d\n"),(WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->apDisableIntraBssFwd);
1359
1360 pSapEventCallback = hdd_hostapd_SAPEventCB;
1361 pConfig->persona = pHostapdAdapter->device_mode;
1362 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,(v_PVOID_t)dev) != VOS_STATUS_SUCCESS)
1363 {
1364 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1365 }
1366
1367 kfree(pConfig);
1368
1369 hddLog(LOG1, FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1370 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1371
1372 if (!VOS_IS_STATUS_SUCCESS(vos_status))
1373 {
1374 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos wait for single_event failed!!\n"));
1375 VOS_ASSERT(0);
1376 }
1377
1378 pHostapdState->bCommit = TRUE;
1379 if(pHostapdState->vosStatus)
1380 {
1381 return -1;
1382 }
1383 else
1384 {
1385 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1386 WLANSAP_Update_WpsIe ( pVosContext );
1387 return 0;
1388 }
1389}
1390static
1391int iw_softap_setmlme(struct net_device *dev,
1392 struct iw_request_info *info,
1393 union iwreq_data *wrqu, char *extra)
1394{
1395 struct sQcSapreq_mlme *pmlme;
1396 hdd_adapter_t *pHostapdAdapter = (hdd_adapter_t*)(netdev_priv(dev));
1397 v_MACADDR_t destAddress;
1398 pmlme = (struct sQcSapreq_mlme *)(wrqu->name);
1399 /* NOTE: this address is not valid incase of TKIP failure, since not filled */
1400 vos_mem_copy(&destAddress.bytes, pmlme->im_macaddr, sizeof(v_MACADDR_t));
1401 switch(pmlme->im_op)
1402 {
1403 case QCSAP_MLME_AUTHORIZE:
1404 hdd_softap_change_STA_state( pHostapdAdapter, &destAddress, WLANTL_STA_AUTHENTICATED);
1405 break;
1406 case QCSAP_MLME_ASSOC:
1407 //TODO:inform to TL after associating (not needed as we do in sapCallback)
1408 break;
1409 case QCSAP_MLME_UNAUTHORIZE:
1410 //TODO: send the disassoc to station
1411 //hdd_softap_change_STA_state( pHostapdAdapter, pmlme->im_macaddr, WLANTL_STA_AUTHENTICATED);
1412 break;
1413 case QCSAP_MLME_DISASSOC:
1414 hdd_softap_sta_disassoc(pHostapdAdapter,pmlme->im_macaddr);
1415 break;
1416 case QCSAP_MLME_DEAUTH:
1417 hdd_softap_sta_deauth(pHostapdAdapter,pmlme->im_macaddr);
1418 break;
1419 case QCSAP_MLME_MICFAILURE:
1420 hdd_softap_tkip_mic_fail_counter_measure(pHostapdAdapter,pmlme->im_reason);
1421 break;
1422 default:
1423 break;
1424 }
1425 return 0;
1426}
1427
1428static int iw_softap_set_channel_range(struct net_device *dev,
1429 struct iw_request_info *info,
1430 union iwreq_data *wrqu, char *extra)
1431{
1432 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1433 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1434
1435 int *value = (int *)extra;
1436 int startChannel = value[0];
1437 int endChannel = value[1];
1438 int band = value[2];
Jeff Johnson43971f52012-07-17 12:26:56 -07001439 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07001440 int ret = 0; /* success */
1441
1442 status = WLANSAP_SetChannelRange(hHal,startChannel,endChannel,band);
1443 if(status != VOS_STATUS_SUCCESS)
1444 {
1445 hddLog( LOGE, FL("iw_softap_set_channel_range: startChannel = %d, endChannel = %d band = %d\n"),
1446 startChannel,endChannel, band);
1447 ret = -EINVAL;
1448 }
1449 return ret;
1450}
1451
1452int iw_softap_get_channel_list(struct net_device *dev,
1453 struct iw_request_info *info,
1454 union iwreq_data *wrqu, char *extra)
1455{
1456 v_U32_t num_channels = 0;
1457 v_U8_t i = 0;
1458 v_U8_t bandStartChannel = RF_CHAN_1;
1459 v_U8_t bandEndChannel = RF_CHAN_165;
1460 v_U32_t temp_num_channels = 0;
1461 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1462 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1463 v_REGDOMAIN_t domainIdCurrentSoftap;
1464
1465 tpChannelListInfo channel_list = (tpChannelListInfo) extra;
1466 wrqu->data.length = sizeof(tChannelListInfo);
1467 ENTER();
1468
1469 for( i = bandStartChannel; i <= bandEndChannel; i++ )
1470 {
1471 if( NV_CHANNEL_ENABLE == regChannels[i].enabled )
1472 {
1473 channel_list->channels[num_channels] = rfChannels[i].channelNum;
1474 num_channels++;
1475 }
1476 }
1477
1478 /* remove indoor channels if the domain is FCC, channels 36 - 48 */
1479
1480 temp_num_channels = num_channels;
1481
1482 if(eHAL_STATUS_SUCCESS != sme_getSoftApDomain(hHal,(v_REGDOMAIN_t *) &domainIdCurrentSoftap))
1483 {
1484 hddLog(LOG1,FL("Failed to get Domain ID, %d \n"),domainIdCurrentSoftap);
1485 return -1;
1486 }
1487
1488 if(REGDOMAIN_FCC == domainIdCurrentSoftap)
1489 {
1490 for(i = 0; i < temp_num_channels; i++)
1491 {
1492
1493 if((channel_list->channels[i] > 35) &&
1494 (channel_list->channels[i] < 49))
1495 {
1496 vos_mem_move(&channel_list->channels[i],
1497 &channel_list->channels[i+1],
1498 temp_num_channels - (i-1));
1499 num_channels--;
1500 temp_num_channels--;
1501 i--;
1502 }
1503 }
1504 }
1505
1506 hddLog(LOG1,FL(" number of channels %d\n"), num_channels);
1507
1508 if (num_channels > IW_MAX_FREQUENCIES)
1509 {
1510 num_channels = IW_MAX_FREQUENCIES;
1511 }
1512
1513 channel_list->num_channels = num_channels;
1514 EXIT();
1515
1516 return 0;
1517}
1518
1519static
1520int iw_get_genie(struct net_device *dev,
1521 struct iw_request_info *info,
1522 union iwreq_data *wrqu, char *extra)
1523{
1524 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1525 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1526 eHalStatus status;
1527 v_U32_t length = DOT11F_IE_RSN_MAX_LEN;
1528 v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN];
1529 ENTER();
1530 hddLog(LOG1,FL("getGEN_IE ioctl\n"));
1531 // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.)
1532 status = WLANSap_getstationIE_information(pVosContext,
1533 &length,
1534 genIeBytes);
1535 wrqu->data.length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN);
1536 vos_mem_copy( wrqu->data.pointer, (v_VOID_t*)genIeBytes, wrqu->data.length);
1537
1538 hddLog(LOG1,FL(" RSN IE of %d bytes returned\n"), wrqu->data.length );
1539
1540
1541 EXIT();
1542 return 0;
1543}
1544static
1545int iw_get_WPSPBCProbeReqIEs(struct net_device *dev,
1546 struct iw_request_info *info,
1547 union iwreq_data *wrqu, char *extra)
1548{
1549 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1550 sQcSapreq_WPSPBCProbeReqIES_t *pWPSPBCProbeReqIEs;
1551 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
1552 ENTER();
1553
1554 hddLog(LOG1,FL("get_WPSPBCProbeReqIEs ioctl\n"));
1555
1556 pWPSPBCProbeReqIEs = (sQcSapreq_WPSPBCProbeReqIES_t *)(wrqu->data.pointer);
1557 pWPSPBCProbeReqIEs->probeReqIELen = pHddApCtx->WPSPBCProbeReq.probeReqIELen;
1558 vos_mem_copy(pWPSPBCProbeReqIEs->probeReqIE, pHddApCtx->WPSPBCProbeReq.probeReqIE, pWPSPBCProbeReqIEs->probeReqIELen);
1559 vos_mem_copy(pWPSPBCProbeReqIEs->macaddr, pHddApCtx->WPSPBCProbeReq.peerMacAddr, sizeof(v_MACADDR_t));
1560 wrqu->data.length = 12 + pWPSPBCProbeReqIEs->probeReqIELen;
1561 hddLog(LOG1, FL("Macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pWPSPBCProbeReqIEs->macaddr));
1562 up(&pHddApCtx->semWpsPBCOverlapInd);
1563 EXIT();
1564 return 0;
1565}
1566
1567/**---------------------------------------------------------------------------
1568
1569 \brief iw_set_auth_hostap() -
1570 This function sets the auth type received from the wpa_supplicant.
1571
1572 \param - dev - Pointer to the net device.
1573 - info - Pointer to the iw_request_info.
1574 - wrqu - Pointer to the iwreq_data.
1575 - extra - Pointer to the data.
1576 \return - 0 for success, non zero for failure
1577
1578 --------------------------------------------------------------------------*/
1579int iw_set_auth_hostap(struct net_device *dev,struct iw_request_info *info,
1580 union iwreq_data *wrqu,char *extra)
1581{
1582 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1583 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1584
1585 ENTER();
1586 switch(wrqu->param.flags & IW_AUTH_INDEX)
1587 {
1588 case IW_AUTH_TKIP_COUNTERMEASURES:
1589 {
1590 if(wrqu->param.value) {
1591 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1592 "Counter Measure started %d", wrqu->param.value);
1593 pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STARTED;
1594 }
1595 else {
1596 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1597 "Counter Measure stopped=%d", wrqu->param.value);
1598 pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STOPED;
1599 }
1600
1601 hdd_softap_tkip_mic_fail_counter_measure(pAdapter,
1602 wrqu->param.value);
1603 }
1604 break;
1605
1606 default:
1607
1608 hddLog(LOGW, "%s called with unsupported auth type %d", __FUNCTION__,
1609 wrqu->param.flags & IW_AUTH_INDEX);
1610 break;
1611 }
1612
1613 EXIT();
1614 return 0;
1615}
1616
1617static int iw_set_ap_encodeext(struct net_device *dev,
1618 struct iw_request_info *info,
1619 union iwreq_data *wrqu, char *extra)
1620{
1621 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1622 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1623 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
Jeff Johnson43971f52012-07-17 12:26:56 -07001624 int retval = 0;
1625 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07001626 struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
1627 v_U8_t groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
1628 int key_index;
1629 struct iw_point *encoding = &wrqu->encoding;
1630 tCsrRoamSetKey setKey;
1631// tCsrRoamRemoveKey RemoveKey;
1632 int i;
Jeff Johnson43971f52012-07-17 12:26:56 -07001633
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 ENTER();
1635
1636 key_index = encoding->flags & IW_ENCODE_INDEX;
1637
1638 if(key_index > 0) {
1639
1640 /*Convert from 1-based to 0-based keying*/
1641 key_index--;
1642 }
1643 if(!ext->key_len) {
1644#if 0
1645 /*Set the encrytion type to NONE*/
1646#if 0
1647 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
1648#endif
1649
1650 RemoveKey.keyId = key_index;
1651 if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1652 /*Key direction for group is RX only*/
1653 vos_mem_copy(RemoveKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
1654 }
1655 else {
1656 vos_mem_copy(RemoveKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
1657 }
1658 switch(ext->alg)
1659 {
1660 case IW_ENCODE_ALG_NONE:
1661 RemoveKey.encType = eCSR_ENCRYPT_TYPE_NONE;
1662 break;
1663 case IW_ENCODE_ALG_WEP:
1664 RemoveKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104;
1665 break;
1666 case IW_ENCODE_ALG_TKIP:
1667 RemoveKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
Jeff Johnson43971f52012-07-17 12:26:56 -07001668 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07001669 case IW_ENCODE_ALG_CCMP:
1670 RemoveKey.encType = eCSR_ENCRYPT_TYPE_AES;
1671 break;
1672 default:
1673 RemoveKey.encType = eCSR_ENCRYPT_TYPE_NONE;
1674 break;
1675 }
1676 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Remove key cipher_alg:%d key_len%d *pEncryptionType :%d \n",
1677 __FUNCTION__,(int)ext->alg,(int)ext->key_len,RemoveKey.encType);
1678 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Peer Mac = "MAC_ADDRESS_STR"\n",
1679 __FUNCTION__, MAC_ADDR_ARRAY(RemoveKey.peerMac));
1680 );
Jeff Johnson43971f52012-07-17 12:26:56 -07001681 vstatus = WLANSAP_DelKeySta( pVosContext, &RemoveKey);
1682 if ( vstatus != VOS_STATUS_SUCCESS )
Jeff Johnson295189b2012-06-20 16:38:30 -07001683 {
1684 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "[%4d] WLANSAP_DeleteKeysSta returned ERROR status= %d",
Jeff Johnson43971f52012-07-17 12:26:56 -07001685 __LINE__, vstatus );
1686 retval = -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001687 }
Jeff Johnson43971f52012-07-17 12:26:56 -07001688#endif
1689 return retval;
Jeff Johnson295189b2012-06-20 16:38:30 -07001690
Jeff Johnson43971f52012-07-17 12:26:56 -07001691 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001692
1693 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
1694
1695 setKey.keyId = key_index;
1696 setKey.keyLength = ext->key_len;
1697
1698 if(ext->key_len <= CSR_MAX_KEY_LEN) {
1699 vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len);
1700 }
1701
1702 if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1703 /*Key direction for group is RX only*/
1704 setKey.keyDirection = eSIR_RX_ONLY;
1705 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
1706 }
1707 else {
1708
1709 setKey.keyDirection = eSIR_TX_RX;
1710 vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
1711 }
1712 if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1713 {
1714 setKey.keyDirection = eSIR_TX_DEFAULT;
1715 vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
1716 }
1717
1718 /*For supplicant pae role is zero*/
1719 setKey.paeRole = 0;
1720
1721 switch(ext->alg)
1722 {
1723 case IW_ENCODE_ALG_NONE:
1724 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
1725 break;
1726
1727 case IW_ENCODE_ALG_WEP:
1728 setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104;
1729 pHddApCtx->uPrivacy = 1;
1730 hddLog(LOG1, "(%s) uPrivacy=%d", __FUNCTION__, pHddApCtx->uPrivacy);
1731 break;
1732
1733 case IW_ENCODE_ALG_TKIP:
1734 {
1735 v_U8_t *pKey = &setKey.Key[0];
1736
1737 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
1738
1739 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
1740
1741 /*Supplicant sends the 32bytes key in this order
1742
1743 |--------------|----------|----------|
1744 | Tk1 |TX-MIC | RX Mic |
1745 |--------------|----------|----------|
1746 <---16bytes---><--8bytes--><--8bytes-->
1747
1748 */
1749 /*Sme expects the 32 bytes key to be in the below order
1750
1751 |--------------|----------|----------|
1752 | Tk1 |RX-MIC | TX Mic |
1753 |--------------|----------|----------|
1754 <---16bytes---><--8bytes--><--8bytes-->
1755 */
1756 /* Copy the Temporal Key 1 (TK1) */
1757 vos_mem_copy(pKey,ext->key,16);
1758
1759 /*Copy the rx mic first*/
1760 vos_mem_copy(&pKey[16],&ext->key[24],8);
1761
1762 /*Copy the tx mic */
1763 vos_mem_copy(&pKey[24],&ext->key[16],8);
1764
1765 }
1766 break;
1767
1768 case IW_ENCODE_ALG_CCMP:
1769 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
1770 break;
1771
1772 default:
1773 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
1774 break;
1775 }
1776
1777 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1778 ("%s:EncryptionType:%d key_len:%d, :%d, KeyId:%d \n"),__FUNCTION__, setKey.encType, setKey.keyLength,
1779 setKey.keyId);
1780 for(i=0; i< ext->key_len; i++)
1781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1782 ("%02x"), setKey.Key[i]);
1783 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1784 ("\n"));
Jeff Johnson43971f52012-07-17 12:26:56 -07001785
1786 vstatus = WLANSAP_SetKeySta( pVosContext, &setKey);
1787 if ( vstatus != VOS_STATUS_SUCCESS )
Jeff Johnson295189b2012-06-20 16:38:30 -07001788 {
1789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson43971f52012-07-17 12:26:56 -07001790 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d", __LINE__, vstatus );
1791 retval = -EINVAL;
1792 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001793
Jeff Johnson43971f52012-07-17 12:26:56 -07001794 return retval;
Jeff Johnson295189b2012-06-20 16:38:30 -07001795}
Jeff Johnson43971f52012-07-17 12:26:56 -07001796
1797
Jeff Johnson295189b2012-06-20 16:38:30 -07001798static int iw_set_ap_mlme(struct net_device *dev,
1799 struct iw_request_info *info,
1800 union iwreq_data *wrqu,
1801 char *extra)
1802{
1803#if 0
1804 hdd_adapter_t *pAdapter = (netdev_priv(dev));
1805 struct iw_mlme *mlme = (struct iw_mlme *)extra;
1806
1807 ENTER();
1808
1809 //reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED
1810 switch (mlme->cmd) {
1811 case IW_MLME_DISASSOC:
1812 case IW_MLME_DEAUTH:
1813 hddLog(LOG1, "Station disassociate");
1814 if( pAdapter->conn_info.connState == eConnectionState_Associated )
1815 {
1816 eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED;
1817
1818 if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE )
1819 reason = eCSR_DISCONNECT_REASON_MIC_ERROR;
1820
1821 status = sme_RoamDisconnect( pAdapter->hHal,pAdapter->sessionId, reason);
1822
1823 //clear all the reason codes
1824 if (status != 0)
1825 {
1826 hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d \n", __FUNCTION__, (int)mlme->cmd, (int)status );
1827 }
1828
1829 netif_stop_queue(dev);
1830 netif_carrier_off(dev);
1831 }
1832 else
1833 {
1834 hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state \n", __FUNCTION__, (int)mlme->cmd );
1835 }
1836 default:
1837 hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate \n", __FUNCTION__, (int)mlme->cmd );
1838 return -EINVAL;
1839 }//end of switch
1840 EXIT();
1841#endif
1842 return 0;
1843// return status;
1844}
1845
1846static int iw_get_ap_rts_threshold(struct net_device *dev,
1847 struct iw_request_info *info,
1848 union iwreq_data *wrqu, char *extra)
1849{
1850 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1851 v_U32_t status = 0;
1852
1853 status = hdd_wlan_get_rts_threshold(pHostapdAdapter, wrqu);
1854
1855 return status;
1856}
1857
1858static int iw_get_ap_frag_threshold(struct net_device *dev,
1859 struct iw_request_info *info,
1860 union iwreq_data *wrqu, char *extra)
1861{
1862 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1863 v_U32_t status = 0;
1864
1865 status = hdd_wlan_get_frag_threshold(pHostapdAdapter, wrqu);
1866
1867 return status;
1868}
1869
1870static int iw_get_ap_freq(struct net_device *dev, struct iw_request_info *info,
1871 struct iw_freq *fwrq, char *extra)
1872{
Jeff Johnsone7245742012-09-05 17:12:55 -07001873 v_U32_t status = FALSE, channel = 0, freq = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001874 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1875 tHalHandle hHal;
1876 hdd_hostapd_state_t *pHostapdState;
Jeff Johnsone7245742012-09-05 17:12:55 -07001877 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001878
1879 ENTER();
1880
1881 if ((WLAN_HDD_GET_CTX(pHostapdAdapter))->isLogpInProgress) {
1882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1883 "%s:LOGP in Progress. Ignore!!!",__func__);
1884 return status;
1885 }
1886
1887 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1888 hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1889
1890 if(pHostapdState->bssState == BSS_STOP )
1891 {
1892 if (ccmCfgGetInt(hHal, WNI_CFG_CURRENT_CHANNEL, &channel)
1893 != eHAL_STATUS_SUCCESS)
1894 {
1895 return -EIO;
1896 }
1897 else
1898 {
1899 status = hdd_wlan_get_freq(channel, &freq);
Jeff Johnsone7245742012-09-05 17:12:55 -07001900 if( TRUE == status)
1901 {
1902 /* Set Exponent parameter as 6 (MHZ) in struct iw_freq
1903 * iwlist & iwconfig command shows frequency into proper
1904 * format (2.412 GHz instead of 246.2 MHz)*/
1905 fwrq->m = freq;
1906 fwrq->e = MHZ;
1907 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001908 }
1909 }
1910 else
1911 {
1912 channel = pHddApCtx->operatingChannel;
1913 status = hdd_wlan_get_freq(channel, &freq);
Jeff Johnsone7245742012-09-05 17:12:55 -07001914 if( TRUE == status)
1915 {
1916 /* Set Exponent parameter as 6 (MHZ) in struct iw_freq
1917 * iwlist & iwconfig command shows frequency into proper
1918 * format (2.412 GHz instead of 246.2 MHz)*/
1919 fwrq->m = freq;
1920 fwrq->e = MHZ;
1921 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001923 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001924}
1925
1926static int iw_softap_setwpsie(struct net_device *dev,
1927 struct iw_request_info *info,
1928 union iwreq_data *wrqu,
1929 char *extra)
1930{
1931 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
1932 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1933 hdd_hostapd_state_t *pHostapdState;
1934 eHalStatus halStatus= eHAL_STATUS_SUCCESS;
1935 u_int8_t *wps_genie = wrqu->data.pointer;
1936 u_int8_t *pos;
1937 tpSap_WPSIE pSap_WPSIe;
1938 u_int8_t WPSIeType;
1939 u_int16_t length;
1940 ENTER();
1941
1942 if(!wrqu->data.length)
1943 return 0;
1944
1945 pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE));
1946 if (NULL == pSap_WPSIe)
1947 {
1948 hddLog(LOGE, "VOS unable to allocate memory\n");
1949 return -ENOMEM;
1950 }
1951 vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE));
1952
1953 hddLog(LOG1,"%s WPS IE type[0x%X] IE[0x%X], LEN[%d]\n", __FUNCTION__, wps_genie[0], wps_genie[1], wps_genie[2]);
1954 WPSIeType = wps_genie[0];
1955 if ( wps_genie[0] == eQC_WPS_BEACON_IE)
1956 {
1957 pSap_WPSIe->sapWPSIECode = eSAP_WPS_BEACON_IE;
1958 wps_genie = wps_genie + 1;
1959 switch ( wps_genie[0] )
1960 {
1961 case DOT11F_EID_WPA:
1962 if (wps_genie[1] < 2 + 4)
1963 {
1964 vos_mem_free(pSap_WPSIe);
1965 return -EINVAL;
1966 }
1967 else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0)
1968 {
1969 hddLog (LOG1, "%s Set WPS BEACON IE(len %d)",__FUNCTION__, wps_genie[1]+2);
1970 pos = &wps_genie[6];
1971 while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) )
1972 {
1973 switch((u_int16_t)(*pos<<8) | *(pos+1))
1974 {
1975 case HDD_WPS_ELEM_VERSION:
1976 pos += 4;
1977 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version = *pos;
1978 hddLog(LOG1, "WPS version %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version);
1979 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_VER_PRESENT;
1980 pos += 1;
1981 break;
1982
1983 case HDD_WPS_ELEM_WPS_STATE:
1984 pos +=4;
1985 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState = *pos;
1986 hddLog(LOG1, "WPS State %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState);
1987 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_STATE_PRESENT;
1988 pos += 1;
1989 break;
1990 case HDD_WPS_ELEM_APSETUPLOCK:
1991 pos += 4;
1992 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked = *pos;
1993 hddLog(LOG1, "AP setup lock %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked);
1994 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_APSETUPLOCK_PRESENT;
1995 pos += 1;
1996 break;
1997 case HDD_WPS_ELEM_SELECTEDREGISTRA:
1998 pos += 4;
1999 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra = *pos;
2000 hddLog(LOG1, "Selected Registra %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra);
2001 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRA_PRESENT;
2002 pos += 1;
2003 break;
2004 case HDD_WPS_ELEM_DEVICE_PASSWORD_ID:
2005 pos += 4;
2006 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID = (*pos<<8) | *(pos+1);
2007 hddLog(LOG1, "Password ID: %x\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID);
2008 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_DEVICEPASSWORDID_PRESENT;
2009 pos += 2;
2010 break;
2011 case HDD_WPS_ELEM_REGISTRA_CONF_METHODS:
2012 pos += 4;
2013 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1);
2014 hddLog(LOG1, "Select Registra Config Methods: %x\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod);
2015 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT;
2016 pos += 2;
2017 break;
2018
2019 case HDD_WPS_ELEM_UUID_E:
2020 pos += 2;
2021 length = *pos<<8 | *(pos+1);
2022 pos += 2;
2023 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length);
2024 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT;
2025 pos += length;
2026 break;
2027 case HDD_WPS_ELEM_RF_BANDS:
2028 pos += 4;
2029 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand = *pos;
2030 hddLog(LOG1, "RF band: %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand);
2031 pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_RF_BANDS_PRESENT;
2032 pos += 1;
2033 break;
2034
2035 default:
2036 hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)\n", (*pos<<8 | *(pos+1)));
2037 vos_mem_free(pSap_WPSIe);
2038 return -EINVAL;
2039 }
2040 }
2041 }
2042 else {
2043 hddLog (LOGE, "%s WPS IE Mismatch %X",
2044 __FUNCTION__, wps_genie[0]);
2045 }
2046 break;
2047
2048 default:
2049 hddLog (LOGE, "%s Set UNKNOWN IE %X",__FUNCTION__, wps_genie[0]);
2050 vos_mem_free(pSap_WPSIe);
2051 return 0;
2052 }
2053 }
2054 else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE)
2055 {
2056 pSap_WPSIe->sapWPSIECode = eSAP_WPS_PROBE_RSP_IE;
2057 wps_genie = wps_genie + 1;
2058 switch ( wps_genie[0] )
2059 {
2060 case DOT11F_EID_WPA:
2061 if (wps_genie[1] < 2 + 4)
2062 {
2063 vos_mem_free(pSap_WPSIe);
2064 return -EINVAL;
2065 }
2066 else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0)
2067 {
2068 hddLog (LOG1, "%s Set WPS PROBE RSP IE(len %d)",__FUNCTION__, wps_genie[1]+2);
2069 pos = &wps_genie[6];
2070 while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) )
2071 {
2072 switch((u_int16_t)(*pos<<8) | *(pos+1))
2073 {
2074 case HDD_WPS_ELEM_VERSION:
2075 pos += 4;
2076 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version = *pos;
2077 hddLog(LOG1, "WPS version %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version);
2078 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_VER_PRESENT;
2079 pos += 1;
2080 break;
2081
2082 case HDD_WPS_ELEM_WPS_STATE:
2083 pos +=4;
2084 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState = *pos;
2085 hddLog(LOG1, "WPS State %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState);
2086 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_STATE_PRESENT;
2087 pos += 1;
2088 break;
2089 case HDD_WPS_ELEM_APSETUPLOCK:
2090 pos += 4;
2091 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked = *pos;
2092 hddLog(LOG1, "AP setup lock %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked);
2093 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_APSETUPLOCK_PRESENT;
2094 pos += 1;
2095 break;
2096 case HDD_WPS_ELEM_SELECTEDREGISTRA:
2097 pos += 4;
2098 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra = *pos;
2099 hddLog(LOG1, "Selected Registra %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra);
2100 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRA_PRESENT;
2101 pos += 1;
2102 break;
2103 case HDD_WPS_ELEM_DEVICE_PASSWORD_ID:
2104 pos += 4;
2105 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID = (*pos<<8) | *(pos+1);
2106 hddLog(LOG1, "Password ID: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID);
2107 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICEPASSWORDID_PRESENT;
2108 pos += 2;
2109 break;
2110 case HDD_WPS_ELEM_REGISTRA_CONF_METHODS:
2111 pos += 4;
2112 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1);
2113 hddLog(LOG1, "Select Registra Config Methods: %x\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod);
2114 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT;
2115 pos += 2;
2116 break;
2117 case HDD_WPS_ELEM_RSP_TYPE:
2118 pos += 4;
2119 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType = *pos;
2120 hddLog(LOG1, "Config Methods: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType);
2121 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RESPONSETYPE_PRESENT;
2122 pos += 1;
2123 break;
2124 case HDD_WPS_ELEM_UUID_E:
2125 pos += 2;
2126 length = *pos<<8 | *(pos+1);
2127 pos += 2;
2128 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length);
2129 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT;
2130 pos += length;
2131 break;
2132
2133 case HDD_WPS_ELEM_MANUFACTURER:
2134 pos += 2;
2135 length = *pos<<8 | *(pos+1);
2136 pos += 2;
2137 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length;
2138 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length);
2139 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT;
2140 pos += length;
2141 break;
2142
2143 case HDD_WPS_ELEM_MODEL_NAME:
2144 pos += 2;
2145 length = *pos<<8 | *(pos+1);
2146 pos += 2;
2147 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length;
2148 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length);
2149 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT;
2150 pos += length;
2151 break;
2152 case HDD_WPS_ELEM_MODEL_NUM:
2153 pos += 2;
2154 length = *pos<<8 | *(pos+1);
2155 pos += 2;
2156 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length;
2157 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length);
2158 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT;
2159 pos += length;
2160 break;
2161 case HDD_WPS_ELEM_SERIAL_NUM:
2162 pos += 2;
2163 length = *pos<<8 | *(pos+1);
2164 pos += 2;
2165 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length;
2166 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length);
2167 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT;
2168 pos += length;
2169 break;
2170 case HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE:
2171 pos += 4;
2172 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory = (*pos<<8 | *(pos+1));
2173 hddLog(LOG1, "primary dev category: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory);
2174 pos += 2;
2175
2176 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceOUI, pos, HDD_WPS_DEVICE_OUI_LEN);
2177 hddLog(LOG1, "primary dev oui: %02x, %02x, %02x, %02x\n", pos[0], pos[1], pos[2], pos[3]);
2178 pos += 4;
2179 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory = (*pos<<8 | *(pos+1));
2180 hddLog(LOG1, "primary dev sub category: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory);
2181 pos += 2;
2182 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT;
2183 break;
2184 case HDD_WPS_ELEM_DEVICE_NAME:
2185 pos += 2;
2186 length = *pos<<8 | *(pos+1);
2187 pos += 2;
2188 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length;
2189 vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length);
2190 pos += length;
2191 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICENAME_PRESENT;
2192 break;
2193 case HDD_WPS_ELEM_CONFIG_METHODS:
2194 pos += 4;
2195 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ConfigMethod = (*pos<<8) | *(pos+1);
2196 hddLog(LOG1, "Config Methods: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod);
2197 pos += 2;
2198 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_CONFIGMETHODS_PRESENT;
2199 break;
2200
2201 case HDD_WPS_ELEM_RF_BANDS:
2202 pos += 4;
2203 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand = *pos;
2204 hddLog(LOG1, "RF band: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand);
2205 pos += 1;
2206 pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RF_BANDS_PRESENT;
2207 break;
2208 } // switch
2209 }
2210 }
2211 else
2212 {
2213 hddLog (LOGE, "%s WPS IE Mismatch %X",__FUNCTION__, wps_genie[0]);
2214 }
2215
2216 } // switch
2217 }
2218 halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe);
2219 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
2220 if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE)
2221 {
2222 //hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
2223 //v_CONTEXT_t pVosContext = pHostapdAdapter->pvosContext;
2224 WLANSAP_Update_WpsIe ( pVosContext );
2225 }
2226
2227 vos_mem_free(pSap_WPSIe);
2228 EXIT();
2229 return halStatus;
2230}
2231
2232static int iw_softap_stopbss(struct net_device *dev,
2233 struct iw_request_info *info,
2234 union iwreq_data *wrqu,
2235 char *extra)
2236{
2237 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
2238 VOS_STATUS status = VOS_STATUS_SUCCESS;
2239 ENTER();
2240 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
2241 {
2242 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext) ) )
2243 {
2244 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
2245
2246 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2247
2248 if (!VOS_IS_STATUS_SUCCESS(status))
2249 {
2250 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2251 ("ERROR: HDD vos wait for single_event failed!!\n"));
2252 VOS_ASSERT(0);
2253 }
2254 }
2255 clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2256 }
2257 EXIT();
2258 return (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY;
2259}
2260
2261static int iw_softap_version(struct net_device *dev,
2262 struct iw_request_info *info,
2263 union iwreq_data *wrqu,
2264 char *extra)
2265{
2266#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2267 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
2268 VOS_STATUS status;
2269 ENTER();
2270 status = hdd_wlan_get_version(pHostapdAdapter, wrqu, extra);
2271 if ( !VOS_IS_STATUS_SUCCESS( status ) ) {
2272 hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!\n",__func__);
2273 return -EINVAL;
2274 }
2275 EXIT();
2276#endif//TODO need to handle in prima
2277 return 0;
2278}
2279static int iw_set_ap_genie(struct net_device *dev,
2280 struct iw_request_info *info,
2281 union iwreq_data *wrqu,
2282 char *extra)
2283{
2284
2285 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
2286 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
2287 eHalStatus halStatus= eHAL_STATUS_SUCCESS;
2288 u_int8_t *genie = wrqu->data.pointer;
2289
2290 ENTER();
2291
2292 if(!wrqu->data.length)
2293 {
2294 EXIT();
2295 return 0;
2296 }
2297
2298 switch (genie[0])
2299 {
2300 case DOT11F_EID_WPA:
2301 case DOT11F_EID_RSN:
2302 if((WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy == 0)
2303 {
2304 hdd_softap_Deregister_BC_STA(pHostapdAdapter);
2305 hdd_softap_Register_BC_STA(pHostapdAdapter, 1);
2306 }
2307 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = 1;
2308 halStatus = WLANSAP_Set_WPARSNIes(pVosContext, wrqu->data.pointer, wrqu->data.length);
2309 break;
2310
2311 default:
2312 hddLog (LOGE, "%s Set UNKNOWN IE %X",__FUNCTION__, genie[0]);
2313 halStatus = 0;
2314 }
2315
2316 EXIT();
2317 return halStatus;
2318}
2319
2320static VOS_STATUS wlan_hdd_get_classAstats_for_station(hdd_adapter_t *pAdapter, u8 staid)
2321{
2322 eHalStatus hstatus;
2323 long lrc;
2324 struct statsContext context;
2325
2326 if (NULL == pAdapter)
2327 {
2328 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Padapter is NULL", __func__);
2329 return VOS_STATUS_E_FAULT;
2330 }
2331
2332 init_completion(&context.completion);
2333 context.pAdapter = pAdapter;
2334 context.magic = STATS_CONTEXT_MAGIC;
2335 hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter),
2336 eCSR_HDD,
2337 SME_GLOBAL_CLASSA_STATS,
2338 hdd_GetClassA_statisticsCB,
2339 0, // not periodic
2340 FALSE, //non-cached results
2341 staid,
2342 &context);
2343 if (eHAL_STATUS_SUCCESS != hstatus)
2344 {
2345 hddLog(VOS_TRACE_LEVEL_ERROR,
2346 "%s: Unable to retrieve statistics for link speed",
2347 __FUNCTION__);
2348 }
2349 else
2350 {
2351 lrc = wait_for_completion_interruptible_timeout(&context.completion,
2352 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
2353 context.magic = 0;
2354 if (lrc <= 0)
2355 {
2356 hddLog(VOS_TRACE_LEVEL_ERROR,
2357 "%s: SME %s while retrieving link speed",
2358 __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
2359 msleep(50);
2360 }
2361 }
2362 return VOS_STATUS_SUCCESS;
2363}
2364
2365int iw_get_softap_linkspeed(struct net_device *dev,
2366 struct iw_request_info *info,
2367 union iwreq_data *wrqu,
2368 char *extra)
2369
2370{
2371 hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
2372 char *pLinkSpeed = (char*)extra;
2373 v_U16_t link_speed;
2374 unsigned short staId;
2375 int len = sizeof(v_U16_t)+1;
2376 v_BYTE_t macAddress[VOS_MAC_ADDR_SIZE];
2377 VOS_STATUS status;
2378 int rc;
2379
2380 if ( hdd_string_to_hex ((char *)wrqu->data.pointer, wrqu->data.length, macAddress ) )
2381 {
2382 hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR: Command not found");
2383 return -EINVAL;
2384 }
2385
2386 status = hdd_softap_GetStaId(pHostapdAdapter, (v_MACADDR_t *)macAddress, (void *)(&staId));
2387
2388 if (!VOS_IS_STATUS_SUCCESS(status ))
2389 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002390 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002391 link_speed = 0;
2392 }
2393 else
2394 {
2395 status = wlan_hdd_get_classAstats_for_station(pHostapdAdapter , staId);
2396 if (!VOS_IS_STATUS_SUCCESS(status ))
2397 {
2398 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve SME statistics", __FUNCTION__);
2399 return -EINVAL;
2400 }
2401 link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2;
2402 }
2403
2404 wrqu->data.length = len;
2405 rc = snprintf(pLinkSpeed, len, "%u", link_speed);
2406 if ((rc < 0) || (rc >= len))
2407 {
2408 // encoding or length error?
2409 hddLog(VOS_TRACE_LEVEL_ERROR,
2410 "%s: Unable to encode link speed, got [%s]",
2411 __FUNCTION__, pLinkSpeed);
2412 return -EIO;
2413 }
2414
2415 return 0;
2416}
2417
2418static const iw_handler hostapd_handler[] =
2419{
2420 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2421 (iw_handler) NULL, /* SIOCGIWNAME */
2422 (iw_handler) NULL, /* SIOCSIWNWID */
2423 (iw_handler) NULL, /* SIOCGIWNWID */
2424 (iw_handler) NULL, /* SIOCSIWFREQ */
2425 (iw_handler) iw_get_ap_freq, /* SIOCGIWFREQ */
2426 (iw_handler) NULL, /* SIOCSIWMODE */
2427 (iw_handler) NULL, /* SIOCGIWMODE */
2428 (iw_handler) NULL, /* SIOCSIWSENS */
2429 (iw_handler) NULL, /* SIOCGIWSENS */
2430 (iw_handler) NULL, /* SIOCSIWRANGE */
2431 (iw_handler) NULL, /* SIOCGIWRANGE */
2432 (iw_handler) NULL, /* SIOCSIWPRIV */
2433 (iw_handler) NULL, /* SIOCGIWPRIV */
2434 (iw_handler) NULL, /* SIOCSIWSTATS */
2435 (iw_handler) NULL, /* SIOCGIWSTATS */
2436 (iw_handler) NULL, /* SIOCSIWSPY */
2437 (iw_handler) NULL, /* SIOCGIWSPY */
2438 (iw_handler) NULL, /* SIOCSIWTHRSPY */
2439 (iw_handler) NULL, /* SIOCGIWTHRSPY */
2440 (iw_handler) NULL, /* SIOCSIWAP */
2441 (iw_handler) NULL, /* SIOCGIWAP */
2442 (iw_handler) iw_set_ap_mlme, /* SIOCSIWMLME */
2443 (iw_handler) NULL, /* SIOCGIWAPLIST */
2444 (iw_handler) NULL, /* SIOCSIWSCAN */
2445 (iw_handler) NULL, /* SIOCGIWSCAN */
2446 (iw_handler) NULL, /* SIOCSIWESSID */
2447 (iw_handler) NULL, /* SIOCGIWESSID */
2448 (iw_handler) NULL, /* SIOCSIWNICKN */
2449 (iw_handler) NULL, /* SIOCGIWNICKN */
2450 (iw_handler) NULL, /* -- hole -- */
2451 (iw_handler) NULL, /* -- hole -- */
2452 (iw_handler) NULL, /* SIOCSIWRATE */
2453 (iw_handler) NULL, /* SIOCGIWRATE */
2454 (iw_handler) NULL, /* SIOCSIWRTS */
2455 (iw_handler) iw_get_ap_rts_threshold, /* SIOCGIWRTS */
2456 (iw_handler) NULL, /* SIOCSIWFRAG */
2457 (iw_handler) iw_get_ap_frag_threshold, /* SIOCGIWFRAG */
2458 (iw_handler) NULL, /* SIOCSIWTXPOW */
2459 (iw_handler) NULL, /* SIOCGIWTXPOW */
2460 (iw_handler) NULL, /* SIOCSIWRETRY */
2461 (iw_handler) NULL, /* SIOCGIWRETRY */
2462 (iw_handler) NULL, /* SIOCSIWENCODE */
2463 (iw_handler) NULL, /* SIOCGIWENCODE */
2464 (iw_handler) NULL, /* SIOCSIWPOWER */
2465 (iw_handler) NULL, /* SIOCGIWPOWER */
2466 (iw_handler) NULL, /* -- hole -- */
2467 (iw_handler) NULL, /* -- hole -- */
2468 (iw_handler) iw_set_ap_genie, /* SIOCSIWGENIE */
2469 (iw_handler) NULL, /* SIOCGIWGENIE */
2470 (iw_handler) iw_set_auth_hostap, /* SIOCSIWAUTH */
2471 (iw_handler) NULL, /* SIOCGIWAUTH */
2472 (iw_handler) iw_set_ap_encodeext, /* SIOCSIWENCODEEXT */
2473 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
2474 (iw_handler) NULL, /* SIOCSIWPMKSA */
2475};
2476
2477#define IW_PRIV_TYPE_OPTIE IW_PRIV_TYPE_BYTE | QCSAP_MAX_OPT_IE
2478#define IW_PRIV_TYPE_MLME \
2479 IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme)
2480
2481static const struct iw_priv_args hostapd_private_args[] = {
2482 { QCSAP_IOCTL_SETPARAM,
2483 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam" },
2484 { QCSAP_IOCTL_SETPARAM,
2485 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
2486 { QCSAP_PARAM_MAX_ASSOC,
2487 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMaxAssoc" },
2488 { QCSAP_PARAM_HIDE_SSID,
2489 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hideSSID" },
2490 { QCSAP_IOCTL_GETPARAM,
2491 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
2492 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" },
2493 { QCSAP_IOCTL_GETPARAM, 0,
2494 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
2495 { QCSAP_PARAM_MAX_ASSOC, 0,
2496 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getMaxAssoc" },
Jeff Johnson43971f52012-07-17 12:26:56 -07002497 { QCSAP_PARAM_GET_WLAN_DBG, 0,
2498 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwlandbg" },
2499 { QCSAP_PARAM_AUTO_CHANNEL, 0,
2500 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getAutoChannel" },
Jeff Johnson295189b2012-06-20 16:38:30 -07002501 { QCSAP_PARAM_MODULE_DOWN_IND, 0,
2502 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "moduleDownInd" },
2503 { QCSAP_PARAM_CLR_ACL, 0,
2504 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "setClearAcl" },
2505 { QCSAP_PARAM_ACL_MODE,
2506 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setAclMode" },
2507 { QCSAP_IOCTL_COMMIT,
2508 IW_PRIV_TYPE_BYTE | sizeof(struct s_CommitConfig) | IW_PRIV_SIZE_FIXED, 0, "commit" },
2509 { QCSAP_IOCTL_SETMLME,
2510 IW_PRIV_TYPE_BYTE | sizeof(struct sQcSapreq_mlme)| IW_PRIV_SIZE_FIXED, 0, "setmlme" },
2511 { QCSAP_IOCTL_GET_STAWPAIE,
2512 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "get_staWPAIE" },
2513 { QCSAP_IOCTL_SETWPAIE,
2514 IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE | IW_PRIV_SIZE_FIXED, 0, "setwpaie" },
2515 { QCSAP_IOCTL_STOPBSS,
2516 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" },
2517 { QCSAP_IOCTL_VERSION, 0,
2518 IW_PRIV_TYPE_CHAR | QCSAP_MAX_WSC_IE, "version" },
2519 { QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES,
2520 IW_PRIV_TYPE_BYTE | sizeof(sQcSapreq_WPSPBCProbeReqIES_t) | IW_PRIV_SIZE_FIXED | 1, 0, "getProbeReqIEs" },
2521 { QCSAP_IOCTL_GET_CHANNEL, 0,
Jeff Johnson43971f52012-07-17 12:26:56 -07002522 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel" },
Jeff Johnson295189b2012-06-20 16:38:30 -07002523 { QCSAP_IOCTL_ASSOC_STA_MACADDR, 0,
2524 IW_PRIV_TYPE_BYTE | /*((WLAN_MAX_STA_COUNT*6)+100)*/1 , "get_assoc_stamac" },
2525 { QCSAP_IOCTL_DISASSOC_STA,
2526 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 6 , 0, "disassoc_sta" },
2527 { QCSAP_IOCTL_AP_STATS,
2528 IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE, 0, "ap_stats" },
2529 { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED,
2530 IW_PRIV_TYPE_CHAR | 18,
2531 IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" },
2532
2533 { QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE,
2534 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" },
2535 /* handlers for sub-ioctl */
2536 { WE_SET_WLAN_DBG,
2537 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
2538 0,
2539 "setwlandbg" },
2540
2541 /* handlers for main ioctl */
2542 { QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE,
2543 IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
2544 0,
2545 "" },
2546
2547 /* handlers for sub-ioctl */
2548 { WE_LOG_DUMP_CMD,
2549 IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
2550 0,
2551 "dump" },
2552#ifdef WLAN_FEATURE_P2P
2553 { WE_P2P_NOA_CMD,
2554 IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
2555 0,
2556 "SetP2pPs" },
2557#endif
2558 /* handlers for main ioctl */
2559 { QCSAP_IOCTL_MODIFY_ACL,
2560 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 8,
2561 0,
2562 "modify_acl" },
2563
2564 /* handlers for main ioctl */
2565 { QCSAP_IOCTL_GET_CHANNEL_LIST,
2566 0,
2567 IW_PRIV_TYPE_BYTE | sizeof(tChannelListInfo),
2568 "getChannelList" },
2569
Jeff Johnsone7245742012-09-05 17:12:55 -07002570 /* handlers for main ioctl */
2571 { QCSAP_IOCTL_SET_TX_POWER,
2572 IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1,
2573 0,
2574 "" },
Jeff Johnson295189b2012-06-20 16:38:30 -07002575};
Jeff Johnsone7245742012-09-05 17:12:55 -07002576
Jeff Johnson295189b2012-06-20 16:38:30 -07002577static const iw_handler hostapd_private[] = {
2578 [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, //set priv ioctl
2579 [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl
2580 [QCSAP_IOCTL_COMMIT - SIOCIWFIRSTPRIV] = iw_softap_commit, //get priv ioctl
2581 [QCSAP_IOCTL_SETMLME - SIOCIWFIRSTPRIV] = iw_softap_setmlme,
2582 [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE
2583 [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie,
2584 [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss
2585 [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version
2586 [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = iw_get_WPSPBCProbeReqIEs,
2587 [QCSAP_IOCTL_GET_CHANNEL - SIOCIWFIRSTPRIV] = iw_softap_getchannel,
2588 [QCSAP_IOCTL_ASSOC_STA_MACADDR - SIOCIWFIRSTPRIV] = iw_softap_getassoc_stamacaddr,
2589 [QCSAP_IOCTL_DISASSOC_STA - SIOCIWFIRSTPRIV] = iw_softap_disassoc_sta,
2590 [QCSAP_IOCTL_AP_STATS - SIOCIWFIRSTPRIV] = iw_softap_ap_stats,
2591 [QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone,
2592 [QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_var_ints_getnone,
2593 [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = iw_softap_set_channel_range,
2594 [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV] = iw_softap_modify_acl,
2595 [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = iw_softap_get_channel_list,
Jeff Johnsone7245742012-09-05 17:12:55 -07002596 [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_softap_linkspeed,
2597 [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_tx_power,
Jeff Johnson295189b2012-06-20 16:38:30 -07002598};
2599const struct iw_handler_def hostapd_handler_def = {
2600 .num_standard = sizeof(hostapd_handler) / sizeof(hostapd_handler[0]),
2601 .num_private = sizeof(hostapd_private) / sizeof(hostapd_private[0]),
2602 .num_private_args = sizeof(hostapd_private_args) / sizeof(hostapd_private_args[0]),
2603 .standard = (iw_handler *)hostapd_handler,
2604 .private = (iw_handler *)hostapd_private,
2605 .private_args = hostapd_private_args,
2606 .get_wireless_stats = NULL,
2607};
2608#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2609struct net_device_ops net_ops_struct = {
2610 .ndo_open = hdd_hostapd_open,
2611 .ndo_stop = hdd_hostapd_stop,
2612 .ndo_uninit = hdd_hostapd_uninit,
2613 .ndo_start_xmit = hdd_softap_hard_start_xmit,
2614 .ndo_tx_timeout = hdd_softap_tx_timeout,
2615 .ndo_get_stats = hdd_softap_stats,
2616 .ndo_set_mac_address = hdd_hostapd_set_mac_address,
2617 .ndo_do_ioctl = hdd_hostapd_ioctl,
2618 .ndo_change_mtu = hdd_hostapd_change_mtu,
2619 .ndo_select_queue = hdd_hostapd_select_queue,
2620 };
2621#endif
2622
2623int hdd_set_hostapd(hdd_adapter_t *pAdapter)
2624{
2625 return VOS_STATUS_SUCCESS;
2626}
2627
2628void hdd_set_ap_ops( struct net_device *pWlanHostapdDev )
2629{
2630#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2631 pWlanHostapdDev->netdev_ops = &net_ops_struct;
2632#else
2633 pWlanHostapdDev->open = hdd_hostapd_open;
2634 pWlanHostapdDev->stop = hdd_hostapd_stop;
2635 pWlanHostapdDev->uninit = hdd_hostapd_uninit;
2636 pWlanHostapdDev->hard_start_xmit = hdd_softap_hard_start_xmit;
2637 pWlanHostapdDev->tx_timeout = hdd_softap_tx_timeout;
2638 pWlanHostapdDev->get_stats = hdd_softap_stats;
2639 pWlanHostapdDev->set_mac_address = hdd_hostapd_set_mac_address;
2640 pWlanHostapdDev->do_ioctl = hdd_hostapd_ioctl;
2641#endif
2642}
2643
2644VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter )
2645{
2646 hdd_hostapd_state_t * phostapdBuf;
2647 struct net_device *dev = pAdapter->dev;
2648 VOS_STATUS status;
2649 ENTER();
2650 // Allocate the Wireless Extensions state structure
2651 phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter );
2652
2653 // Zero the memory. This zeros the profile structure.
2654 memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t));
2655
2656 // Set up the pointer to the Wireless Extensions state structure
2657 // NOP
2658 status = hdd_set_hostapd(pAdapter);
2659 if(!VOS_IS_STATUS_SUCCESS(status)) {
2660 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: hdd_set_hostapd failed!!\n"));
2661 return status;
2662 }
2663
2664 status = vos_event_init(&phostapdBuf->vosEvent);
2665 if (!VOS_IS_STATUS_SUCCESS(status))
2666 {
2667 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!\n"));
2668 return status;
2669 }
2670
2671 init_completion(&pAdapter->session_close_comp_var);
2672 init_completion(&pAdapter->session_open_comp_var);
2673
2674 sema_init(&(WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->semWpsPBCOverlapInd, 1);
2675
2676 // Register as a wireless device
2677 dev->wireless_handlers = (struct iw_handler_def *)& hostapd_handler_def;
2678
2679 //Initialize the data path module
2680 status = hdd_softap_init_tx_rx(pAdapter);
2681 if ( !VOS_IS_STATUS_SUCCESS( status ))
2682 {
2683 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_softap_init_tx_rx failed", __FUNCTION__);
2684 }
2685
2686#ifdef CONFIG_CFG80211
2687 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), pAdapter );
2688#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002689 EXIT();
2690 return status;
2691}
2692
2693hdd_adapter_t* hdd_wlan_create_ap_dev( hdd_context_t *pHddCtx, tSirMacAddr macAddr, tANI_U8 *iface_name )
2694{
2695 struct net_device *pWlanHostapdDev = NULL;
2696 hdd_adapter_t *pHostapdAdapter = NULL;
2697 v_CONTEXT_t pVosContext= NULL;
2698
2699#ifdef CONFIG_CFG80211
2700 pWlanHostapdDev = alloc_netdev_mq(sizeof(hdd_adapter_t), iface_name, ether_setup, NUM_TX_QUEUES);
2701#else
2702 pWlanHostapdDev = alloc_etherdev_mq(sizeof(hdd_adapter_t), NUM_TX_QUEUES);
2703#endif
2704
2705 if (pWlanHostapdDev != NULL)
2706 {
2707 pHostapdAdapter = netdev_priv(pWlanHostapdDev);
2708
2709 //Init the net_device structure
2710 ether_setup(pWlanHostapdDev);
2711
2712 //Initialize the adapter context to zeros.
2713 vos_mem_zero(pHostapdAdapter, sizeof( hdd_adapter_t ));
2714 pHostapdAdapter->dev = pWlanHostapdDev;
2715 pHostapdAdapter->pHddCtx = pHddCtx;
2716 pHostapdAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2717
2718 //Get the Global VOSS context.
2719 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
2720 //Save the adapter context in global context for future.
2721 ((VosContextType*)(pVosContext))->pHDDSoftAPContext = (v_VOID_t*)pHostapdAdapter;
2722
2723 //Init the net_device structure
2724 strlcpy(pWlanHostapdDev->name, (const char *)iface_name, IFNAMSIZ);
2725
2726 hdd_set_ap_ops( pHostapdAdapter->dev );
2727
2728 pWlanHostapdDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2729 pWlanHostapdDev->watchdog_timeo = HDD_TX_TIMEOUT;
2730 pWlanHostapdDev->mtu = HDD_DEFAULT_MTU;
2731
2732 vos_mem_copy(pWlanHostapdDev->dev_addr, (void *)macAddr,sizeof(tSirMacAddr));
2733 vos_mem_copy(pHostapdAdapter->macAddressCurrent.bytes, (void *)macAddr, sizeof(tSirMacAddr));
2734
2735 pWlanHostapdDev->destructor = free_netdev;
2736#ifdef CONFIG_CFG80211
2737 pWlanHostapdDev->ieee80211_ptr = &pHostapdAdapter->wdev ;
2738 pHostapdAdapter->wdev.wiphy = pHddCtx->wiphy;
2739 pHostapdAdapter->wdev.netdev = pWlanHostapdDev;
2740 init_completion(&pHostapdAdapter->tx_action_cnf_event);
2741#endif
2742 init_completion(&pHostapdAdapter->cancel_rem_on_chan_var);
2743 init_completion(&pHostapdAdapter->rem_on_chan_ready_event);
2744#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2745 init_completion(&pHostapdAdapter->offchannel_tx_event);
2746#endif
2747
2748 init_completion(&pHostapdAdapter->scan_info.scan_req_completion_event);
2749
2750 SET_NETDEV_DEV(pWlanHostapdDev, pHddCtx->parent_dev);
2751 }
2752 return pHostapdAdapter;
2753}
2754
2755VOS_STATUS hdd_register_hostapd( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2756{
2757 struct net_device *dev = pAdapter->dev;
2758 VOS_STATUS status = VOS_STATUS_SUCCESS;
2759
2760 ENTER();
2761
2762 if( rtnl_lock_held )
2763 {
2764 if (strchr(dev->name, '%')) {
2765 if( dev_alloc_name(dev, dev->name) < 0 )
2766 {
2767 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:Failed:dev_alloc_name", __func__);
2768 return VOS_STATUS_E_FAILURE;
2769 }
2770 }
2771 if (register_netdevice(dev))
2772 {
2773 hddLog(VOS_TRACE_LEVEL_FATAL,
2774 "%s:Failed:register_netdevice", __func__);
2775 return VOS_STATUS_E_FAILURE;
2776 }
2777 }
2778 else
2779 {
2780 if (register_netdev(dev))
2781 {
2782 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed:register_netdev", __func__);
2783 return VOS_STATUS_E_FAILURE;
2784 }
2785 }
2786 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2787
2788 EXIT();
2789 return status;
2790}
2791
2792VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter)
2793{
2794 ENTER();
2795
2796 hdd_softap_deinit_tx_rx(pAdapter);
2797
2798 /* if we are being called during driver unload, then the dev has already
2799 been invalidated. if we are being called at other times, then we can
2800 detatch the wireless device handlers */
2801 if (pAdapter->dev)
2802 {
2803 pAdapter->dev->wireless_handlers = NULL;
2804 }
2805 EXIT();
2806 return 0;
2807}