Merge tag 'sound-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[cascardo/linux.git] / drivers / staging / csr / sme_wext.c
1 /*
2  * ---------------------------------------------------------------------------
3  * FILE:     sme_wext.c
4  *
5  * PURPOSE:
6  *      Handlers for ioctls from iwconfig.
7  *      These provide the control plane operations.
8  *
9  * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
10  *
11  * Refer to LICENSE.txt included with this source code for details on
12  * the license terms.
13  *
14  * ---------------------------------------------------------------------------
15  */
16 #include <linux/types.h>
17 #include <linux/etherdevice.h>
18 #include <linux/if_arp.h>
19 #include <asm/uaccess.h>
20 #include <linux/ctype.h>
21 #include "unifi_priv.h"
22 #include <linux/rtnetlink.h>
23
24 #define CHECK_INITED(_priv)                             \
25     do {                                                    \
26         if (_priv->init_progress != UNIFI_INIT_COMPLETED) { \
27             unifi_trace(_priv, UDBG2, "%s unifi not ready, failing wext call\n", __FUNCTION__); \
28             return -ENODEV;                                 \
29         }                                                   \
30     } while (0)
31
32 /* Workaround for the wpa_supplicant hanging issue - disabled on Android */
33 #ifndef ANDROID_BUILD
34 #define CSR_WIFI_WEXT_HANG_WORKAROUND
35 #endif
36
37 #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND
38 # define UF_RTNL_LOCK()    rtnl_lock()
39 # define UF_RTNL_UNLOCK()  rtnl_unlock()
40 #else
41 # define UF_RTNL_LOCK()
42 # define UF_RTNL_UNLOCK()
43 #endif
44
45
46 /*
47  * ---------------------------------------------------------------------------
48  *      Helper functions
49  * ---------------------------------------------------------------------------
50  */
51
52 /*
53  * ---------------------------------------------------------------------------
54  *  wext_freq_to_channel
55  *  channel_to_mhz
56  *
57  *      These functions convert between channel number and frequency.
58  *
59  *  Arguments:
60  *      ch      Channel number, as defined in 802.11 specs
61  *      m, e    Mantissa and exponent as provided by wireless extension.
62  *
63  *  Returns:
64  *      channel or frequency (in MHz) value
65  * ---------------------------------------------------------------------------
66  */
67 static int
68 wext_freq_to_channel(int m, int e)
69 {
70     int mhz;
71
72     mhz = m;
73     while (e < 6) {
74         mhz /= 10;
75         e++;
76     }
77     while (e > 6) {
78         mhz *= 10;
79         e--;
80     }
81
82     if (mhz >= 5000) {
83         return ((mhz - 5000) / 5);
84     }
85
86     if (mhz == 2482) {
87         return 14;
88     }
89
90     if (mhz >= 2407) {
91         return ((mhz - 2407) / 5);
92     }
93
94     return 0;
95 } /* wext_freq_to_channel() */
96
97 static int
98 channel_to_mhz(int ch, int dot11a)
99 {
100
101     if (ch == 0) return 0;
102     if (ch > 200) return 0;
103
104     /* 5G */
105     if (dot11a) {
106         return (5000 + (5 * ch));
107     }
108
109     /* 2.4G */
110     if (ch == 14) {
111         return 2484;
112     }
113
114     if ((ch < 14) && (ch > 0)) {
115         return (2407 + (5 * ch));
116     }
117
118     return 0;
119 }
120 #ifdef CSR_SUPPORT_WEXT_AP
121 void uf_sme_wext_ap_set_defaults(unifi_priv_t *priv)
122 {
123     memcpy(priv->ap_config.ssid.ssid,"defaultssid",sizeof("defaultssid"));
124
125     priv->ap_config.ssid.length = 8;
126     priv->ap_config.channel = 6;
127     priv->ap_config.if_index = 1;
128     priv->ap_config.credentials.authType = 0;
129     priv->ap_config.max_connections=8;
130
131     priv->group_sec_config.apGroupkeyTimeout = 0;
132     priv->group_sec_config.apStrictGtkRekey = 0;
133     priv->group_sec_config.apGmkTimeout = 0;
134     priv->group_sec_config.apResponseTimeout = 100; /* Default*/
135     priv->group_sec_config.apRetransLimit = 3; /* Default*/
136     /* Set default params even if they may not be used*/
137     /* Until Here*/
138
139     priv->ap_mac_config.preamble = CSR_WIFI_SME_USE_LONG_PREAMBLE;
140     priv->ap_mac_config.shortSlotTimeEnabled = FALSE;
141     priv->ap_mac_config.ctsProtectionType=CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC;
142
143     priv->ap_mac_config.wmmEnabled = TRUE;
144     priv->ap_mac_config.wmmApParams[0].cwMin=4;
145     priv->ap_mac_config.wmmApParams[0].cwMax=10;
146     priv->ap_mac_config.wmmApParams[0].aifs=3;
147     priv->ap_mac_config.wmmApParams[0].txopLimit=0;
148     priv->ap_mac_config.wmmApParams[0].admissionControlMandatory=FALSE;
149     priv->ap_mac_config.wmmApParams[1].cwMin=4;
150     priv->ap_mac_config.wmmApParams[1].cwMax=10;
151     priv->ap_mac_config.wmmApParams[1].aifs=7;
152     priv->ap_mac_config.wmmApParams[1].txopLimit=0;
153     priv->ap_mac_config.wmmApParams[1].admissionControlMandatory=FALSE;
154     priv->ap_mac_config.wmmApParams[2].cwMin=3;
155     priv->ap_mac_config.wmmApParams[2].cwMax=4;
156     priv->ap_mac_config.wmmApParams[2].aifs=1;
157     priv->ap_mac_config.wmmApParams[2].txopLimit=94;
158     priv->ap_mac_config.wmmApParams[2].admissionControlMandatory=FALSE;
159     priv->ap_mac_config.wmmApParams[3].cwMin=2;
160     priv->ap_mac_config.wmmApParams[3].cwMax=3;
161     priv->ap_mac_config.wmmApParams[3].aifs=1;
162     priv->ap_mac_config.wmmApParams[3].txopLimit=47;
163     priv->ap_mac_config.wmmApParams[3].admissionControlMandatory=FALSE;
164
165     priv->ap_mac_config.wmmApBcParams[0].cwMin=4;
166     priv->ap_mac_config.wmmApBcParams[0].cwMax=10;
167     priv->ap_mac_config.wmmApBcParams[0].aifs=3;
168     priv->ap_mac_config.wmmApBcParams[0].txopLimit=0;
169     priv->ap_mac_config.wmmApBcParams[0].admissionControlMandatory=FALSE;
170     priv->ap_mac_config.wmmApBcParams[1].cwMin=4;
171     priv->ap_mac_config.wmmApBcParams[1].cwMax=10;
172     priv->ap_mac_config.wmmApBcParams[1].aifs=7;
173     priv->ap_mac_config.wmmApBcParams[1].txopLimit=0;
174     priv->ap_mac_config.wmmApBcParams[1].admissionControlMandatory=FALSE;
175     priv->ap_mac_config.wmmApBcParams[2].cwMin=3;
176     priv->ap_mac_config.wmmApBcParams[2].cwMax=4;
177     priv->ap_mac_config.wmmApBcParams[2].aifs=2;
178     priv->ap_mac_config.wmmApBcParams[2].txopLimit=94;
179     priv->ap_mac_config.wmmApBcParams[2].admissionControlMandatory=FALSE;
180     priv->ap_mac_config.wmmApBcParams[3].cwMin=2;
181     priv->ap_mac_config.wmmApBcParams[3].cwMax=3;
182     priv->ap_mac_config.wmmApBcParams[3].aifs=2;
183     priv->ap_mac_config.wmmApBcParams[3].txopLimit=47;
184     priv->ap_mac_config.wmmApBcParams[3].admissionControlMandatory=FALSE;
185
186     priv->ap_mac_config.accessType=CSR_WIFI_AP_ACCESS_TYPE_NONE;
187     priv->ap_mac_config.macAddressListCount=0;
188     priv->ap_mac_config.macAddressList=NULL;
189
190     priv->ap_mac_config.apHtParams.rxStbc=1;
191     priv->ap_mac_config.apHtParams.rifsModeAllowed=TRUE;
192     priv->ap_mac_config.apHtParams.greenfieldSupported=FALSE;
193     priv->ap_mac_config.apHtParams.shortGi20MHz=TRUE;
194     priv->ap_mac_config.apHtParams.htProtection=0;
195     priv->ap_mac_config.apHtParams.dualCtsProtection=FALSE;
196
197     priv->ap_mac_config.phySupportedBitmap =
198             (CSR_WIFI_SME_AP_PHY_SUPPORT_B|CSR_WIFI_SME_AP_PHY_SUPPORT_G|CSR_WIFI_SME_AP_PHY_SUPPORT_N);
199     priv->ap_mac_config.beaconInterval= 100;
200     priv->ap_mac_config.dtimPeriod=3;
201     priv->ap_mac_config.maxListenInterval=0x00ff;/* Set it to a large value
202                                                     to enable different types of
203                                                     devices to join us */
204     priv->ap_mac_config.supportedRatesCount =
205            uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap);
206 }
207 #endif
208 /*
209  * ---------------------------------------------------------------------------
210  *  uf_sme_wext_set_defaults
211  *
212  *      Set up power-on defaults for driver config.
213  *
214  *      Note: The SME Management API *cannot* be used in this function.
215  *
216  *  Arguments:
217  *      priv            Pointer to device private context struct
218  *
219  *  Returns:
220  *      None.
221  * ---------------------------------------------------------------------------
222  */
223 void
224 uf_sme_wext_set_defaults(unifi_priv_t *priv)
225 {
226     memset(&priv->connection_config, 0, sizeof(CsrWifiSmeConnectionConfig));
227
228     priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE;
229     priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
230     priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
231     priv->connection_config.privacyMode = CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
232     priv->connection_config.wmmQosInfo = 0xFF;
233     priv->connection_config.ifIndex = CSR_WIFI_SME_RADIO_IF_BOTH;
234     priv->connection_config.adhocJoinOnly = FALSE;
235     priv->connection_config.adhocChannel = 6;
236
237     priv->wep_tx_key_index = 0;
238
239     priv->wext_wireless_stats.qual.qual = 0;
240     priv->wext_wireless_stats.qual.level = 0;
241     priv->wext_wireless_stats.qual.noise = 0;
242     priv->wext_wireless_stats.qual.updated = 0x70;
243 #ifdef CSR_SUPPORT_WEXT_AP
244     /* Initialize the default configuration for AP */
245     uf_sme_wext_ap_set_defaults(priv);
246 #endif
247
248
249 } /* uf_sme_wext_set_defaults() */
250
251
252 /*
253  * ---------------------------------------------------------------------------
254  *      WEXT methods
255  * ---------------------------------------------------------------------------
256  */
257
258 /*
259  * ---------------------------------------------------------------------------
260  *  unifi_giwname   - handler for SIOCGIWNAME
261  *  unifi_siwfreq   - handler for SIOCSIWFREQ
262  *  unifi_giwfreq   - handler for SIOCGIWFREQ
263  *  unifi_siwmode   - handler for SIOCSIWMODE
264  *  unifi_giwmode   - handler for SIOCGIWMODE
265  *  unifi_giwrange  - handler for SIOCGIWRANGE
266  *  unifi_siwap     - handler for SIOCSIWAP
267  *  unifi_giwap     - handler for SIOCGIWAP
268  *  unifi_siwscan   - handler for SIOCSIWSCAN
269  *  unifi_giwscan   - handler for SIOCGIWSCAN
270  *  unifi_siwessid  - handler for SIOCSIWESSID
271  *  unifi_giwessid  - handler for SIOCGIWESSID
272  *  unifi_siwencode - handler for SIOCSIWENCODE
273  *  unifi_giwencode - handler for SIOCGIWENCODE
274  *
275  *      Handler functions for IW extensions.
276  *      These are registered via the unifi_iw_handler_def struct below
277  *      and called by the generic IW driver support code.
278  *      See include/net/iw_handler.h.
279  *
280  *  Arguments:
281  *      None.
282  *
283  *  Returns:
284  *      None.
285  * ---------------------------------------------------------------------------
286  */
287 static int
288 iwprivsdefs(struct net_device *dev, struct iw_request_info *info,
289         union iwreq_data *wrqu, char *extra)
290 {
291     int r;
292     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
293     unifi_priv_t *priv = interfacePriv->privPtr;
294     CsrWifiSmeMibConfig mibConfig;
295     CsrWifiSmePowerConfig powerConfig;
296
297     unifi_trace(priv, UDBG1, "iwprivs80211defaults: reload defaults\n");
298
299     uf_sme_wext_set_defaults(priv);
300
301     /* Get, modify and set the MIB data */
302     r = sme_mgt_mib_config_get(priv, &mibConfig);
303     if (r) {
304         unifi_error(priv, "iwprivs80211defaults: Get CsrWifiSmeMibConfigValue failed.\n");
305         return r;
306     }
307     mibConfig.dot11RtsThreshold = 2347;
308     mibConfig.dot11FragmentationThreshold = 2346;
309     r = sme_mgt_mib_config_set(priv, &mibConfig);
310     if (r) {
311         unifi_error(priv, "iwprivs80211defaults: Set CsrWifiSmeMibConfigValue failed.\n");
312         return r;
313     }
314
315     powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
316     powerConfig.listenIntervalTu = 100;
317     powerConfig.rxDtims = 1;
318
319     r = sme_mgt_power_config_set(priv, &powerConfig);
320     if (r) {
321         unifi_error(priv, "iwprivs80211defaults: Set unifi_PowerConfigValue failed.\n");
322         return r;
323     }
324
325     return 0;
326 } /* iwprivsdefs() */
327
328 static int
329 iwprivs80211ps(struct net_device *dev, struct iw_request_info *info,
330         union iwreq_data *wrqu, char *extra)
331 {
332     int r = 0;
333     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
334     unifi_priv_t *priv = interfacePriv->privPtr;
335
336     int ps_mode = (int)(*extra);
337     CsrWifiSmePowerConfig powerConfig;
338
339     unifi_trace(priv, UDBG1, "iwprivs80211ps: power save mode = %d\n", ps_mode);
340
341     r = sme_mgt_power_config_get(priv, &powerConfig);
342     if (r) {
343         unifi_error(priv, "iwprivs80211ps: Get unifi_PowerConfigValue failed.\n");
344         return r;
345     }
346
347     switch (ps_mode) {
348         case CSR_PMM_ACTIVE_MODE:
349             powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
350             break;
351         case CSR_PMM_POWER_SAVE:
352             powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
353             break;
354         case CSR_PMM_FAST_POWER_SAVE:
355             powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED;
356             break;
357         default:
358             powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO;
359             break;
360     }
361
362     r = sme_mgt_power_config_set(priv, &powerConfig);
363     if (r) {
364         unifi_error(priv, "iwprivs80211ps: Set unifi_PowerConfigValue failed.\n");
365     }
366
367     return r;
368 }
369
370 static int
371 iwprivg80211ps(struct net_device *dev, struct iw_request_info *info,
372         union iwreq_data *wrqu, char *extra)
373 {
374     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
375     unifi_priv_t *priv = interfacePriv->privPtr;
376
377     CsrWifiSmePowerConfig powerConfig;
378     int r;
379
380     r = sme_mgt_power_config_get(priv, &powerConfig);
381     if (r) {
382         unifi_error(priv, "iwprivg80211ps: Get 802.11 power mode failed.\n");
383         return r;
384     }
385
386     switch (powerConfig.powerSaveLevel) {
387         case CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW:
388             snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
389                      "Power save mode: %d (Active)",
390                      powerConfig.powerSaveLevel);
391             break;
392         case CSR_WIFI_SME_POWER_SAVE_LEVEL_MED:
393             snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
394                      "Power save mode: %d (Fast)",
395                      powerConfig.powerSaveLevel);
396             break;
397         case CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH:
398             snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
399                      "Power save mode: %d (Full)",
400                      powerConfig.powerSaveLevel);
401             break;
402         case CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO:
403             snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
404                      "Power save mode: %d (Auto)",
405                      powerConfig.powerSaveLevel);
406             break;
407         default:
408             snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
409                      "Power save mode: %d (Unknown)",
410                      powerConfig.powerSaveLevel);
411             break;
412     }
413
414     wrqu->data.length = strlen(extra) + 1;
415
416     return 0;
417 }
418
419 static int
420 iwprivssmedebug(struct net_device *dev, struct iw_request_info *info,
421         union iwreq_data *wrqu, char *extra)
422 {
423     /* No longer supported on the API */
424 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE)
425     unifi_debug_buf_dump();
426 #endif
427
428     return 0;
429 }
430
431 #ifdef CSR_SUPPORT_WEXT_AP
432 #define PARAM_TYPE_INT 0
433 #define PARAM_TYPE_STRING 1
434 #define CSR_WIFI_MAX_SSID_LEN 32
435 #define CSR_WIFI_MAX_SEC_LEN 16
436 #define CSR_WIFI_MAX_KEY_LEN 65
437
438 static int hex_look_up(char x)
439 {
440     if(x>='0' && x<='9')
441         return (x-48);
442     if(x>= 'a' && x <= 'f')
443         return (x-87);
444     return -1;
445 }
446
447 static int power (int a, int b)
448 {
449     int i;
450     int num =1;
451     for(i=0;i<b;i++)
452        num *=a;
453     return num;
454 }
455
456 static int decode_parameter_from_string(unifi_priv_t* priv, char **str_ptr,
457                                         const char *token, int param_type,
458                                         void  *dst, int param_max_len)
459 {
460     u8 int_str[7] = "0";
461     u32 param_str_len;
462     u8  *param_str_begin,*param_str_end;
463     u8  *orig_str = *str_ptr;
464
465     if (!strncmp(*str_ptr, token, strlen(token))) {
466         strsep(str_ptr, "=,");
467         param_str_begin = *str_ptr;
468         strsep(str_ptr, "=,");
469         if (*str_ptr == NULL) {
470             param_str_len = strlen(param_str_begin);
471         } else {
472             param_str_end = *str_ptr-1;
473             param_str_len = param_str_end - param_str_begin;
474         }
475         unifi_trace(priv,UDBG2,"'token:%s', len:%d, ", token, param_str_len);
476         if (param_str_len > param_max_len) {
477             unifi_notice(priv,"extracted param len:%d is > MAX:%d\n",param_str_len, param_max_len);
478             param_str_len = param_max_len;
479         }
480         switch (param_type) {
481             case PARAM_TYPE_INT:
482             {
483                 u32 *pdst_int = dst,num =0;
484                 int i,j=0;
485                 if (param_str_len > sizeof(int_str)) {
486                     param_str_len = sizeof(int_str);
487                 }
488                 memcpy(int_str, param_str_begin, param_str_len);
489                 for(i = param_str_len; i>0;i--) {
490                     if(int_str[i-1] >= '0' && int_str[i-1] <='9') {
491                         num += ((int_str[i-1]-'0')*power(10,j));
492                         j++;
493                     } else {
494                         unifi_error(priv,"decode_parameter_from_string:not a number %c\n",(int_str[i-1]));
495                         return -1;
496                     }
497                 }
498                 *pdst_int = num;
499                 unifi_trace(priv,UDBG2,"decode_parameter_from_string:decoded int = %d\n",*pdst_int);
500             }
501             break;
502             default:
503                 memcpy(dst, param_str_begin, param_str_len);
504                 *((char *)dst + param_str_len) = 0;
505                 unifi_trace(priv,UDBG2,"decode_parameter_from_string:decoded string = %s\n",(char *)dst);
506             break;
507         }
508     } else {
509         unifi_error(priv,"decode_parameter_from_string: Token:%s not found in %s \n",token,orig_str);
510         return -1;
511     }
512     return 0;
513 }
514 static int store_ap_advanced_config_from_string(unifi_priv_t *priv, char *param_str)
515 {
516     char * str_ptr=param_str;
517     int ret = 0,tmp_var;
518     char phy_mode[6];
519     CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config;
520
521     /* Check for BI */
522     ret = decode_parameter_from_string(priv, &str_ptr, "BI=",
523                                        PARAM_TYPE_INT, &tmp_var, 5);
524     if(ret) {
525         unifi_error(priv,"store_ap_advanced_config_from_string: BI not found\n");
526         return -1;
527     }
528     ap_mac_config->beaconInterval = tmp_var;
529     ret = decode_parameter_from_string(priv, &str_ptr, "DTIM_PER=",
530                                         PARAM_TYPE_INT, &tmp_var, 5);
531     if(ret) {
532         unifi_error(priv,"store_ap_advanced_config_from_string: DTIM_PER not found\n");
533         return -1;
534     }
535     ap_mac_config->dtimPeriod = tmp_var;
536     ret = decode_parameter_from_string(priv, &str_ptr, "WMM=",
537                                         PARAM_TYPE_INT, &tmp_var, 5);
538     if(ret) {
539         unifi_error(priv,"store_ap_advanced_config_from_string: WMM not found\n");
540         return -1;
541     }
542     ap_mac_config->wmmEnabled = tmp_var;
543     ret = decode_parameter_from_string(priv, &str_ptr, "PHY=",
544                                         PARAM_TYPE_STRING, phy_mode, 5);
545     if(ret) {
546         unifi_error(priv,"store_ap_advanced_config_from_string: PHY not found\n");
547     } else {
548        if(strstr(phy_mode,"b")){
549            ap_mac_config->phySupportedBitmap = CSR_WIFI_SME_AP_PHY_SUPPORT_B;
550        }
551        if(strstr(phy_mode,"g")) {
552            ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_G;
553        }
554        if(strstr(phy_mode,"n")) {
555            ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_N;
556        }
557        ap_mac_config->supportedRatesCount =
558        uf_configure_supported_rates(ap_mac_config->supportedRates, ap_mac_config->phySupportedBitmap);
559     }
560     return ret;
561 }
562
563 static int store_ap_config_from_string( unifi_priv_t * priv,char *param_str)
564
565 {
566     char *str_ptr = param_str;
567     char sub_cmd[16];
568     char sec[CSR_WIFI_MAX_SEC_LEN];
569     char key[CSR_WIFI_MAX_KEY_LEN];
570     int ret = 0,tmp_var;
571     CsrWifiSmeApConfig_t *ap_config = &priv->ap_config;
572     CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config;
573     memset(sub_cmd, 0, sizeof(sub_cmd));
574     if(!strstr(param_str,"END")) {
575         unifi_error(priv,"store_ap_config_from_string:Invalid config string:%s\n",param_str);
576         return -1;
577     }
578     if (decode_parameter_from_string(priv,&str_ptr, "ASCII_CMD=",
579         PARAM_TYPE_STRING, sub_cmd, 6) != 0) {
580          return -1;
581     }
582     if (strncmp(sub_cmd, "AP_CFG", 6)) {
583
584         if(!strncmp(sub_cmd ,"ADVCFG", 6)) {
585            return store_ap_advanced_config_from_string(priv, str_ptr);
586         }
587         unifi_error(priv,"store_ap_config_from_string: sub_cmd:%s != 'AP_CFG or ADVCFG'!\n", sub_cmd);
588         return -1;
589     }
590     memset(ap_config, 0, sizeof(CsrWifiSmeApConfig_t));
591     ret = decode_parameter_from_string(priv,&str_ptr, "SSID=",
592                                        PARAM_TYPE_STRING, ap_config->ssid.ssid,
593                                        CSR_WIFI_MAX_SSID_LEN);
594     if(ret) {
595         unifi_error(priv,"store_ap_config_from_string: SSID not found\n");
596         return -1;
597     }
598     ap_config->ssid.length = strlen(ap_config->ssid.ssid);
599
600     ret = decode_parameter_from_string(priv, &str_ptr, "SEC=",
601                                        PARAM_TYPE_STRING, sec, CSR_WIFI_MAX_SEC_LEN);
602     if(ret) {
603         unifi_error(priv,"store_ap_config_from_string: SEC not found\n");
604         return -1;
605     }
606     ret = decode_parameter_from_string(priv,&str_ptr, "KEY=",
607                          PARAM_TYPE_STRING,  key, CSR_WIFI_MAX_KEY_LEN);
608     if(!strcasecmp(sec,"open")) {
609         unifi_trace(priv,UDBG2,"store_ap_config_from_string: security open");
610         ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM;
611         if(ret) {
612             unifi_notice(priv,"store_ap_config_from_string: KEY not found:fine with Open\n");
613         }
614     }
615     else if(!strcasecmp(sec,"wpa2-psk")) {
616         int i,j=0;
617         CsrWifiNmeApAuthPers *pers =
618                             ((CsrWifiNmeApAuthPers *)&(ap_config->credentials.nmeAuthType.authTypePersonal));
619         u8 *psk = pers->authPers_credentials.psk.psk;
620
621         unifi_trace(priv,UDBG2,"store_ap_config_from_string: security WPA2");
622         if(ret) {
623             unifi_error(priv,"store_ap_config_from_string: KEY not found for WPA2\n");
624             return -1;
625         }
626         ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL;
627         pers->authSupport = CSR_WIFI_SME_RSN_AUTH_WPA2PSK;
628         pers->rsnCapabilities =0;
629         pers->wapiCapabilities =0;
630         pers->pskOrPassphrase=CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK;
631         pers->authPers_credentials.psk.encryptionMode =
632                  (CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP |CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP) ;
633         for(i=0;i<32;i++){
634            psk[i] = (16*hex_look_up(key[j]))+hex_look_up(key[j+1]);
635            j+=2;
636         }
637
638     } else {
639        unifi_notice(priv,"store_ap_config_from_string: Unknown security: Assuming Open");
640        ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM;
641        return -1;
642     }
643    /* Get the decoded value in a temp int variable to ensure that other fields within the struct
644       which are of type other than int are not over written */
645     ret = decode_parameter_from_string(priv,&str_ptr, "CHANNEL=", PARAM_TYPE_INT, &tmp_var, 5);
646     if(ret)
647         return -1;
648     ap_config->channel = tmp_var;
649     ret = decode_parameter_from_string(priv,&str_ptr, "PREAMBLE=", PARAM_TYPE_INT, &tmp_var, 5);
650     if(ret)
651         return -1;
652     ap_mac_config->preamble = tmp_var;
653     ret = decode_parameter_from_string(priv,&str_ptr, "MAX_SCB=", PARAM_TYPE_INT,  &tmp_var, 5);
654     ap_config->max_connections = tmp_var;
655     return ret;
656 }
657
658 static int
659 iwprivsapstart(struct net_device *dev, struct iw_request_info *info,
660                union iwreq_data *wrqu, char *extra)
661 {
662     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
663     unifi_priv_t *priv = interfacePriv->privPtr;
664     int r;
665
666     unifi_trace(priv, UDBG1, "iwprivsapstart\n" );
667     r = sme_ap_start(priv,interfacePriv->InterfaceTag,&priv->ap_config);
668     if(r) {
669         unifi_error(priv,"iwprivsapstart AP START failed : %d\n",-r);
670     }
671     return r;
672 }
673
674 static int
675 iwprivsapconfig(struct net_device *dev, struct iw_request_info *info,
676                 union iwreq_data *wrqu, char *extra)
677 {
678     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
679     unifi_priv_t *priv = interfacePriv->privPtr;
680     char  *cfg_str = NULL;
681     int r;
682
683     unifi_trace(priv, UDBG1, "iwprivsapconfig\n" );
684     if (wrqu->data.length != 0) {
685         char *str;
686         if (!(cfg_str = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
687         {
688             return -ENOMEM;
689         }
690         if (copy_from_user(cfg_str, wrqu->data.pointer, wrqu->data.length)) {
691             kfree(cfg_str);
692             return -EFAULT;
693         }
694         cfg_str[wrqu->data.length] = 0;
695         unifi_trace(priv,UDBG2,"length:%d\n",wrqu->data.length);
696         unifi_trace(priv,UDBG2,"AP configuration string:%s\n",cfg_str);
697         str = cfg_str;
698        if ((r = store_ap_config_from_string(priv,str))) {
699            unifi_error(priv, "iwprivsapconfig:Failed  to decode the string %d\n",r);
700            kfree(cfg_str);
701            return -EIO;
702
703        }
704     } else {
705         unifi_error(priv,"iwprivsapconfig argument length = 0 \n");
706         return -EIO;
707     }
708     r = sme_ap_config(priv, &priv->ap_mac_config, &priv->group_sec_config);
709     if(r) {
710         unifi_error(priv,"iwprivsapstop AP Config failed : %d\n",-r);
711     } else if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
712         interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
713         unifi_trace(priv, UDBG1, "iwprivsapconfig: Starting the AP");
714         r = sme_ap_start(priv,interfacePriv->InterfaceTag,&priv->ap_config);
715         if(r) {
716             unifi_error(priv,"iwprivsapstart AP START failed : %d\n",-r);
717         }
718     }
719     kfree(cfg_str);
720     return r;
721 }
722
723 static int
724 iwprivsapstop(struct net_device *dev, struct iw_request_info *info,
725         union iwreq_data *wrqu, char *extra)
726 {
727     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
728     unifi_priv_t *priv = interfacePriv->privPtr;
729     int r;
730     u16 interface_tag = interfacePriv->InterfaceTag;
731
732     unifi_trace(priv, UDBG1, "iwprivsapstop\n" );
733     r = sme_ap_stop(priv,interface_tag);
734     if(r) {
735         unifi_error(priv,"iwprivsapstop AP STOP failed : %d\n",-r);
736     }
737     return r;
738 }
739
740 #ifdef ANDROID_BUILD
741 static int
742 iwprivsapfwreload(struct net_device *dev, struct iw_request_info *info,
743                   union iwreq_data *wrqu, char *extra)
744 {
745     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
746     unifi_priv_t *priv = interfacePriv->privPtr;
747
748     unifi_trace(priv, UDBG1, "iwprivsapfwreload\n" );
749     return 0;
750 }
751
752 static int
753 iwprivsstackstart(struct net_device *dev, struct iw_request_info *info,
754         union iwreq_data *wrqu, char *extra)
755 {
756     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
757     unifi_priv_t *priv = interfacePriv->privPtr;
758     unifi_trace(priv, UDBG1, "iwprivsstackstart\n" );
759     return 0;
760 }
761
762 static int
763 iwprivsstackstop(struct net_device *dev, struct iw_request_info *info,
764         union iwreq_data *wrqu, char *extra)
765 {
766     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
767     unifi_priv_t *priv = interfacePriv->privPtr;
768     int r = 0;
769     u16 interface_tag = interfacePriv->InterfaceTag;
770
771     unifi_trace(priv, UDBG1, "iwprivsstackstop\n" );
772
773     switch(interfacePriv->interfaceMode) {
774         case CSR_WIFI_ROUTER_CTRL_MODE_STA:
775         case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI:
776         case CSR_WIFI_ROUTER_CTRL_MODE_IBSS:
777             r = sme_mgt_disconnect(priv);
778             break;
779         case CSR_WIFI_ROUTER_CTRL_MODE_AP:
780         case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO:
781             r = sme_ap_stop(priv,interface_tag);
782             break;
783         default :
784             break;
785     }
786
787     if(r) {
788         unifi_error(priv,"iwprivsstackstop Stack stop failed : %d\n",-r);
789     }
790     return 0;
791 }
792 #endif /* ANDROID_BUILD */
793 #endif /* CSR_SUPPORT_WEXT_AP */
794
795 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
796 static int
797 iwprivsconfwapi(struct net_device *dev, struct iw_request_info *info,
798         union iwreq_data *wrqu, char *extra)
799 {
800     u8 enable;
801     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
802     unifi_priv_t *priv = interfacePriv->privPtr;
803     func_enter();
804
805     unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" );
806
807     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
808        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
809        unifi_error(priv, "iwprivsconfwapi: not permitted in Mode %d\n",
810                                       interfacePriv->interfaceMode);
811        return -EPERM;
812     }
813
814     enable = *(u8*)(extra);
815
816     if (enable) {
817         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
818         priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
819         priv->connection_config.encryptionModeMask |=
820             CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4;
821     } else {
822         priv->connection_config.authModeMask &= ~(CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
823         priv->connection_config.encryptionModeMask &=
824             ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4);
825     }
826
827     func_exit();
828     return 0;
829 }
830
831 static int
832 iwprivswpikey(struct net_device *dev, struct iw_request_info *info,
833         union iwreq_data *wrqu, char *extra)
834 {
835     int r = 0, i;
836     CsrWifiSmeKey key;
837     unifiio_wapi_key_t inKey;
838     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
839     unifi_priv_t *priv = interfacePriv->privPtr;
840     func_enter();
841
842     unifi_trace(priv, UDBG1, "iwprivswpikey\n" );
843
844     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
845        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
846        unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
847                                       interfacePriv->interfaceMode);
848        return -EPERM;
849     }
850
851     inKey = *(unifiio_wapi_key_t*)(extra);
852
853     if (inKey.unicastKey) {
854         key.keyType   = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
855     } else {
856         key.keyType   = CSR_WIFI_SME_KEY_TYPE_GROUP;
857     }
858
859     key.keyIndex  = inKey.keyIndex;
860
861     /* memcpy(key.keyRsc, inKey.keyRsc, 16); */
862     for (i = 0; i < 16; i+= 2)
863     {
864         key.keyRsc[i/2] = inKey.keyRsc[i+1] << 8 | inKey.keyRsc[i];
865     }
866
867     memcpy(key.address.a, inKey.address, 6);
868     key.keyLength = 32;
869     memcpy(key.key, inKey.key, 32);
870     key.authenticator = 0;
871     key.wepTxKey = 0;
872
873     unifi_trace(priv, UDBG1, "keyType = %d, keyIndex = %d, wepTxKey = %d, keyRsc = %x:%x, auth = %d, address = %x:%x, "
874                 "keylength = %d, key = %x:%x\n", key.keyType, key.keyIndex, key.wepTxKey,
875                 key.keyRsc[0], key.keyRsc[7], key.authenticator,
876                 key.address.a[0], key.address.a[5], key.keyLength, key.key[0],
877                 key.key[15]);
878
879     r = sme_mgt_key(priv, &key, CSR_WIFI_SME_LIST_ACTION_ADD);
880     if (r) {
881         unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
882         return convert_sme_error(r);
883     }
884
885     func_exit();
886     return r;
887 }
888 #endif
889
890
891 static int
892 unifi_giwname(struct net_device *dev, struct iw_request_info *info,
893         union iwreq_data *wrqu, char *extra)
894 {
895     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
896     unifi_priv_t *priv = interfacePriv->privPtr;
897     char *name = wrqu->name;
898     unifi_trace(priv, UDBG2, "unifi_giwname\n");
899
900     if (priv->if_index == CSR_INDEX_5G) {
901         strcpy(name, "IEEE 802.11-a");
902     } else {
903         strcpy(name, "IEEE 802.11-bgn");
904     }
905     return 0;
906 } /* unifi_giwname() */
907
908
909 static int
910 unifi_siwfreq(struct net_device *dev, struct iw_request_info *info,
911         union iwreq_data *wrqu, char *extra)
912 {
913     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
914     unifi_priv_t *priv = interfacePriv->privPtr;
915     struct iw_freq *freq = (struct iw_freq *)wrqu;
916
917     func_enter();
918     unifi_trace(priv, UDBG2, "unifi_siwfreq\n");
919
920     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
921        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
922        unifi_error(priv, "unifi_siwfreq: not permitted in Mode %d\n",
923                                       interfacePriv->interfaceMode);
924        return -EPERM;
925     }
926
927
928     /*
929      * Channel is stored in the connection configuration,
930      * and set later when ask for a connection.
931      */
932     if ((freq->e == 0) && (freq->m <= 1000)) {
933         priv->connection_config.adhocChannel = freq->m;
934     } else {
935         priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e);
936     }
937
938     func_exit();
939     return 0;
940 } /* unifi_siwfreq() */
941
942
943 static int
944 unifi_giwfreq(struct net_device *dev, struct iw_request_info *info,
945         union iwreq_data *wrqu, char *extra)
946 {
947     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
948     unifi_priv_t *priv = interfacePriv->privPtr;
949     struct iw_freq *freq = (struct iw_freq *)wrqu;
950     int err = 0;
951     CsrWifiSmeConnectionInfo connectionInfo;
952
953     func_enter();
954     unifi_trace(priv, UDBG2, "unifi_giwfreq\n");
955     CHECK_INITED(priv);
956
957     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
958        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
959        unifi_error(priv, "unifi_giwfreq: not permitted in Mode %d\n",
960                                       interfacePriv->interfaceMode);
961        return -EPERM;
962     }
963
964
965     UF_RTNL_UNLOCK();
966     err = sme_mgt_connection_info_get(priv, &connectionInfo);
967     UF_RTNL_LOCK();
968
969     freq->m = channel_to_mhz(connectionInfo.channelNumber,
970             (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0));
971     freq->e = 6;
972
973     func_exit();
974     return convert_sme_error(err);
975 } /* unifi_giwfreq() */
976
977
978 static int
979 unifi_siwmode(struct net_device *dev, struct iw_request_info *info,
980         union iwreq_data *wrqu, char *extra)
981 {
982     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
983     unifi_priv_t *priv = interfacePriv->privPtr;
984
985     func_enter();
986     unifi_trace(priv, UDBG2, "unifi_siwmode\n");
987
988     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
989        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
990        unifi_error(priv, "unifi_siwmode: not permitted in Mode %d\n",
991                                       interfacePriv->interfaceMode);
992        return -EPERM;
993     }
994
995
996     switch(wrqu->mode) {
997         case IW_MODE_ADHOC:
998             priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ADHOC;
999             break;
1000         case IW_MODE_INFRA:
1001             priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE;
1002             break;
1003         case IW_MODE_AUTO:
1004             priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ANY_BSS;
1005             break;
1006         default:
1007             unifi_notice(priv, "Unknown IW MODE value.\n");
1008     }
1009
1010     /* Clear the SSID and BSSID configuration */
1011     priv->connection_config.ssid.length = 0;
1012     memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1013
1014     func_exit();
1015     return 0;
1016 } /* unifi_siwmode() */
1017
1018
1019
1020 static int
1021 unifi_giwmode(struct net_device *dev, struct iw_request_info *info,
1022         union iwreq_data *wrqu, char *extra)
1023 {
1024     int r = 0;
1025     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1026     unifi_priv_t *priv = interfacePriv->privPtr;
1027     CsrWifiSmeConnectionConfig connectionConfig;
1028
1029     func_enter();
1030     unifi_trace(priv, UDBG2, "unifi_giwmode\n");
1031     CHECK_INITED(priv);
1032
1033     unifi_trace(priv, UDBG2, "unifi_giwmode: Exisitng mode = 0x%x\n",
1034                 interfacePriv->interfaceMode);
1035     switch(interfacePriv->interfaceMode) {
1036         case CSR_WIFI_ROUTER_CTRL_MODE_STA:
1037         case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI:
1038            wrqu->mode = IW_MODE_INFRA;
1039            break;
1040         case CSR_WIFI_ROUTER_CTRL_MODE_AP:
1041         case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO:
1042             wrqu->mode = IW_MODE_MASTER;
1043             break;
1044         case CSR_WIFI_ROUTER_CTRL_MODE_IBSS:
1045             wrqu->mode = IW_MODE_ADHOC;
1046             break;
1047         case CSR_WIFI_ROUTER_CTRL_MODE_P2P:
1048         case CSR_WIFI_ROUTER_CTRL_MODE_NONE:
1049             UF_RTNL_UNLOCK();
1050             r = sme_mgt_connection_config_get(priv, &connectionConfig);
1051             UF_RTNL_LOCK();
1052             if (r == 0) {
1053                 switch(connectionConfig.bssType) {
1054                     case CSR_WIFI_SME_BSS_TYPE_ADHOC:
1055                         wrqu->mode = IW_MODE_ADHOC;
1056                         break;
1057                     case CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE:
1058                         wrqu->mode = IW_MODE_INFRA;
1059                         break;
1060                     default:
1061                         wrqu->mode = IW_MODE_AUTO;
1062                         unifi_notice(priv, "Unknown IW MODE value.\n");
1063                 }
1064             }
1065             break;
1066         default:
1067             wrqu->mode = IW_MODE_AUTO;
1068             unifi_notice(priv, "Unknown IW MODE value.\n");
1069
1070     }
1071     unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode);
1072     func_exit();
1073     return r;
1074 } /* unifi_giwmode() */
1075
1076
1077
1078 static int
1079 unifi_giwrange(struct net_device *dev, struct iw_request_info *info,
1080         union iwreq_data *wrqu, char *extra)
1081 {
1082     struct iw_point *dwrq = &wrqu->data;
1083     struct iw_range *range = (struct iw_range *) extra;
1084     int i;
1085
1086     unifi_trace(NULL, UDBG2, "unifi_giwrange\n");
1087
1088     dwrq->length = sizeof(struct iw_range);
1089     memset(range, 0, sizeof(*range));
1090     range->min_nwid = 0x0000;
1091     range->max_nwid = 0x0000;
1092
1093     /*
1094      * Don't report the frequency/channel table, then the channel
1095      * number returned elsewhere will be printed as a channel number.
1096      */
1097
1098     /* Ranges of values reported in quality structs */
1099     range->max_qual.qual  = 40;         /* Max expected qual value */
1100     range->max_qual.level = -120;       /* Noise floor in dBm */
1101     range->max_qual.noise = -120;       /* Noise floor in dBm */
1102
1103
1104     /* space for IW_MAX_BITRATES (8 up to WE15, 32 later) */
1105     i = 0;
1106 #if WIRELESS_EXT > 15
1107     range->bitrate[i++] =   2 * 500000;
1108     range->bitrate[i++] =   4 * 500000;
1109     range->bitrate[i++] =  11 * 500000;
1110     range->bitrate[i++] =  22 * 500000;
1111     range->bitrate[i++] =  12 * 500000;
1112     range->bitrate[i++] =  18 * 500000;
1113     range->bitrate[i++] =  24 * 500000;
1114     range->bitrate[i++] =  36 * 500000;
1115     range->bitrate[i++] =  48 * 500000;
1116     range->bitrate[i++] =  72 * 500000;
1117     range->bitrate[i++] =  96 * 500000;
1118     range->bitrate[i++] = 108 * 500000;
1119 #else
1120     range->bitrate[i++] =   2 * 500000;
1121     range->bitrate[i++] =   4 * 500000;
1122     range->bitrate[i++] =  11 * 500000;
1123     range->bitrate[i++] =  22 * 500000;
1124     range->bitrate[i++] =  24 * 500000;
1125     range->bitrate[i++] =  48 * 500000;
1126     range->bitrate[i++] =  96 * 500000;
1127     range->bitrate[i++] = 108 * 500000;
1128 #endif /* WIRELESS_EXT < 16 */
1129     range->num_bitrates = i;
1130
1131     range->max_encoding_tokens = NUM_WEPKEYS;
1132     range->num_encoding_sizes = 2;
1133     range->encoding_size[0] = 5;
1134     range->encoding_size[1] = 13;
1135
1136     range->we_version_source = 20;
1137     range->we_version_compiled = WIRELESS_EXT;
1138
1139     /* Number of channels available in h/w */
1140     range->num_channels = 14;
1141     /* Number of entries in freq[] array */
1142     range->num_frequency = 14;
1143     for (i = 0; (i < range->num_frequency) && (i < IW_MAX_FREQUENCIES); i++) {
1144         int chan = i + 1;
1145         range->freq[i].i = chan;
1146         range->freq[i].m = channel_to_mhz(chan, 0);
1147         range->freq[i].e = 6;
1148     }
1149     if ((i+3) < IW_MAX_FREQUENCIES) {
1150         range->freq[i].i = 36;
1151         range->freq[i].m = channel_to_mhz(36, 1);
1152         range->freq[i].e = 6;
1153         range->freq[i+1].i = 40;
1154         range->freq[i+1].m = channel_to_mhz(40, 1);
1155         range->freq[i+1].e = 6;
1156         range->freq[i+2].i = 44;
1157         range->freq[i+2].m = channel_to_mhz(44, 1);
1158         range->freq[i+2].e = 6;
1159         range->freq[i+3].i = 48;
1160         range->freq[i+3].m = channel_to_mhz(48, 1);
1161         range->freq[i+3].e = 6;
1162     }
1163
1164 #if WIRELESS_EXT > 16
1165     /* Event capability (kernel + driver) */
1166     range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
1167             IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
1168             IW_EVENT_CAPA_MASK(SIOCGIWAP) |
1169             IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
1170     range->event_capa[1] = IW_EVENT_CAPA_K_1;
1171     range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
1172             IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
1173             IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
1174             IW_EVENT_CAPA_MASK(IWEVEXPIRED));
1175 #endif /* WIRELESS_EXT > 16 */
1176
1177 #if WIRELESS_EXT > 17
1178     range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1179         IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1180 #endif /* WIRELESS_EXT > 17 */
1181
1182
1183     return 0;
1184 } /* unifi_giwrange() */
1185
1186
1187 static int
1188 unifi_siwap(struct net_device *dev, struct iw_request_info *info,
1189         union iwreq_data *wrqu, char *extra)
1190 {
1191     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1192     unifi_priv_t *priv = interfacePriv->privPtr;
1193     int err = 0;
1194     const unsigned char zero_bssid[ETH_ALEN] = {0x00, 0x00, 0x00,
1195         0x00, 0x00, 0x00};
1196
1197     func_enter();
1198
1199     CHECK_INITED(priv);
1200
1201     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1202        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1203        unifi_error(priv, "unifi_siwap: not permitted in Mode %d\n",
1204                                       interfacePriv->interfaceMode);
1205        return -EPERM;
1206     }
1207
1208
1209     if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) {
1210         return -EINVAL;
1211     }
1212
1213         unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n",
1214                 wrqu->ap_addr.sa_data);
1215
1216     if (!memcmp(wrqu->ap_addr.sa_data, zero_bssid, ETH_ALEN)) {
1217         priv->ignore_bssid_join = FALSE;
1218         err = sme_mgt_disconnect(priv);
1219         if (err) {
1220             unifi_trace(priv, UDBG4, "unifi_siwap: Disconnect failed, status %d\n", err);
1221         }
1222         return 0;
1223     }
1224
1225     if (priv->ignore_bssid_join) {
1226         unifi_trace(priv, UDBG4, "unifi_siwap: ignoring second join\n");
1227         priv->ignore_bssid_join = FALSE;
1228     } else {
1229         memcpy(priv->connection_config.bssid.a, wrqu->ap_addr.sa_data, ETH_ALEN);
1230         unifi_trace(priv, UDBG1, "unifi_siwap: Joining %X:%X:%X:%X:%X:%X\n",
1231                     priv->connection_config.bssid.a[0],
1232                     priv->connection_config.bssid.a[1],
1233                     priv->connection_config.bssid.a[2],
1234                     priv->connection_config.bssid.a[3],
1235                     priv->connection_config.bssid.a[4],
1236                     priv->connection_config.bssid.a[5]);
1237         err = sme_mgt_connect(priv);
1238         if (err) {
1239             unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err);
1240             func_exit();
1241             return convert_sme_error(err);
1242         }
1243     }
1244     func_exit();
1245
1246     return 0;
1247 } /* unifi_siwap() */
1248
1249
1250 static int
1251 unifi_giwap(struct net_device *dev, struct iw_request_info *info,
1252         union iwreq_data *wrqu, char *extra)
1253 {
1254     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1255     unifi_priv_t *priv = interfacePriv->privPtr;
1256     CsrWifiSmeConnectionInfo connectionInfo;
1257     int r = 0;
1258     u8 *bssid;
1259
1260     func_enter();
1261
1262     CHECK_INITED(priv);
1263     unifi_trace(priv, UDBG2, "unifi_giwap\n");
1264
1265     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1266        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1267        unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
1268                                       interfacePriv->interfaceMode);
1269        return -EPERM;
1270     }
1271
1272     UF_RTNL_UNLOCK();
1273     r = sme_mgt_connection_info_get(priv, &connectionInfo);
1274     UF_RTNL_LOCK();
1275
1276     if (r == 0) {
1277         bssid = connectionInfo.bssid.a;
1278         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1279                 unifi_trace(priv, UDBG4, "unifi_giwap: BSSID = %pM\n", bssid);
1280
1281         memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
1282     } else {
1283         memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1284     }
1285
1286     func_exit();
1287     return 0;
1288 } /* unifi_giwap() */
1289
1290
1291 static int
1292 unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
1293         union iwreq_data *wrqu, char *extra)
1294 {
1295     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1296     unifi_priv_t *priv = interfacePriv->privPtr;
1297     int scantype;
1298     int r;
1299     CsrWifiSsid scan_ssid;
1300     unsigned char *channel_list = NULL;
1301     int chans_good = 0;
1302 #if WIRELESS_EXT > 17
1303     struct iw_point *data = &wrqu->data;
1304     struct iw_scan_req *req = (struct iw_scan_req *) extra;
1305 #endif
1306
1307     func_enter();
1308
1309     CHECK_INITED(priv);
1310
1311     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1312        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1313        unifi_error(priv, "unifi_siwscan: not permitted in Mode %d\n",
1314                                       interfacePriv->interfaceMode);
1315        return -EPERM;
1316     }
1317
1318
1319     scantype = UNIFI_SCAN_ACTIVE;
1320
1321 #if WIRELESS_EXT > 17
1322     /* Providing a valid channel list will force an active scan */
1323     if (req) {
1324         if ((req->num_channels > 0) && (req->num_channels < IW_MAX_FREQUENCIES)) {
1325             channel_list = kmalloc(req->num_channels, GFP_KERNEL);
1326             if (channel_list) {
1327                 int i;
1328                 for (i = 0; i < req->num_channels; i++) {
1329                     /* Convert frequency to channel number */
1330                     int ch = wext_freq_to_channel(req->channel_list[i].m,
1331                             req->channel_list[i].e);
1332                     if (ch) {
1333                         channel_list[chans_good++] = ch;
1334                     }
1335                 }
1336                 unifi_trace(priv, UDBG1,
1337                             "SIWSCAN: Scanning %d channels\n", chans_good);
1338             } else {
1339                 /* Fall back to scanning all */
1340                 unifi_error(priv, "SIWSCAN: Can't alloc channel_list (%d)\n",
1341                         req->num_channels);
1342             }
1343         }
1344     }
1345
1346     if (req && (data->flags & IW_SCAN_THIS_ESSID)) {
1347         memcpy(scan_ssid.ssid, req->essid, req->essid_len);
1348         scan_ssid.length = req->essid_len;
1349         unifi_trace(priv, UDBG1,
1350                     "SIWSCAN: Scanning for %.*s\n",
1351                     scan_ssid.length, scan_ssid.ssid);
1352     } else
1353 #endif
1354     {
1355         unifi_trace(priv, UDBG1, "SIWSCAN: Scanning for all APs\n");
1356         scan_ssid.length = 0;
1357     }
1358
1359     r = sme_mgt_scan_full(priv, &scan_ssid, chans_good, channel_list);
1360     if (r) {
1361         unifi_error(priv, "SIWSCAN: Scan returned error %d\n", r);
1362     } else {
1363         unifi_trace(priv, UDBG1, "SIWSCAN: Scan done\n");
1364         wext_send_scan_results_event(priv);
1365     }
1366
1367     if (channel_list) {
1368         kfree(channel_list);
1369     }
1370
1371     func_exit();
1372     return r;
1373
1374 } /* unifi_siwscan() */
1375
1376
1377 static const unsigned char *
1378 unifi_find_info_element(int id, const unsigned char *info, int len)
1379 {
1380     const unsigned char *ie = info;
1381
1382     while (len > 1)
1383     {
1384         int e_id, e_len;
1385         e_id = ie[0];
1386         e_len = ie[1];
1387
1388         /* Return if we find a match */
1389         if (e_id == id)
1390         {
1391             return ie;
1392         }
1393
1394         len -= (e_len + 2);
1395         ie  += (e_len + 2);
1396     }
1397
1398     return NULL;
1399 } /* unifi_find_info_element() */
1400
1401
1402 /*
1403  * Translate scan data returned from the card to a card independent
1404  * format that the Wireless Tools will understand - Jean II
1405  */
1406 int
1407 unifi_translate_scan(struct net_device *dev,
1408                      struct iw_request_info *info,
1409                      char *current_ev, char *end_buf,
1410                      CsrWifiSmeScanResult *scan_data,
1411                      int scan_index)
1412 {
1413     struct iw_event iwe;                /* Temporary buffer */
1414     unsigned char *info_elems;
1415     int info_elem_len;
1416     const unsigned char *elem;
1417     u16 capabilities;
1418     int signal, noise, snr;
1419     char *start_buf = current_ev;
1420     char *current_val;  /* For rates */
1421     int i, r;
1422
1423     info_elems    = scan_data->informationElements;
1424     info_elem_len = scan_data->informationElementsLength;
1425
1426     if (!scan_data->informationElementsLength || !scan_data->informationElements) {
1427         unifi_error(NULL, "*** NULL SCAN IEs ***\n");
1428         return -EIO;
1429     }
1430
1431     /* get capinfo bits */
1432     capabilities = scan_data->capabilityInformation;
1433
1434     unifi_trace(NULL, UDBG5, "Capabilities: 0x%x\n", capabilities);
1435
1436     /* First entry *MUST* be the AP MAC address */
1437     memset(&iwe, 0, sizeof(iwe));
1438     iwe.cmd = SIOCGIWAP;
1439     iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1440     memcpy(iwe.u.ap_addr.sa_data, scan_data->bssid.a, ETH_ALEN);
1441     iwe.len = IW_EV_ADDR_LEN;
1442     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_ADDR_LEN);
1443     if (r < 0) {
1444         return r;
1445     }
1446     start_buf += r;
1447
1448     /* Other entries will be displayed in the order we give them */
1449
1450     /* Add the ESSID */
1451     /* find SSID in Info Elems */
1452     elem = unifi_find_info_element(IE_SSID_ID, info_elems, info_elem_len);
1453     if (elem) {
1454         int e_len = elem[1];
1455         const unsigned char *e_ptr = elem + 2;
1456         unsigned char buf[33];
1457
1458         memset(&iwe, 0, sizeof(iwe));
1459         iwe.cmd = SIOCGIWESSID;
1460         iwe.u.essid.length = e_len;
1461         if (iwe.u.essid.length > 32) {
1462             iwe.u.essid.length = 32;
1463         }
1464         iwe.u.essid.flags = scan_index;
1465         memcpy(buf, e_ptr, iwe.u.essid.length);
1466         buf[iwe.u.essid.length] = '\0';
1467         r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, buf);
1468         if (r < 0) {
1469             return r;
1470         }
1471         start_buf += r;
1472
1473     }
1474
1475     /* Add mode */
1476     memset(&iwe, 0, sizeof(iwe));
1477     iwe.cmd = SIOCGIWMODE;
1478     if (scan_data->bssType == CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE) {
1479         iwe.u.mode = IW_MODE_INFRA;
1480     } else {
1481         iwe.u.mode = IW_MODE_ADHOC;
1482     }
1483     iwe.len = IW_EV_UINT_LEN;
1484     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_UINT_LEN);
1485     if (r < 0) {
1486         return r;
1487     }
1488     start_buf += r;
1489
1490     /* Add frequency. iwlist will convert to channel using table given in giwrange */
1491     memset(&iwe, 0, sizeof(iwe));
1492     iwe.cmd = SIOCGIWFREQ;
1493     iwe.u.freq.m = scan_data->channelFrequency;
1494     iwe.u.freq.e = 6;
1495     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_FREQ_LEN);
1496     if (r < 0) {
1497         return r;
1498     }
1499     start_buf += r;
1500
1501
1502     /* Add quality statistics */
1503     iwe.cmd = IWEVQUAL;
1504     /*
1505      * level and noise below are mapped into an unsigned 8 bit number,
1506      * ranging from [-192; 63]. The way this is achieved is simply to
1507      * add 0x100 onto the number if it is negative,
1508      * once clipped to the correct range.
1509      */
1510     signal = scan_data->rssi; /* This value is in dBm */
1511     /* Clip range of snr */
1512     snr    = (scan_data->snr > 0) ? scan_data->snr : 0; /* In dB relative, from 0 - 255 */
1513     snr    = (snr < 255) ? snr : 255;
1514     noise  = signal - snr;
1515
1516     /* Clip range of signal */
1517     signal = (signal < 63) ? signal : 63;
1518     signal = (signal > -192) ? signal : -192;
1519
1520     /* Clip range of noise */
1521     noise = (noise < 63) ? noise : 63;
1522     noise = (noise > -192) ? noise : -192;
1523
1524     /* Make u8 */
1525     signal = ( signal < 0 ) ? signal + 0x100 : signal;
1526     noise = ( noise < 0 ) ? noise + 0x100 : noise;
1527
1528     iwe.u.qual.level = (u8)signal; /* -192 : 63 */
1529     iwe.u.qual.noise = (u8)noise;  /* -192 : 63 */
1530     iwe.u.qual.qual = snr;         /* 0 : 255 */
1531     iwe.u.qual.updated = 0;
1532 #if WIRELESS_EXT > 16
1533     iwe.u.qual.updated |= IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED |
1534         IW_QUAL_QUAL_UPDATED;
1535 #if WIRELESS_EXT > 18
1536     iwe.u.qual.updated |= IW_QUAL_DBM;
1537 #endif
1538 #endif
1539     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_QUAL_LEN);
1540     if (r < 0) {
1541         return r;
1542     }
1543     start_buf += r;
1544
1545     /* Add encryption capability */
1546     iwe.cmd = SIOCGIWENCODE;
1547     if (capabilities & SIG_CAP_PRIVACY) {
1548         iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1549     } else {
1550         iwe.u.data.flags = IW_ENCODE_DISABLED;
1551     }
1552     iwe.u.data.length = 0;
1553     iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
1554     r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, "");
1555     if (r < 0) {
1556         return r;
1557     }
1558     start_buf += r;
1559
1560
1561     /*
1562      * Rate : stuffing multiple values in a single event require a bit
1563      * more of magic - Jean II
1564      */
1565     current_val = start_buf + IW_EV_LCP_LEN;
1566
1567     iwe.cmd = SIOCGIWRATE;
1568     /* Those two flags are ignored... */
1569     iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1570
1571     elem = unifi_find_info_element(IE_SUPPORTED_RATES_ID,
1572             info_elems, info_elem_len);
1573     if (elem) {
1574         int e_len = elem[1];
1575         const unsigned char *e_ptr = elem + 2;
1576
1577         /*
1578          * Count how many rates we have.
1579          * Zero marks the end of the list, if the list is not truncated.
1580          */
1581         /* Max 8 values */
1582         for (i = 0; i < e_len; i++) {
1583             if (e_ptr[i] == 0) {
1584                 break;
1585             }
1586             /* Bit rate given in 500 kb/s units (+ 0x80) */
1587             iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1588             /* Add new value to event */
1589             r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1590             if (r < 0) {
1591                 return r;
1592             }
1593             current_val +=r;
1594
1595         }
1596     }
1597     elem = unifi_find_info_element(IE_EXTENDED_SUPPORTED_RATES_ID,
1598             info_elems, info_elem_len);
1599     if (elem) {
1600         int e_len = elem[1];
1601         const unsigned char *e_ptr = elem + 2;
1602
1603         /*
1604          * Count how many rates we have.
1605          * Zero marks the end of the list, if the list is not truncated.
1606          */
1607         /* Max 8 values */
1608         for (i = 0; i < e_len; i++) {
1609             if (e_ptr[i] == 0) {
1610                 break;
1611             }
1612             /* Bit rate given in 500 kb/s units (+ 0x80) */
1613             iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1614             /* Add new value to event */
1615             r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1616             if (r < 0) {
1617                 return r;
1618             }
1619             current_val +=r;
1620         }
1621     }
1622     /* Check if we added any rates event */
1623     if ((current_val - start_buf) > IW_EV_LCP_LEN) {
1624         start_buf = current_val;
1625     }
1626
1627
1628 #if WIRELESS_EXT > 17
1629     memset(&iwe, 0, sizeof(iwe));
1630     iwe.cmd = IWEVGENIE;
1631     iwe.u.data.length = info_elem_len;
1632
1633     r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, info_elems);
1634     if (r < 0) {
1635         return r;
1636     }
1637
1638     start_buf += r;
1639 #endif /* WE > 17 */
1640
1641     return (start_buf - current_ev);
1642 } /* unifi_translate_scan() */
1643
1644
1645
1646 static int
1647 unifi_giwscan(struct net_device *dev, struct iw_request_info *info,
1648               union iwreq_data *wrqu, char *extra)
1649 {
1650     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1651     unifi_priv_t *priv = interfacePriv->privPtr;
1652     struct iw_point *dwrq = &wrqu->data;
1653     int r;
1654
1655     CHECK_INITED(priv);
1656
1657     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1658        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1659        unifi_error(priv, "unifi_giwscan: not permitted in Mode %d\n",
1660                                       interfacePriv->interfaceMode);
1661        return -EPERM;
1662     }
1663
1664
1665     unifi_trace(priv, UDBG1,
1666             "unifi_giwscan: buffer (%d bytes) \n",
1667             dwrq->length);
1668     UF_RTNL_UNLOCK();
1669     r = sme_mgt_scan_results_get_async(priv, info, extra, dwrq->length);
1670     UF_RTNL_LOCK();
1671     if (r < 0) {
1672         unifi_trace(priv, UDBG1,
1673                 "unifi_giwscan: buffer (%d bytes) not big enough.\n",
1674                 dwrq->length);
1675         return r;
1676     }
1677
1678     dwrq->length = r;
1679     dwrq->flags = 0;
1680
1681     return 0;
1682 } /* unifi_giwscan() */
1683
1684
1685 /*
1686  * ---------------------------------------------------------------------------
1687  *  unifi_siwessid
1688  *
1689  *      Request to join a network or start and AdHoc.
1690  *
1691  *  Arguments:
1692  *      dev             Pointer to network device struct.
1693  *      info            Pointer to broken-out ioctl request.
1694  *      data            Pointer to argument data.
1695  *      essid           Pointer to string giving name of network to join
1696  *                      or start
1697  *
1698  *  Returns:
1699  *      0 on success and everything complete
1700  *      -EINPROGRESS to have the higher level call the commit method.
1701  * ---------------------------------------------------------------------------
1702  */
1703 static int
1704 unifi_siwessid(struct net_device *dev, struct iw_request_info *info,
1705                struct iw_point *data, char *essid)
1706 {
1707     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1708     unifi_priv_t *priv = interfacePriv->privPtr;
1709     int len;
1710     int err = 0;
1711
1712     func_enter();
1713     CHECK_INITED(priv);
1714
1715     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1716        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1717        unifi_error(priv, "unifi_siwessid: not permitted in Mode %d\n",
1718                                       interfacePriv->interfaceMode);
1719        return -EPERM;
1720     }
1721
1722
1723     len = 0;
1724     if (data->flags & 1) {
1725         /* Limit length  */
1726         len = data->length;
1727         if (len > UNIFI_MAX_SSID_LEN) {
1728             len = UNIFI_MAX_SSID_LEN;
1729         }
1730     }
1731
1732 #ifdef UNIFI_DEBUG
1733     {
1734         char essid_str[UNIFI_MAX_SSID_LEN+1];
1735         int i;
1736
1737         for (i = 0; i < len; i++) {
1738             essid_str[i] = (isprint(essid[i]) ? essid[i] : '?');
1739         }
1740         essid_str[i] = '\0';
1741
1742         unifi_trace(priv, UDBG1, "unifi_siwessid: asked for '%*s' (%d)\n", len, essid_str, len);
1743         unifi_trace(priv, UDBG2, " with authModeMask = %d", priv->connection_config.authModeMask);
1744     }
1745 #endif
1746
1747     memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1748     if (len) {
1749         if (essid[len - 1] == 0) {
1750             len --;
1751         }
1752
1753         memcpy(priv->connection_config.ssid.ssid, essid, len);
1754         priv->connection_config.ssid.length = len;
1755
1756     } else {
1757         priv->connection_config.ssid.length = 0;
1758     }
1759
1760     UF_RTNL_UNLOCK();
1761     err = sme_mgt_connect(priv);
1762     UF_RTNL_LOCK();
1763     if (err) {
1764         unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err);
1765         func_exit();
1766         return convert_sme_error(err);
1767     }
1768
1769     func_exit();
1770     return 0;
1771 } /* unifi_siwessid() */
1772
1773
1774 static int
1775 unifi_giwessid(struct net_device *dev, struct iw_request_info *info,
1776                union iwreq_data *wrqu, char *essid)
1777 {
1778     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1779     unifi_priv_t *priv = interfacePriv->privPtr;
1780     struct iw_point *data = &wrqu->essid;
1781     CsrWifiSmeConnectionInfo connectionInfo;
1782     int r = 0;
1783
1784     func_enter();
1785     unifi_trace(priv, UDBG2, "unifi_giwessid\n");
1786     CHECK_INITED(priv);
1787
1788     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1789        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1790        unifi_error(priv, "unifi_giwessid: not permitted in Mode %d\n",
1791                                       interfacePriv->interfaceMode);
1792        return -EPERM;
1793     }
1794
1795     UF_RTNL_UNLOCK();
1796     r = sme_mgt_connection_info_get(priv, &connectionInfo);
1797     UF_RTNL_LOCK();
1798
1799     if (r == 0) {
1800         data->length = connectionInfo.ssid.length;
1801         strncpy(essid,
1802                 connectionInfo.ssid.ssid,
1803                 data->length);
1804         data->flags = 1;            /* active */
1805
1806         unifi_trace(priv, UDBG2, "unifi_giwessid: %.*s\n",
1807                 data->length, essid);
1808     }
1809
1810     func_exit();
1811
1812     return 0;
1813 } /* unifi_giwessid() */
1814
1815
1816 static int
1817 unifi_siwrate(struct net_device *dev, struct iw_request_info *info,
1818               union iwreq_data *wrqu, char *extra)
1819 {
1820     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1821     unifi_priv_t *priv = interfacePriv->privPtr;
1822     struct iw_param *args = &wrqu->bitrate;
1823     CsrWifiSmeMibConfig mibConfig;
1824     int r;
1825
1826     func_enter();
1827
1828     CHECK_INITED(priv);
1829     unifi_trace(priv, UDBG2, "unifi_siwrate\n");
1830
1831     /*
1832      * If args->fixed == 0, value is max rate or -1 for best
1833      * If args->fixed == 1, value is rate to set or -1 for best
1834      * args->disabled and args->flags are not used in SIOCSIWRATE
1835      */
1836
1837     /* Get, modify and set the MIB data */
1838     UF_RTNL_UNLOCK();
1839     r = sme_mgt_mib_config_get(priv, &mibConfig);
1840     UF_RTNL_LOCK();
1841     if (r) {
1842         unifi_error(priv, "unifi_siwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1843         return r;
1844     }
1845
1846     /* Default to auto rate algorithm */
1847     /* in 500Kbit/s, 0 means auto */
1848     mibConfig.unifiFixTxDataRate = 0;
1849
1850     if (args->value != -1) {
1851         mibConfig.unifiFixTxDataRate = args->value / 500000;
1852     }
1853
1854     /* 1 means rate is a maximum, 2 means rate is a set value */
1855     if (args->fixed == 1) {
1856         mibConfig.unifiFixMaxTxDataRate = 0;
1857     } else {
1858         mibConfig.unifiFixMaxTxDataRate = 1;
1859     }
1860     UF_RTNL_UNLOCK();
1861     r = sme_mgt_mib_config_set(priv, &mibConfig);
1862     UF_RTNL_LOCK();
1863     if (r) {
1864         unifi_error(priv, "unifi_siwrate: Set CsrWifiSmeMibConfigValue failed.\n");
1865         return r;
1866     }
1867
1868     func_exit();
1869
1870     return 0;
1871 } /* unifi_siwrate() */
1872
1873
1874
1875 static int
1876 unifi_giwrate(struct net_device *dev, struct iw_request_info *info,
1877               union iwreq_data *wrqu, char *extra)
1878 {
1879     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1880     unifi_priv_t *priv = interfacePriv->privPtr;
1881     struct iw_param *args = &wrqu->bitrate;
1882     int r;
1883     int bitrate, flag;
1884     CsrWifiSmeMibConfig mibConfig;
1885     CsrWifiSmeConnectionStats connectionStats;
1886
1887     func_enter();
1888     unifi_trace(priv, UDBG2, "unifi_giwrate\n");
1889     CHECK_INITED(priv);
1890
1891     flag = 0;
1892     bitrate = 0;
1893     UF_RTNL_UNLOCK();
1894     r = sme_mgt_mib_config_get(priv, &mibConfig);
1895     UF_RTNL_LOCK();
1896     if (r) {
1897         unifi_error(priv, "unifi_giwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1898         return r;
1899     }
1900
1901     bitrate = mibConfig.unifiFixTxDataRate;
1902     flag = mibConfig.unifiFixMaxTxDataRate;
1903
1904     /* Used the value returned by the SME if MIB returns 0 */
1905     if (bitrate == 0) {
1906         UF_RTNL_UNLOCK();
1907         r = sme_mgt_connection_stats_get(priv, &connectionStats);
1908         UF_RTNL_LOCK();
1909         /* Ignore errors, we may be disconnected */
1910         if (r == 0) {
1911             bitrate = connectionStats.unifiTxDataRate;
1912         }
1913     }
1914
1915     args->value = bitrate * 500000;
1916     args->fixed = !flag;
1917
1918     func_exit();
1919
1920     return 0;
1921 } /* unifi_giwrate() */
1922
1923
1924 static int
1925 unifi_siwrts(struct net_device *dev, struct iw_request_info *info,
1926              union iwreq_data *wrqu, char *extra)
1927 {
1928     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1929     unifi_priv_t *priv = interfacePriv->privPtr;
1930     int val = wrqu->rts.value;
1931     int r = 0;
1932     CsrWifiSmeMibConfig mibConfig;
1933
1934     unifi_trace(priv, UDBG2, "unifi_siwrts\n");
1935     CHECK_INITED(priv);
1936
1937     if (wrqu->rts.disabled) {
1938         val = 2347;
1939     }
1940
1941     if ( (val < 0) || (val > 2347) )
1942     {
1943         return -EINVAL;
1944     }
1945
1946     /* Get, modify and set the MIB data */
1947     UF_RTNL_UNLOCK();
1948     r = sme_mgt_mib_config_get(priv, &mibConfig);
1949     UF_RTNL_LOCK();
1950     if (r) {
1951         unifi_error(priv, "unifi_siwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1952         return r;
1953     }
1954     mibConfig.dot11RtsThreshold = val;
1955     UF_RTNL_UNLOCK();
1956     r = sme_mgt_mib_config_set(priv, &mibConfig);
1957     UF_RTNL_LOCK();
1958     if (r) {
1959         unifi_error(priv, "unifi_siwrts: Set CsrWifiSmeMibConfigValue failed.\n");
1960         return r;
1961     }
1962
1963     return 0;
1964 }
1965
1966
1967 static int
1968 unifi_giwrts(struct net_device *dev, struct iw_request_info *info,
1969              union iwreq_data *wrqu, char *extra)
1970 {
1971     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1972     unifi_priv_t *priv = interfacePriv->privPtr;
1973     int r;
1974     int rts_thresh;
1975     CsrWifiSmeMibConfig mibConfig;
1976
1977     unifi_trace(priv, UDBG2, "unifi_giwrts\n");
1978     CHECK_INITED(priv);
1979
1980     UF_RTNL_UNLOCK();
1981     r = sme_mgt_mib_config_get(priv, &mibConfig);
1982     UF_RTNL_LOCK();
1983     if (r) {
1984         unifi_error(priv, "unifi_giwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1985         return r;
1986     }
1987
1988     rts_thresh = mibConfig.dot11RtsThreshold;
1989     if (rts_thresh > 2347) {
1990         rts_thresh = 2347;
1991     }
1992
1993     wrqu->rts.value = rts_thresh;
1994     wrqu->rts.disabled = (rts_thresh == 2347);
1995     wrqu->rts.fixed = 1;
1996
1997     return 0;
1998 }
1999
2000
2001 static int
2002 unifi_siwfrag(struct net_device *dev, struct iw_request_info *info,
2003               union iwreq_data *wrqu, char *extra)
2004 {
2005     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2006     unifi_priv_t *priv = interfacePriv->privPtr;
2007     int val = wrqu->frag.value;
2008     int r = 0;
2009     CsrWifiSmeMibConfig mibConfig;
2010
2011     unifi_trace(priv, UDBG2, "unifi_siwfrag\n");
2012     CHECK_INITED(priv);
2013
2014     if (wrqu->frag.disabled)
2015         val = 2346;
2016
2017     if ( (val < 256) || (val > 2347) )
2018         return -EINVAL;
2019
2020     /* Get, modify and set the MIB data */
2021     UF_RTNL_UNLOCK();
2022     r = sme_mgt_mib_config_get(priv, &mibConfig);
2023     UF_RTNL_LOCK();
2024     if (r) {
2025         unifi_error(priv, "unifi_siwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
2026         return r;
2027     }
2028     /* Fragmentation Threashold must be even */
2029     mibConfig.dot11FragmentationThreshold = (val & ~0x1);
2030     UF_RTNL_UNLOCK();
2031     r = sme_mgt_mib_config_set(priv, &mibConfig);
2032     UF_RTNL_LOCK();
2033     if (r) {
2034         unifi_error(priv, "unifi_siwfrag: Set CsrWifiSmeMibConfigValue failed.\n");
2035         return r;
2036     }
2037
2038     return 0;
2039 }
2040
2041
2042 static int
2043 unifi_giwfrag(struct net_device *dev, struct iw_request_info *info,
2044               union iwreq_data *wrqu, char *extra)
2045 {
2046     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2047     unifi_priv_t *priv = interfacePriv->privPtr;
2048     int r;
2049     int frag_thresh;
2050     CsrWifiSmeMibConfig mibConfig;
2051
2052     unifi_trace(priv, UDBG2, "unifi_giwfrag\n");
2053     CHECK_INITED(priv);
2054
2055     UF_RTNL_UNLOCK();
2056     r = sme_mgt_mib_config_get(priv, &mibConfig);
2057     UF_RTNL_LOCK();
2058     if (r) {
2059         unifi_error(priv, "unifi_giwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
2060         return r;
2061     }
2062
2063     frag_thresh = mibConfig.dot11FragmentationThreshold;
2064
2065     /* Build the return structure */
2066     wrqu->frag.value = frag_thresh;
2067     wrqu->frag.disabled = (frag_thresh >= 2346);
2068     wrqu->frag.fixed = 1;
2069
2070     return 0;
2071 }
2072
2073
2074 static int
2075 unifi_siwencode(struct net_device *dev, struct iw_request_info *info,
2076                 union iwreq_data *wrqu, char *extra)
2077 {
2078     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2079     unifi_priv_t *priv = interfacePriv->privPtr;
2080     struct iw_point *erq = &wrqu->encoding;
2081     int index;
2082     int rc = 0;
2083     int privacy = -1;
2084     CsrWifiSmeKey sme_key;
2085
2086     func_enter();
2087     unifi_trace(priv, UDBG2, "unifi_siwencode\n");
2088
2089     CHECK_INITED(priv);
2090
2091     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2092        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2093        unifi_error(priv, "unifi_siwencode: not permitted in Mode %d\n",
2094                                       interfacePriv->interfaceMode);
2095        return -EPERM;
2096     }
2097
2098
2099     /*
2100      * Key index is encoded in the flags.
2101      * 0 - use current default,
2102      * 1-4 - if a key value is given set that key
2103      *       if not use that key
2104      */
2105     index = (erq->flags & IW_ENCODE_INDEX);  /* key number, 1-4 */
2106     if ((index < 0) || (index > 4)) {
2107         unifi_error(priv, "unifi_siwencode: Request to set an invalid key (index:%d)", index);
2108         return -EINVAL;
2109     }
2110
2111     /*
2112      * Basic checking: do we have a key to set ?
2113      * The IW_ENCODE_NOKEY flag is set when no key is present (only change flags),
2114      * but older versions rely on sending a key id 1-4.
2115      */
2116     if (erq->length > 0) {
2117
2118         /* Check the size of the key */
2119         if ((erq->length > LARGE_KEY_SIZE) || (erq->length < SMALL_KEY_SIZE)) {
2120             unifi_error(priv, "unifi_siwencode: Request to set an invalid key (length:%d)",
2121                         erq->length);
2122             return -EINVAL;
2123         }
2124
2125         /* Check the index (none (i.e. 0) means use current) */
2126         if ((index < 1) || (index > 4)) {
2127             /* If we do not have a previous key, use 1 as default */
2128             if (!priv->wep_tx_key_index) {
2129                 priv->wep_tx_key_index = 1;
2130             }
2131             index = priv->wep_tx_key_index;
2132         }
2133
2134         /* If we didn't have a key and a valid index is set, we want to remember it*/
2135         if (!priv->wep_tx_key_index) {
2136             priv->wep_tx_key_index = index;
2137         }
2138
2139         unifi_trace(priv, UDBG1, "Tx key Index is %d\n", priv->wep_tx_key_index);
2140
2141         privacy = 1;
2142
2143         /* Check if the key is not marked as invalid */
2144         if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
2145
2146             unifi_trace(priv, UDBG1, "New %s key (len=%d, index=%d)\n",
2147                         (priv->wep_tx_key_index == index) ? "tx" : "",
2148                         erq->length, index);
2149
2150             sme_key.wepTxKey = (priv->wep_tx_key_index == index);
2151             if (priv->wep_tx_key_index == index) {
2152                 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2153             } else {
2154                 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2155             }
2156             /* Key index is zero based in SME but 1 based in wext */
2157             sme_key.keyIndex = (index - 1);
2158             sme_key.keyLength = erq->length;
2159             sme_key.authenticator = 0;
2160             memset(sme_key.address.a, 0xFF, ETH_ALEN);
2161             memcpy(sme_key.key, extra, erq->length);
2162
2163             UF_RTNL_UNLOCK();
2164             rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2165             UF_RTNL_LOCK();
2166             if (rc) {
2167                 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2168                 return convert_sme_error(rc);
2169             }
2170
2171             /* Store the key to be reported by the SIOCGIWENCODE handler */
2172             priv->wep_keys[index - 1].len = erq->length;
2173             memcpy(priv->wep_keys[index - 1].key, extra, erq->length);
2174         }
2175     } else {
2176         /*
2177          * No additional key data, so it must be a request to change the
2178          * active key.
2179          */
2180         if (index != 0) {
2181             unifi_trace(priv, UDBG1, "Tx key Index is %d\n", index - 1);
2182
2183             /* Store the index to be reported by the SIOCGIWENCODE handler */
2184             priv->wep_tx_key_index = index;
2185
2186             sme_key.wepTxKey = 1;
2187             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2188
2189             /* Key index is zero based in SME but 1 based in wext */
2190             sme_key.keyIndex = (index - 1);
2191             sme_key.keyLength = 0;
2192             sme_key.authenticator = 0;
2193             UF_RTNL_UNLOCK();
2194             rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2195             UF_RTNL_LOCK();
2196             if (rc) {
2197                 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2198                 return convert_sme_error(rc);
2199             }
2200
2201             /* Turn on encryption */
2202             privacy = 1;
2203         }
2204     }
2205
2206     /* Read the flags */
2207     if (erq->flags & IW_ENCODE_DISABLED) {
2208         /* disable encryption */
2209         unifi_trace(priv, UDBG1, "disable WEP encryption\n");
2210         privacy = 0;
2211
2212         priv->wep_tx_key_index = 0;
2213
2214         unifi_trace(priv, UDBG1, "IW_ENCODE_DISABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2215         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2216     }
2217
2218     if (erq->flags & IW_ENCODE_RESTRICTED) {
2219         /* Use shared key auth */
2220         unifi_trace(priv, UDBG1, "IW_ENCODE_RESTRICTED: CSR_WIFI_SME_AUTH_MODE_80211_SHARED\n");
2221         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2222
2223         /* Turn on encryption */
2224         privacy = 1;
2225     }
2226     if (erq->flags & IW_ENCODE_OPEN) {
2227         unifi_trace(priv, UDBG1, "IW_ENCODE_OPEN: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2228         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2229     }
2230
2231     /* Commit the changes to flags if needed */
2232     if (privacy != -1) {
2233         priv->connection_config.privacyMode = privacy ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2234         priv->connection_config.encryptionModeMask = privacy ? (CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 |
2235                 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 |
2236                 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2237                 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104) :
2238             CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2239     }
2240
2241     func_exit_r(rc);
2242     return convert_sme_error(rc);
2243
2244 } /* unifi_siwencode() */
2245
2246
2247
2248 static int
2249 unifi_giwencode(struct net_device *dev, struct iw_request_info *info,
2250                 union iwreq_data *wrqu, char *extra)
2251 {
2252     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2253     unifi_priv_t *priv = interfacePriv->privPtr;
2254     struct iw_point *erq = &wrqu->encoding;
2255
2256     unifi_trace(priv, UDBG2, "unifi_giwencode\n");
2257
2258     CHECK_INITED(priv);
2259
2260     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2261        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2262        unifi_error(priv, "unifi_giwencode: not permitted in Mode %d\n",
2263                                       interfacePriv->interfaceMode);
2264        return -EPERM;
2265     }
2266
2267
2268     if (priv->connection_config.authModeMask == CSR_WIFI_SME_AUTH_MODE_80211_SHARED) {
2269         erq->flags = IW_ENCODE_RESTRICTED;
2270     }
2271     else {
2272         if (priv->connection_config.privacyMode == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) {
2273             erq->flags = IW_ENCODE_DISABLED;
2274         } else {
2275             erq->flags = IW_ENCODE_OPEN;
2276         }
2277     }
2278
2279     erq->length = 0;
2280
2281     if (erq->flags != IW_ENCODE_DISABLED) {
2282         int index = priv->wep_tx_key_index;
2283
2284         if ((index > 0) && (index <= NUM_WEPKEYS)) {
2285             erq->flags |= (index & IW_ENCODE_INDEX);
2286             erq->length = priv->wep_keys[index - 1].len;
2287             memcpy(extra, priv->wep_keys[index - 1].key, erq->length);
2288         } else {
2289             unifi_notice(priv, "unifi_giwencode: Surprise, do not have a valid key index (%d)\n",
2290                          index);
2291         }
2292     }
2293
2294     return 0;
2295 } /* unifi_giwencode() */
2296
2297
2298 static int
2299 unifi_siwpower(struct net_device *dev, struct iw_request_info *info,
2300                union iwreq_data *wrqu, char *extra)
2301 {
2302     struct iw_param *args = &wrqu->power;
2303     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2304     unifi_priv_t *priv = interfacePriv->privPtr;
2305     int listen_interval, wake_for_dtim;
2306     int r = 0;
2307     CsrWifiSmePowerConfig powerConfig;
2308
2309     unifi_trace(priv, UDBG2, "unifi_siwpower\n");
2310
2311     CHECK_INITED(priv);
2312
2313     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2314        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2315        unifi_error(priv, "unifi_siwpower: not permitted in Mode %d\n",
2316                                       interfacePriv->interfaceMode);
2317        return -EPERM;
2318     }
2319
2320     UF_RTNL_UNLOCK();
2321     r = sme_mgt_power_config_get(priv, &powerConfig);
2322     UF_RTNL_LOCK();
2323     if (r) {
2324         unifi_error(priv, "unifi_siwpower: Get unifi_PowerConfigValue failed.\n");
2325         return r;
2326     }
2327
2328     listen_interval = -1;
2329     wake_for_dtim = -1;
2330     if (args->disabled) {
2331         powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
2332     }
2333     else
2334     {
2335         powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
2336
2337         switch (args->flags & IW_POWER_TYPE) {
2338             case 0:
2339                 /* not specified */
2340                 break;
2341             case IW_POWER_PERIOD:
2342                 listen_interval = args->value / 1000;
2343                 break;
2344             default:
2345                 return -EINVAL;
2346         }
2347
2348         switch (args->flags & IW_POWER_MODE) {
2349             case 0:
2350                 /* not specified */
2351                 break;
2352             case IW_POWER_UNICAST_R:
2353                 /* not interested in broadcast packets */
2354                 wake_for_dtim = 0;
2355                 break;
2356             case IW_POWER_ALL_R:
2357                 /* yes, we are interested in broadcast packets */
2358                 wake_for_dtim = 1;
2359                 break;
2360             default:
2361                 return -EINVAL;
2362         }
2363     }
2364
2365     if (listen_interval > 0) {
2366         powerConfig.listenIntervalTu = listen_interval;
2367         unifi_trace(priv, UDBG4, "unifi_siwpower: new Listen Interval = %d.\n",
2368                     powerConfig.listenIntervalTu);
2369     }
2370
2371     if (wake_for_dtim >= 0) {
2372         powerConfig.rxDtims = wake_for_dtim;
2373     }
2374     UF_RTNL_UNLOCK();
2375     r = sme_mgt_power_config_set(priv, &powerConfig);
2376     UF_RTNL_LOCK();
2377     if (r) {
2378         unifi_error(priv, "unifi_siwpower: Set unifi_PowerConfigValue failed.\n");
2379         return r;
2380     }
2381
2382     return 0;
2383 } /* unifi_siwpower() */
2384
2385
2386 static int
2387 unifi_giwpower(struct net_device *dev, struct iw_request_info *info,
2388                union iwreq_data *wrqu, char *extra)
2389 {
2390     struct iw_param *args = &wrqu->power;
2391     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2392     unifi_priv_t *priv = interfacePriv->privPtr;
2393     CsrWifiSmePowerConfig powerConfig;
2394     int r;
2395
2396     unifi_trace(priv, UDBG2, "unifi_giwpower\n");
2397
2398     CHECK_INITED(priv);
2399
2400     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2401        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2402        unifi_error(priv, "unifi_giwpower: not permitted in Mode %d\n",
2403                                       interfacePriv->interfaceMode);
2404        return -EPERM;
2405     }
2406
2407
2408     args->flags = 0;
2409     UF_RTNL_UNLOCK();
2410     r = sme_mgt_power_config_get(priv, &powerConfig);
2411     UF_RTNL_LOCK();
2412     if (r) {
2413         unifi_error(priv, "unifi_giwpower: Get unifi_PowerConfigValue failed.\n");
2414         return r;
2415     }
2416
2417     unifi_trace(priv, UDBG4, "unifi_giwpower: mode=%d\n",
2418                 powerConfig.powerSaveLevel);
2419
2420     args->disabled = (powerConfig.powerSaveLevel == CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW);
2421     if (args->disabled) {
2422         args->flags = 0;
2423         return 0;
2424     }
2425
2426     args->value = powerConfig.listenIntervalTu * 1000;
2427     args->flags |= IW_POWER_PERIOD;
2428
2429     if (powerConfig.rxDtims) {
2430         args->flags |= IW_POWER_ALL_R;
2431     } else {
2432         args->flags |= IW_POWER_UNICAST_R;
2433     }
2434
2435     return 0;
2436 } /* unifi_giwpower() */
2437
2438
2439 /*
2440  * ---------------------------------------------------------------------------
2441  *  unifi_siwcommit - handler for SIOCSIWCOMMIT
2442  *
2443  *      Apply all the parameters that have been set.
2444  *      In practice this means:
2445  *       - do a scan
2446  *       - join a network or start an AdHoc
2447  *       - authenticate and associate.
2448  *
2449  *  Arguments:
2450  *      None.
2451  *
2452  *  Returns:
2453  *      None.
2454  * ---------------------------------------------------------------------------
2455  */
2456 static int
2457 unifi_siwcommit(struct net_device *dev, struct iw_request_info *info,
2458                 union iwreq_data *wrqu, char *extra)
2459 {
2460     return 0;
2461 } /* unifi_siwcommit() */
2462
2463
2464
2465 static int
2466 unifi_siwmlme(struct net_device *dev, struct iw_request_info *info,
2467               union iwreq_data *wrqu, char *extra)
2468 {
2469     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2470     unifi_priv_t *priv = interfacePriv->privPtr;
2471     struct iw_mlme *mlme = (struct iw_mlme *)extra;
2472     func_enter();
2473
2474     unifi_trace(priv, UDBG2, "unifi_siwmlme\n");
2475     CHECK_INITED(priv);
2476
2477     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2478        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2479        unifi_error(priv, "unifi_siwmlme: not permitted in Mode %d\n",
2480                                       interfacePriv->interfaceMode);
2481        return -EPERM;
2482     }
2483
2484
2485     switch (mlme->cmd) {
2486         case IW_MLME_DEAUTH:
2487         case IW_MLME_DISASSOC:
2488             UF_RTNL_UNLOCK();
2489             sme_mgt_disconnect(priv);
2490             UF_RTNL_LOCK();
2491             break;
2492         default:
2493             func_exit_r(-EOPNOTSUPP);
2494             return -EOPNOTSUPP;
2495     }
2496
2497     func_exit();
2498     return 0;
2499 } /* unifi_siwmlme() */
2500
2501
2502 /*
2503  * ---------------------------------------------------------------------------
2504  *  unifi_siwgenie
2505  *  unifi_giwgenie
2506  *
2507  *      WPA : Generic IEEE 802.11 information element (e.g., for WPA/RSN/WMM).
2508  *      Handlers for SIOCSIWGENIE, SIOCGIWGENIE - set/get generic IE
2509  *
2510  *      The host program (e.g. wpa_supplicant) uses this call to set the
2511  *      additional IEs to accompany the next (Associate?) request.
2512  *
2513  *  Arguments:
2514  *      None.
2515  *
2516  *  Returns:
2517  *      None.
2518  *  Notes:
2519  *      From wireless.h:
2520  *        This ioctl uses struct iw_point and data buffer that includes IE id
2521  *        and len fields. More than one IE may be included in the
2522  *        request. Setting the generic IE to empty buffer (len=0) removes the
2523  *        generic IE from the driver.
2524  * ---------------------------------------------------------------------------
2525  */
2526 static int
2527 unifi_siwgenie(struct net_device *dev, struct iw_request_info *info,
2528                union iwreq_data *wrqu, char *extra)
2529 {
2530     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2531     unifi_priv_t *priv = interfacePriv->privPtr;
2532     int len;
2533
2534     func_enter();
2535     unifi_trace(priv, UDBG2, "unifi_siwgenie\n");
2536
2537     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2538        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2539        unifi_error(priv, "unifi_siwgenie: not permitted in Mode %d\n",
2540                                       interfacePriv->interfaceMode);
2541        return -EPERM;
2542     }
2543
2544
2545     if ( priv->connection_config.mlmeAssociateReqInformationElements) {
2546         kfree( priv->connection_config.mlmeAssociateReqInformationElements);
2547     }
2548     priv->connection_config.mlmeAssociateReqInformationElementsLength = 0;
2549     priv->connection_config.mlmeAssociateReqInformationElements = NULL;
2550
2551     len = wrqu->data.length;
2552     if (len == 0) {
2553         func_exit();
2554         return 0;
2555     }
2556
2557     priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL);
2558     if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) {
2559         func_exit();
2560         return -ENOMEM;
2561     }
2562
2563     priv->connection_config.mlmeAssociateReqInformationElementsLength = len;
2564     memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len);
2565
2566     func_exit();
2567     return 0;
2568 } /* unifi_siwgenie() */
2569
2570
2571 static int
2572 unifi_giwgenie(struct net_device *dev, struct iw_request_info *info,
2573                union iwreq_data *wrqu, char *extra)
2574 {
2575     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2576     unifi_priv_t *priv = interfacePriv->privPtr;
2577     int len;
2578
2579     func_enter();
2580     unifi_trace(priv, UDBG2, "unifi_giwgenie\n");
2581
2582     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2583        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2584        unifi_error(priv, "unifi_giwgenie: not permitted in Mode %d\n",
2585                                       interfacePriv->interfaceMode);
2586        return -EPERM;
2587     }
2588
2589
2590     len = priv->connection_config.mlmeAssociateReqInformationElementsLength;
2591
2592     if (len == 0) {
2593         wrqu->data.length = 0;
2594         return 0;
2595     }
2596
2597     if (wrqu->data.length < len) {
2598         return -E2BIG;
2599     }
2600
2601     wrqu->data.length = len;
2602     memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len);
2603
2604     func_exit();
2605     return 0;
2606 } /* unifi_giwgenie() */
2607
2608
2609 /*
2610  * ---------------------------------------------------------------------------
2611  *  unifi_siwauth
2612  *  unifi_giwauth
2613  *
2614  *      Handlers for SIOCSIWAUTH, SIOCGIWAUTH
2615  *      Set/get various authentication parameters.
2616  *
2617  *  Arguments:
2618  *
2619  *
2620  *  Returns:
2621  *      None.
2622  * ---------------------------------------------------------------------------
2623  */
2624 static int
2625 _unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2626                union iwreq_data *wrqu, char *extra)
2627 {
2628     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2629     unifi_priv_t *priv = interfacePriv->privPtr;
2630     CsrWifiSmeAuthModeMask new_auth;
2631
2632     func_enter();
2633     unifi_trace(priv, UDBG2, "unifi_siwauth\n");
2634
2635     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2636        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2637        unifi_error(priv, "unifi_siwauth: not permitted in Mode %d\n",
2638                                       interfacePriv->interfaceMode);
2639        return -EPERM;
2640     }
2641
2642
2643     /*
2644      * This ioctl is safe to call even when UniFi is powered off.
2645      * wpa_supplicant calls it to test whether we support WPA.
2646      */
2647
2648     switch (wrqu->param.flags & IW_AUTH_INDEX) {
2649
2650         case IW_AUTH_WPA_ENABLED:
2651             unifi_trace(priv, UDBG1, "IW_AUTH_WPA_ENABLED: %d\n", wrqu->param.value);
2652
2653             if (wrqu->param.value == 0) {
2654                 unifi_trace(priv, UDBG5, "IW_AUTH_WPA_ENABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2655                 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2656             }
2657             break;
2658
2659         case IW_AUTH_PRIVACY_INVOKED:
2660             unifi_trace(priv, UDBG1, "IW_AUTH_PRIVACY_INVOKED: %d\n", wrqu->param.value);
2661
2662             priv->connection_config.privacyMode = wrqu->param.value ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2663             if (wrqu->param.value == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED)
2664             {
2665                 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2666             }
2667             break;
2668
2669         case IW_AUTH_80211_AUTH_ALG:
2670             /*
2671                IW_AUTH_ALG_OPEN_SYSTEM      0x00000001
2672                IW_AUTH_ALG_SHARED_KEY       0x00000002
2673                IW_AUTH_ALG_LEAP             0x00000004
2674                */
2675             new_auth = 0;
2676             if (wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) {
2677                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_OPEN_SYSTEM)\n", wrqu->param.value);
2678                 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2679             }
2680             if (wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) {
2681                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_SHARED_KEY)\n", wrqu->param.value);
2682                 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2683             }
2684             if (wrqu->param.value & IW_AUTH_ALG_LEAP) {
2685                 /* Initial exchanges using open-system to set EAP */
2686                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_LEAP)\n", wrqu->param.value);
2687                 new_auth |= CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X;
2688             }
2689             if (new_auth == 0) {
2690                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: invalid value %d\n",
2691                         wrqu->param.value);
2692                 return -EINVAL;
2693             } else {
2694                 priv->connection_config.authModeMask = new_auth;
2695             }
2696             break;
2697
2698         case IW_AUTH_WPA_VERSION:
2699             unifi_trace(priv, UDBG1, "IW_AUTH_WPA_VERSION: %d\n", wrqu->param.value);
2700             priv->ignore_bssid_join = TRUE;
2701             /*
2702                IW_AUTH_WPA_VERSION_DISABLED 0x00000001
2703                IW_AUTH_WPA_VERSION_WPA      0x00000002
2704                IW_AUTH_WPA_VERSION_WPA2     0x00000004
2705                */
2706
2707             if (!(wrqu->param.value & IW_AUTH_WPA_VERSION_DISABLED)) {
2708
2709                 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2710
2711                 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA) {
2712                     unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA, WPA-PSK\n");
2713                     priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK);
2714                 }
2715                 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA2) {
2716                     unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA2, WPA2-PSK\n");
2717                     priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK);
2718                 }
2719             }
2720             break;
2721
2722         case IW_AUTH_CIPHER_PAIRWISE:
2723             unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_PAIRWISE: %d\n", wrqu->param.value);
2724             /*
2725              * one of:
2726              IW_AUTH_CIPHER_NONE        0x00000001
2727              IW_AUTH_CIPHER_WEP40       0x00000002
2728              IW_AUTH_CIPHER_TKIP        0x00000004
2729              IW_AUTH_CIPHER_CCMP        0x00000008
2730              IW_AUTH_CIPHER_WEP104      0x00000010
2731              */
2732
2733             priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2734
2735             if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2736                 priv->connection_config.encryptionModeMask |=
2737                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2738             }
2739             if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2740                 priv->connection_config.encryptionModeMask |=
2741                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2742             }
2743             if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2744                 priv->connection_config.encryptionModeMask |=
2745                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2746             }
2747             if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2748                 priv->connection_config.encryptionModeMask |=
2749                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2750             }
2751
2752             break;
2753
2754         case IW_AUTH_CIPHER_GROUP:
2755             unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_GROUP: %d\n", wrqu->param.value);
2756             /*
2757              * Use the WPA version and the group cipher suite to set the permitted
2758              * group key in the MIB. f/w uses this value to validate WPA and RSN IEs
2759              * in the probe responses from the desired BSS(ID)
2760              */
2761
2762             priv->connection_config.encryptionModeMask &= ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2763                     CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 |
2764                     CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP |
2765                     CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP);
2766             if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2767                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2768             }
2769             if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2770                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2771             }
2772             if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2773                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2774             }
2775             if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2776                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2777             }
2778
2779             break;
2780
2781         case IW_AUTH_KEY_MGMT:
2782             unifi_trace(priv, UDBG1, "IW_AUTH_KEY_MGMT: %d\n", wrqu->param.value);
2783             /*
2784                IW_AUTH_KEY_MGMT_802_1X 1
2785                IW_AUTH_KEY_MGMT_PSK    2
2786                */
2787             if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK)) {
2788                 /* Check for explicitly set mode. */
2789                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2790                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK;
2791                 }
2792                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2793                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA;
2794                 }
2795                 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA: %d\n",
2796                             priv->connection_config.authModeMask);
2797             }
2798             if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK)) {
2799                 /* Check for explicitly set mode. */
2800                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2801                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK;
2802                 }
2803                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2804                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2;
2805                 }
2806                 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA2: %d\n",
2807                             priv->connection_config.authModeMask);
2808             }
2809
2810             break;
2811         case IW_AUTH_TKIP_COUNTERMEASURES:
2812             /*
2813              * Set to true at the start of the 60 second backup-off period
2814              * following 2 MichaelMIC failures within 60s.
2815              */
2816             unifi_trace(priv, UDBG1, "IW_AUTH_TKIP_COUNTERMEASURES: %d\n", wrqu->param.value);
2817             break;
2818
2819         case IW_AUTH_DROP_UNENCRYPTED:
2820             /*
2821              * Set to true on init.
2822              * Set to false just before associate if encryption will not be
2823              * required.
2824              *
2825              * Note this is not the same as the 802.1X controlled port
2826              */
2827             unifi_trace(priv, UDBG1, "IW_AUTH_DROP_UNENCRYPTED: %d\n", wrqu->param.value);
2828             break;
2829
2830         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2831             /*
2832              * This is set by wpa_supplicant to allow unencrypted EAPOL messages
2833              * even if pairwise keys are set when not using WPA. IEEE 802.1X
2834              * specifies that these frames are not encrypted, but WPA encrypts
2835              * them when pairwise keys are in use.
2836              * I think the UniFi f/w handles this decision for us.
2837              */
2838             unifi_trace(priv, UDBG1, "IW_AUTH_RX_UNENCRYPTED_EAPOL: %d\n", wrqu->param.value);
2839             break;
2840
2841         case IW_AUTH_ROAMING_CONTROL:
2842             unifi_trace(priv, UDBG1, "IW_AUTH_ROAMING_CONTROL: %d\n", wrqu->param.value);
2843             break;
2844
2845         default:
2846             unifi_trace(priv, UDBG1, "Unsupported auth param %d to 0x%X\n",
2847                         wrqu->param.flags & IW_AUTH_INDEX,
2848                         wrqu->param.value);
2849             return -EOPNOTSUPP;
2850     }
2851
2852     unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask);
2853     func_exit();
2854
2855     return 0;
2856 } /* _unifi_siwauth() */
2857
2858
2859 static int
2860 unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2861         union iwreq_data *wrqu, char *extra)
2862 {
2863     int err = 0;
2864
2865     UF_RTNL_UNLOCK();
2866     err = _unifi_siwauth(dev, info, wrqu, extra);
2867     UF_RTNL_LOCK();
2868
2869     return err;
2870 } /* unifi_siwauth() */
2871
2872
2873 static int
2874 unifi_giwauth(struct net_device *dev, struct iw_request_info *info,
2875         union iwreq_data *wrqu, char *extra)
2876 {
2877     unifi_trace(NULL, UDBG2, "unifi_giwauth\n");
2878     return -EOPNOTSUPP;
2879 } /* unifi_giwauth() */
2880
2881 /*
2882  * ---------------------------------------------------------------------------
2883  *  unifi_siwencodeext
2884  *  unifi_giwencodeext
2885  *
2886  *      Handlers for SIOCSIWENCODEEXT, SIOCGIWENCODEEXT - set/get
2887  *      encoding token & mode
2888  *
2889  *  Arguments:
2890  *      None.
2891  *
2892  *  Returns:
2893  *      None.
2894  *
2895  *  Notes:
2896  *      For WPA/WPA2 we don't take note of the IW_ENCODE_EXT_SET_TX_KEY flag.
2897  *      This flag means "use this key to encode transmissions"; we just
2898  *      assume only one key will be set and that is the one to use.
2899  * ---------------------------------------------------------------------------
2900  */
2901 static int
2902 _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
2903         union iwreq_data *wrqu, char *extra)
2904 {
2905     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2906     unifi_priv_t *priv = interfacePriv->privPtr;
2907     struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
2908     int r = 0;
2909     unsigned char *keydata;
2910     unsigned char tkip_key[32];
2911     int keyid;
2912     unsigned char *a = (unsigned char *)ext->addr.sa_data;
2913     CsrWifiSmeKey sme_key;
2914     CsrWifiSmeKeyType key_type;
2915
2916     func_enter();
2917
2918     CHECK_INITED(priv);
2919
2920     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2921        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2922        unifi_error(priv, "unifi_siwencodeext: not permitted in Mode %d\n",
2923                                       interfacePriv->interfaceMode);
2924        return -EPERM;
2925     }
2926
2927
2928     unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n",
2929                 wrqu->encoding.flags, ext->alg, ext->ext_flags,
2930                 ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX));
2931         unifi_trace(priv, UDBG3, "              addr=%pM\n", a);
2932
2933     if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
2934         /* This means use a different key (given by key_idx) for Tx. */
2935         /* NYI */
2936         unifi_trace(priv, UDBG1, KERN_ERR "unifi_siwencodeext: NYI should change tx key id here!!\n");
2937         return -ENOTSUPP;
2938     }
2939
2940     memset(&sme_key, 0, sizeof(sme_key));
2941
2942     keydata = (unsigned char *)(ext + 1);
2943     keyid = (wrqu->encoding.flags & IW_ENCODE_INDEX);
2944
2945     /*
2946      * Check for request to delete keys for an address.
2947      */
2948     /* Pick out request for no privacy. */
2949     if (ext->alg == IW_ENCODE_ALG_NONE) {
2950
2951         unifi_trace(priv, UDBG1, "Deleting %s key %d\n",
2952                     (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? "GROUP" : "PAIRWISE",
2953                     keyid);
2954
2955         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
2956             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2957         } else {
2958             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2959         }
2960         sme_key.keyIndex = (keyid - 1);
2961         sme_key.keyLength = 0;
2962         sme_key.authenticator = 0;
2963         memcpy(sme_key.address.a, a, ETH_ALEN);
2964         UF_RTNL_UNLOCK();
2965         r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_REMOVE);
2966         UF_RTNL_LOCK();
2967         if (r) {
2968             unifi_error(priv, "Delete key request was rejected with result %d\n", r);
2969             return convert_sme_error(r);
2970         }
2971
2972         return 0;
2973     }
2974
2975     /*
2976      * Request is to set a key, not delete
2977      */
2978
2979     /* Pick out WEP and use set_wep_key(). */
2980     if (ext->alg == IW_ENCODE_ALG_WEP) {
2981         /* WEP-40, WEP-104 */
2982
2983         /* Check for valid key length */
2984         if (!((ext->key_len == 5) || (ext->key_len == 13))) {
2985             unifi_trace(priv, UDBG1, KERN_ERR "Invalid length for WEP key: %d\n", ext->key_len);
2986             return -EINVAL;
2987         }
2988
2989         unifi_trace(priv, UDBG1, "Setting WEP key %d tx:%d\n",
2990                     keyid, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY);
2991
2992         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
2993             sme_key.wepTxKey = TRUE;
2994             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2995         } else {
2996             sme_key.wepTxKey = FALSE;
2997             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2998         }
2999         sme_key.keyIndex = (keyid - 1);
3000         sme_key.keyLength = ext->key_len;
3001         sme_key.authenticator = 0;
3002         memset(sme_key.address.a, 0xFF, ETH_ALEN);
3003         memcpy(sme_key.key, keydata, ext->key_len);
3004         UF_RTNL_UNLOCK();
3005         r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
3006         UF_RTNL_LOCK();
3007         if (r) {
3008             unifi_error(priv, "siwencodeext: Set key failed (%d)", r);
3009             return convert_sme_error(r);
3010         }
3011
3012         return 0;
3013     }
3014
3015     /*
3016      *
3017      * If we reach here, we are dealing with a WPA/WPA2 key
3018      *
3019      */
3020     if (ext->key_len > 32) {
3021         return -EINVAL;
3022     }
3023
3024     /*
3025      * TKIP keys from wpa_supplicant need swapping.
3026      * What about other supplicants (when they come along)?
3027      */
3028     if ((ext->alg == IW_ENCODE_ALG_TKIP) && (ext->key_len == 32)) {
3029         memcpy(tkip_key, keydata, 16);
3030         memcpy(tkip_key + 16, keydata + 24, 8);
3031         memcpy(tkip_key + 24, keydata + 16, 8);
3032         keydata = tkip_key;
3033     }
3034
3035     key_type = (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ?
3036         CSR_WIFI_SME_KEY_TYPE_GROUP : /* Group Key */
3037         CSR_WIFI_SME_KEY_TYPE_PAIRWISE; /* Pairwise Key */
3038
3039     sme_key.keyType = key_type;
3040     sme_key.keyIndex = (keyid - 1);
3041     sme_key.keyLength = ext->key_len;
3042     sme_key.authenticator = 0;
3043     memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN);
3044     if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
3045
3046         unifi_trace(priv, UDBG5, "RSC first 6 bytes = %02X:%02X:%02X:%02X:%02X:%02X\n",
3047                     ext->rx_seq[0], ext->rx_seq[1], ext->rx_seq[2], ext->rx_seq[3], ext->rx_seq[4], ext->rx_seq[5]);
3048
3049         /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */
3050         sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0];
3051         sme_key.keyRsc[1] = ext->rx_seq[3] << 8 | ext->rx_seq[2];
3052         sme_key.keyRsc[2] = ext->rx_seq[5] << 8 | ext->rx_seq[4];
3053         sme_key.keyRsc[3] = ext->rx_seq[7] << 8 | ext->rx_seq[6];
3054
3055     }
3056
3057     memcpy(sme_key.key, keydata, ext->key_len);
3058     UF_RTNL_UNLOCK();
3059     r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
3060     UF_RTNL_LOCK();
3061     if (r) {
3062         unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
3063         return convert_sme_error(r);
3064     }
3065
3066     func_exit();
3067     return r;
3068 } /* _unifi_siwencodeext() */
3069
3070
3071 static int
3072 unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
3073         union iwreq_data *wrqu, char *extra)
3074 {
3075     int err = 0;
3076
3077     err = _unifi_siwencodeext(dev, info, wrqu, extra);
3078
3079     return err;
3080 } /* unifi_siwencodeext() */
3081
3082
3083 static int
3084 unifi_giwencodeext(struct net_device *dev, struct iw_request_info *info,
3085         union iwreq_data *wrqu, char *extra)
3086 {
3087     return -EOPNOTSUPP;
3088 } /* unifi_giwencodeext() */
3089
3090
3091 /*
3092  * ---------------------------------------------------------------------------
3093  *  unifi_siwpmksa
3094  *
3095  *      SIOCSIWPMKSA - PMKSA cache operation
3096  *      The caller passes a pmksa structure:
3097  *        - cmd         one of ADD, REMOVE, FLUSH
3098  *        - bssid       MAC address
3099  *        - pmkid       ID string (16 bytes)
3100  *
3101  *  Arguments:
3102  *      None.
3103  *
3104  *  Returns:
3105  *      None.
3106  *
3107  *  Notes:
3108  *      This is not needed since we provide a siwgenie method.
3109  * ---------------------------------------------------------------------------
3110  */
3111 #define UNIFI_PMKID_KEY_SIZE 16
3112 static int
3113 unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info,
3114         union iwreq_data *wrqu, char *extra)
3115 {
3116     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3117     unifi_priv_t *priv = interfacePriv->privPtr;
3118     struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
3119     CsrResult r = 0;
3120     CsrWifiSmePmkidList pmkid_list;
3121     CsrWifiSmePmkid pmkid;
3122     CsrWifiSmeListAction action;
3123
3124     CHECK_INITED(priv);
3125
3126     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
3127        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
3128        unifi_error(priv, "unifi_siwpmksa: not permitted in Mode %d\n",
3129                                       interfacePriv->interfaceMode);
3130        return -EPERM;
3131     }
3132
3133
3134         unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %pM\n", pmksa->cmd,
3135                 pmksa->bssid.sa_data);
3136
3137     pmkid_list.pmkids = NULL;
3138     switch (pmksa->cmd) {
3139       case IW_PMKSA_ADD:
3140         pmkid_list.pmkids = &pmkid;
3141         action = CSR_WIFI_SME_LIST_ACTION_ADD;
3142         pmkid_list.pmkidsCount = 1;
3143         memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3144         memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3145         break;
3146       case IW_PMKSA_REMOVE:
3147         pmkid_list.pmkids = &pmkid;
3148         action = CSR_WIFI_SME_LIST_ACTION_REMOVE;
3149         pmkid_list.pmkidsCount = 1;
3150         memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3151         memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3152         break;
3153       case IW_PMKSA_FLUSH:
3154         /* Replace current PMKID's with an empty list */
3155         pmkid_list.pmkidsCount = 0;
3156         action = CSR_WIFI_SME_LIST_ACTION_FLUSH;
3157         break;
3158       default:
3159         unifi_notice(priv, "SIWPMKSA: Unknown command (0x%x)\n", pmksa->cmd);
3160         return -EINVAL;
3161     }
3162
3163     /* Set the Value the pmkid's will have 1 added OR 1 removed OR be cleared at this point */
3164     UF_RTNL_UNLOCK();
3165     r = sme_mgt_pmkid(priv, action, &pmkid_list);
3166     UF_RTNL_LOCK();
3167     if (r) {
3168         unifi_error(priv, "SIWPMKSA: Set PMKID's Failed.\n");
3169     }
3170
3171     return r;
3172
3173 } /* unifi_siwpmksa() */
3174
3175
3176 /*
3177  * ---------------------------------------------------------------------------
3178  *  unifi_get_wireless_stats
3179  *
3180  *      get_wireless_stats method for Linux wireless extensions.
3181  *
3182  *  Arguments:
3183  *      dev             Pointer to associated netdevice.
3184  *
3185  *  Returns:
3186  *      Pointer to iw_statistics struct.
3187  * ---------------------------------------------------------------------------
3188  */
3189 struct iw_statistics *
3190 unifi_get_wireless_stats(struct net_device *dev)
3191 {
3192     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3193     unifi_priv_t *priv = interfacePriv->privPtr;
3194
3195     if (priv->init_progress != UNIFI_INIT_COMPLETED) {
3196         return NULL;
3197     }
3198
3199     return &priv->wext_wireless_stats;
3200 } /* unifi_get_wireless_stats() */
3201
3202
3203 /*
3204  * Structures to export the Wireless Handlers
3205  */
3206
3207 static const struct iw_priv_args unifi_private_args[] = {
3208     /*{ cmd,         set_args,                            get_args, name } */
3209     { SIOCIWS80211POWERSAVEPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3210         IW_PRIV_TYPE_NONE, "iwprivs80211ps" },
3211     { SIOCIWG80211POWERSAVEPRIV, IW_PRIV_TYPE_NONE,
3212         IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IWPRIV_POWER_SAVE_MAX_STRING, "iwprivg80211ps" },
3213     { SIOCIWS80211RELOADDEFAULTSPRIV, IW_PRIV_TYPE_NONE,
3214         IW_PRIV_TYPE_NONE, "iwprivsdefs" },
3215     { SIOCIWSSMEDEBUGPRIV, IW_PRIV_TYPE_CHAR | IWPRIV_SME_DEBUG_MAX_STRING, IW_PRIV_TYPE_NONE, "iwprivssmedebug" },
3216 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3217     { SIOCIWSCONFWAPIPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3218         IW_PRIV_TYPE_NONE, "iwprivsconfwapi" },
3219     { SIOCIWSWAPIKEYPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(unifiio_wapi_key_t),
3220         IW_PRIV_TYPE_NONE, "iwprivswpikey" },
3221 #endif
3222 #ifdef CSR_SUPPORT_WEXT_AP
3223     { SIOCIWSAPCFGPRIV, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_NONE, "AP_SET_CFG" },
3224     { SIOCIWSAPSTARTPRIV, 0,IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING,"AP_BSS_START" },
3225     { SIOCIWSAPSTOPPRIV, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0,
3226       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "AP_BSS_STOP" },
3227 #ifdef ANDROID_BUILD
3228     { SIOCIWSFWRELOADPRIV, IW_PRIV_TYPE_CHAR |256,
3229       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "WL_FW_RELOAD" },
3230     { SIOCIWSSTACKSTART, 0,
3231       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "START" },
3232     { SIOCIWSSTACKSTOP, 0,
3233       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "STOP" },
3234 #endif /* ANDROID_BUILD */
3235 #endif /* CSR_SUPPORT_WEXT_AP */
3236 };
3237
3238 static const iw_handler unifi_handler[] =
3239 {
3240     (iw_handler) unifi_siwcommit,           /* SIOCSIWCOMMIT */
3241     (iw_handler) unifi_giwname,             /* SIOCGIWNAME */
3242     (iw_handler) NULL,                      /* SIOCSIWNWID */
3243     (iw_handler) NULL,                      /* SIOCGIWNWID */
3244     (iw_handler) unifi_siwfreq,             /* SIOCSIWFREQ */
3245     (iw_handler) unifi_giwfreq,             /* SIOCGIWFREQ */
3246     (iw_handler) unifi_siwmode,             /* SIOCSIWMODE */
3247     (iw_handler) unifi_giwmode,             /* SIOCGIWMODE */
3248     (iw_handler) NULL,                      /* SIOCSIWSENS */
3249     (iw_handler) NULL,                      /* SIOCGIWSENS */
3250     (iw_handler) NULL,                      /* SIOCSIWRANGE */
3251     (iw_handler) unifi_giwrange,            /* SIOCGIWRANGE */
3252     (iw_handler) NULL,                      /* SIOCSIWPRIV */
3253     (iw_handler) NULL,                      /* SIOCGIWPRIV */
3254     (iw_handler) NULL,                      /* SIOCSIWSTATS */
3255     (iw_handler) NULL,                      /* SIOCGIWSTATS */
3256     (iw_handler) NULL,                      /* SIOCSIWSPY */
3257     (iw_handler) NULL,                      /* SIOCGIWSPY */
3258     (iw_handler) NULL,                      /* SIOCSIWTHRSPY */
3259     (iw_handler) NULL,                      /* SIOCGIWTHRSPY */
3260     (iw_handler) unifi_siwap,               /* SIOCSIWAP */
3261     (iw_handler) unifi_giwap,               /* SIOCGIWAP */
3262 #if WIRELESS_EXT > 17
3263     /* WPA : IEEE 802.11 MLME requests */
3264     unifi_siwmlme,              /* SIOCSIWMLME, request MLME operation */
3265 #else
3266     (iw_handler) NULL,                      /* -- hole -- */
3267 #endif
3268     (iw_handler) NULL,                      /* SIOCGIWAPLIST */
3269     (iw_handler) unifi_siwscan,             /* SIOCSIWSCAN */
3270     (iw_handler) unifi_giwscan,             /* SIOCGIWSCAN */
3271     (iw_handler) unifi_siwessid,            /* SIOCSIWESSID */
3272     (iw_handler) unifi_giwessid,            /* SIOCGIWESSID */
3273     (iw_handler) NULL,                      /* SIOCSIWNICKN */
3274     (iw_handler) NULL,                      /* SIOCGIWNICKN */
3275     (iw_handler) NULL,                      /* -- hole -- */
3276     (iw_handler) NULL,                      /* -- hole -- */
3277     unifi_siwrate,                          /* SIOCSIWRATE */
3278     unifi_giwrate,                          /* SIOCGIWRATE */
3279     unifi_siwrts,                           /* SIOCSIWRTS */
3280     unifi_giwrts,                           /* SIOCGIWRTS */
3281     unifi_siwfrag,                          /* SIOCSIWFRAG */
3282     unifi_giwfrag,                          /* SIOCGIWFRAG */
3283     (iw_handler) NULL,                      /* SIOCSIWTXPOW */
3284     (iw_handler) NULL,                      /* SIOCGIWTXPOW */
3285     (iw_handler) NULL,                      /* SIOCSIWRETRY */
3286     (iw_handler) NULL,                      /* SIOCGIWRETRY */
3287     unifi_siwencode,                        /* SIOCSIWENCODE */
3288     unifi_giwencode,                        /* SIOCGIWENCODE */
3289     unifi_siwpower,                         /* SIOCSIWPOWER */
3290     unifi_giwpower,                         /* SIOCGIWPOWER */
3291 #if WIRELESS_EXT > 17
3292     (iw_handler) NULL,                      /* -- hole -- */
3293     (iw_handler) NULL,                      /* -- hole -- */
3294
3295     /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). */
3296     unifi_siwgenie,             /* SIOCSIWGENIE */      /* set generic IE */
3297     unifi_giwgenie,             /* SIOCGIWGENIE */      /* get generic IE */
3298
3299     /* WPA : Authentication mode parameters */
3300     unifi_siwauth,              /* SIOCSIWAUTH */       /* set authentication mode params */
3301     unifi_giwauth,              /* SIOCGIWAUTH */       /* get authentication mode params */
3302
3303     /* WPA : Extended version of encoding configuration */
3304     unifi_siwencodeext,         /* SIOCSIWENCODEEXT */  /* set encoding token & mode */
3305     unifi_giwencodeext,         /* SIOCGIWENCODEEXT */  /* get encoding token & mode */
3306
3307     /* WPA2 : PMKSA cache management */
3308     unifi_siwpmksa,             /* SIOCSIWPMKSA */      /* PMKSA cache operation */
3309     (iw_handler) NULL,          /* -- hole -- */
3310 #endif /* WIRELESS_EXT > 17 */
3311 };
3312
3313
3314 static const iw_handler unifi_private_handler[] =
3315 {
3316     iwprivs80211ps,                 /* SIOCIWFIRSTPRIV */
3317     iwprivg80211ps,                 /* SIOCIWFIRSTPRIV + 1 */
3318     iwprivsdefs,                    /* SIOCIWFIRSTPRIV + 2 */
3319     (iw_handler) NULL,
3320 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3321     iwprivsconfwapi,                /* SIOCIWFIRSTPRIV + 4 */
3322     (iw_handler) NULL,              /* SIOCIWFIRSTPRIV + 5 */
3323     iwprivswpikey,                  /* SIOCIWFIRSTPRIV + 6 */
3324 #else
3325     (iw_handler) NULL,
3326     (iw_handler) NULL,
3327     (iw_handler) NULL,
3328 #endif
3329     (iw_handler) NULL,
3330     iwprivssmedebug,                /* SIOCIWFIRSTPRIV + 8 */
3331 #ifdef CSR_SUPPORT_WEXT_AP
3332     (iw_handler) NULL,
3333     iwprivsapconfig,
3334     (iw_handler) NULL,
3335     iwprivsapstart,
3336     (iw_handler) NULL,
3337     iwprivsapstop,
3338     (iw_handler) NULL,
3339 #ifdef ANDROID_BUILD
3340     iwprivsapfwreload,
3341     (iw_handler) NULL,
3342     iwprivsstackstart,
3343     (iw_handler) NULL,
3344     iwprivsstackstop,
3345 #else
3346     (iw_handler) NULL,
3347     (iw_handler) NULL,
3348     (iw_handler) NULL,
3349     (iw_handler) NULL,
3350     (iw_handler) NULL,
3351 #endif /* ANDROID_BUILD */
3352 #else
3353     (iw_handler) NULL,
3354     (iw_handler) NULL,
3355     (iw_handler) NULL,
3356     (iw_handler) NULL,
3357     (iw_handler) NULL,
3358     (iw_handler) NULL,
3359     (iw_handler) NULL,
3360     (iw_handler) NULL,
3361     (iw_handler) NULL,
3362     (iw_handler) NULL,
3363     (iw_handler) NULL,
3364     (iw_handler) NULL,
3365 #endif /* CSR_SUPPORT_WEXT_AP */
3366 };
3367
3368 struct iw_handler_def unifi_iw_handler_def =
3369 {
3370     .num_standard       = sizeof(unifi_handler) / sizeof(iw_handler),
3371     .num_private        = sizeof(unifi_private_handler) / sizeof(iw_handler),
3372     .num_private_args   = sizeof(unifi_private_args) / sizeof(struct iw_priv_args),
3373     .standard           = (iw_handler *) unifi_handler,
3374     .private            = (iw_handler *) unifi_private_handler,
3375     .private_args       = (struct iw_priv_args *) unifi_private_args,
3376 #if IW_HANDLER_VERSION >= 6
3377     .get_wireless_stats = unifi_get_wireless_stats,
3378 #endif
3379 };
3380
3381