Merge tag 'tty-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
[firefly-linux-kernel-4.4.55.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
804     unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" );
805
806     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
807        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
808        unifi_error(priv, "iwprivsconfwapi: not permitted in Mode %d\n",
809                                       interfacePriv->interfaceMode);
810        return -EPERM;
811     }
812
813     enable = *(u8*)(extra);
814
815     if (enable) {
816         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
817         priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
818         priv->connection_config.encryptionModeMask |=
819             CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4;
820     } else {
821         priv->connection_config.authModeMask &= ~(CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
822         priv->connection_config.encryptionModeMask &=
823             ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4);
824     }
825
826     return 0;
827 }
828
829 static int
830 iwprivswpikey(struct net_device *dev, struct iw_request_info *info,
831         union iwreq_data *wrqu, char *extra)
832 {
833     int r = 0, i;
834     CsrWifiSmeKey key;
835     unifiio_wapi_key_t inKey;
836     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
837     unifi_priv_t *priv = interfacePriv->privPtr;
838
839     unifi_trace(priv, UDBG1, "iwprivswpikey\n" );
840
841     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
842        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
843        unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
844                                       interfacePriv->interfaceMode);
845        return -EPERM;
846     }
847
848     inKey = *(unifiio_wapi_key_t*)(extra);
849
850     if (inKey.unicastKey) {
851         key.keyType   = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
852     } else {
853         key.keyType   = CSR_WIFI_SME_KEY_TYPE_GROUP;
854     }
855
856     key.keyIndex  = inKey.keyIndex;
857
858     /* memcpy(key.keyRsc, inKey.keyRsc, 16); */
859     for (i = 0; i < 16; i+= 2)
860     {
861         key.keyRsc[i/2] = inKey.keyRsc[i+1] << 8 | inKey.keyRsc[i];
862     }
863
864     memcpy(key.address.a, inKey.address, 6);
865     key.keyLength = 32;
866     memcpy(key.key, inKey.key, 32);
867     key.authenticator = 0;
868     key.wepTxKey = 0;
869
870     unifi_trace(priv, UDBG1, "keyType = %d, keyIndex = %d, wepTxKey = %d, keyRsc = %x:%x, auth = %d, address = %x:%x, "
871                 "keylength = %d, key = %x:%x\n", key.keyType, key.keyIndex, key.wepTxKey,
872                 key.keyRsc[0], key.keyRsc[7], key.authenticator,
873                 key.address.a[0], key.address.a[5], key.keyLength, key.key[0],
874                 key.key[15]);
875
876     r = sme_mgt_key(priv, &key, CSR_WIFI_SME_LIST_ACTION_ADD);
877     if (r) {
878         unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
879         return convert_sme_error(r);
880     }
881
882     return r;
883 }
884 #endif
885
886
887 static int
888 unifi_giwname(struct net_device *dev, struct iw_request_info *info,
889         union iwreq_data *wrqu, char *extra)
890 {
891     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
892     unifi_priv_t *priv = interfacePriv->privPtr;
893     char *name = wrqu->name;
894     unifi_trace(priv, UDBG2, "unifi_giwname\n");
895
896     if (priv->if_index == CSR_INDEX_5G) {
897         strcpy(name, "IEEE 802.11-a");
898     } else {
899         strcpy(name, "IEEE 802.11-bgn");
900     }
901     return 0;
902 } /* unifi_giwname() */
903
904
905 static int
906 unifi_siwfreq(struct net_device *dev, struct iw_request_info *info,
907         union iwreq_data *wrqu, char *extra)
908 {
909     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
910     unifi_priv_t *priv = interfacePriv->privPtr;
911     struct iw_freq *freq = (struct iw_freq *)wrqu;
912
913     unifi_trace(priv, UDBG2, "unifi_siwfreq\n");
914
915     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
916        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
917        unifi_error(priv, "unifi_siwfreq: not permitted in Mode %d\n",
918                                       interfacePriv->interfaceMode);
919        return -EPERM;
920     }
921
922
923     /*
924      * Channel is stored in the connection configuration,
925      * and set later when ask for a connection.
926      */
927     if ((freq->e == 0) && (freq->m <= 1000)) {
928         priv->connection_config.adhocChannel = freq->m;
929     } else {
930         priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e);
931     }
932
933     return 0;
934 } /* unifi_siwfreq() */
935
936
937 static int
938 unifi_giwfreq(struct net_device *dev, struct iw_request_info *info,
939         union iwreq_data *wrqu, char *extra)
940 {
941     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
942     unifi_priv_t *priv = interfacePriv->privPtr;
943     struct iw_freq *freq = (struct iw_freq *)wrqu;
944     int err = 0;
945     CsrWifiSmeConnectionInfo connectionInfo;
946
947     unifi_trace(priv, UDBG2, "unifi_giwfreq\n");
948     CHECK_INITED(priv);
949
950     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
951        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
952        unifi_error(priv, "unifi_giwfreq: not permitted in Mode %d\n",
953                                       interfacePriv->interfaceMode);
954        return -EPERM;
955     }
956
957
958     UF_RTNL_UNLOCK();
959     err = sme_mgt_connection_info_get(priv, &connectionInfo);
960     UF_RTNL_LOCK();
961
962     freq->m = channel_to_mhz(connectionInfo.channelNumber,
963             (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0));
964     freq->e = 6;
965
966     return convert_sme_error(err);
967 } /* unifi_giwfreq() */
968
969
970 static int
971 unifi_siwmode(struct net_device *dev, struct iw_request_info *info,
972         union iwreq_data *wrqu, char *extra)
973 {
974     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
975     unifi_priv_t *priv = interfacePriv->privPtr;
976
977     unifi_trace(priv, UDBG2, "unifi_siwmode\n");
978
979     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
980        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
981        unifi_error(priv, "unifi_siwmode: not permitted in Mode %d\n",
982                                       interfacePriv->interfaceMode);
983        return -EPERM;
984     }
985
986
987     switch(wrqu->mode) {
988         case IW_MODE_ADHOC:
989             priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ADHOC;
990             break;
991         case IW_MODE_INFRA:
992             priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE;
993             break;
994         case IW_MODE_AUTO:
995             priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ANY_BSS;
996             break;
997         default:
998             unifi_notice(priv, "Unknown IW MODE value.\n");
999     }
1000
1001     /* Clear the SSID and BSSID configuration */
1002     priv->connection_config.ssid.length = 0;
1003     memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1004
1005     return 0;
1006 } /* unifi_siwmode() */
1007
1008
1009
1010 static int
1011 unifi_giwmode(struct net_device *dev, struct iw_request_info *info,
1012         union iwreq_data *wrqu, char *extra)
1013 {
1014     int r = 0;
1015     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1016     unifi_priv_t *priv = interfacePriv->privPtr;
1017     CsrWifiSmeConnectionConfig connectionConfig;
1018
1019     unifi_trace(priv, UDBG2, "unifi_giwmode\n");
1020     CHECK_INITED(priv);
1021
1022     unifi_trace(priv, UDBG2, "unifi_giwmode: Exisitng mode = 0x%x\n",
1023                 interfacePriv->interfaceMode);
1024     switch(interfacePriv->interfaceMode) {
1025         case CSR_WIFI_ROUTER_CTRL_MODE_STA:
1026         case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI:
1027            wrqu->mode = IW_MODE_INFRA;
1028            break;
1029         case CSR_WIFI_ROUTER_CTRL_MODE_AP:
1030         case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO:
1031             wrqu->mode = IW_MODE_MASTER;
1032             break;
1033         case CSR_WIFI_ROUTER_CTRL_MODE_IBSS:
1034             wrqu->mode = IW_MODE_ADHOC;
1035             break;
1036         case CSR_WIFI_ROUTER_CTRL_MODE_P2P:
1037         case CSR_WIFI_ROUTER_CTRL_MODE_NONE:
1038             UF_RTNL_UNLOCK();
1039             r = sme_mgt_connection_config_get(priv, &connectionConfig);
1040             UF_RTNL_LOCK();
1041             if (r == 0) {
1042                 switch(connectionConfig.bssType) {
1043                     case CSR_WIFI_SME_BSS_TYPE_ADHOC:
1044                         wrqu->mode = IW_MODE_ADHOC;
1045                         break;
1046                     case CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE:
1047                         wrqu->mode = IW_MODE_INFRA;
1048                         break;
1049                     default:
1050                         wrqu->mode = IW_MODE_AUTO;
1051                         unifi_notice(priv, "Unknown IW MODE value.\n");
1052                 }
1053             }
1054             break;
1055         default:
1056             wrqu->mode = IW_MODE_AUTO;
1057             unifi_notice(priv, "Unknown IW MODE value.\n");
1058
1059     }
1060     unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode);
1061     return r;
1062 } /* unifi_giwmode() */
1063
1064
1065
1066 static int
1067 unifi_giwrange(struct net_device *dev, struct iw_request_info *info,
1068         union iwreq_data *wrqu, char *extra)
1069 {
1070     struct iw_point *dwrq = &wrqu->data;
1071     struct iw_range *range = (struct iw_range *) extra;
1072     int i;
1073
1074     unifi_trace(NULL, UDBG2, "unifi_giwrange\n");
1075
1076     dwrq->length = sizeof(struct iw_range);
1077     memset(range, 0, sizeof(*range));
1078     range->min_nwid = 0x0000;
1079     range->max_nwid = 0x0000;
1080
1081     /*
1082      * Don't report the frequency/channel table, then the channel
1083      * number returned elsewhere will be printed as a channel number.
1084      */
1085
1086     /* Ranges of values reported in quality structs */
1087     range->max_qual.qual  = 40;         /* Max expected qual value */
1088     range->max_qual.level = -120;       /* Noise floor in dBm */
1089     range->max_qual.noise = -120;       /* Noise floor in dBm */
1090
1091
1092     /* space for IW_MAX_BITRATES (8 up to WE15, 32 later) */
1093     i = 0;
1094 #if WIRELESS_EXT > 15
1095     range->bitrate[i++] =   2 * 500000;
1096     range->bitrate[i++] =   4 * 500000;
1097     range->bitrate[i++] =  11 * 500000;
1098     range->bitrate[i++] =  22 * 500000;
1099     range->bitrate[i++] =  12 * 500000;
1100     range->bitrate[i++] =  18 * 500000;
1101     range->bitrate[i++] =  24 * 500000;
1102     range->bitrate[i++] =  36 * 500000;
1103     range->bitrate[i++] =  48 * 500000;
1104     range->bitrate[i++] =  72 * 500000;
1105     range->bitrate[i++] =  96 * 500000;
1106     range->bitrate[i++] = 108 * 500000;
1107 #else
1108     range->bitrate[i++] =   2 * 500000;
1109     range->bitrate[i++] =   4 * 500000;
1110     range->bitrate[i++] =  11 * 500000;
1111     range->bitrate[i++] =  22 * 500000;
1112     range->bitrate[i++] =  24 * 500000;
1113     range->bitrate[i++] =  48 * 500000;
1114     range->bitrate[i++] =  96 * 500000;
1115     range->bitrate[i++] = 108 * 500000;
1116 #endif /* WIRELESS_EXT < 16 */
1117     range->num_bitrates = i;
1118
1119     range->max_encoding_tokens = NUM_WEPKEYS;
1120     range->num_encoding_sizes = 2;
1121     range->encoding_size[0] = 5;
1122     range->encoding_size[1] = 13;
1123
1124     range->we_version_source = 20;
1125     range->we_version_compiled = WIRELESS_EXT;
1126
1127     /* Number of channels available in h/w */
1128     range->num_channels = 14;
1129     /* Number of entries in freq[] array */
1130     range->num_frequency = 14;
1131     for (i = 0; (i < range->num_frequency) && (i < IW_MAX_FREQUENCIES); i++) {
1132         int chan = i + 1;
1133         range->freq[i].i = chan;
1134         range->freq[i].m = channel_to_mhz(chan, 0);
1135         range->freq[i].e = 6;
1136     }
1137     if ((i+3) < IW_MAX_FREQUENCIES) {
1138         range->freq[i].i = 36;
1139         range->freq[i].m = channel_to_mhz(36, 1);
1140         range->freq[i].e = 6;
1141         range->freq[i+1].i = 40;
1142         range->freq[i+1].m = channel_to_mhz(40, 1);
1143         range->freq[i+1].e = 6;
1144         range->freq[i+2].i = 44;
1145         range->freq[i+2].m = channel_to_mhz(44, 1);
1146         range->freq[i+2].e = 6;
1147         range->freq[i+3].i = 48;
1148         range->freq[i+3].m = channel_to_mhz(48, 1);
1149         range->freq[i+3].e = 6;
1150     }
1151
1152 #if WIRELESS_EXT > 16
1153     /* Event capability (kernel + driver) */
1154     range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
1155             IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
1156             IW_EVENT_CAPA_MASK(SIOCGIWAP) |
1157             IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
1158     range->event_capa[1] = IW_EVENT_CAPA_K_1;
1159     range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
1160             IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
1161             IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
1162             IW_EVENT_CAPA_MASK(IWEVEXPIRED));
1163 #endif /* WIRELESS_EXT > 16 */
1164
1165 #if WIRELESS_EXT > 17
1166     range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1167         IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1168 #endif /* WIRELESS_EXT > 17 */
1169
1170
1171     return 0;
1172 } /* unifi_giwrange() */
1173
1174
1175 static int
1176 unifi_siwap(struct net_device *dev, struct iw_request_info *info,
1177         union iwreq_data *wrqu, char *extra)
1178 {
1179     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1180     unifi_priv_t *priv = interfacePriv->privPtr;
1181     int err = 0;
1182
1183     CHECK_INITED(priv);
1184
1185     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1186        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1187        unifi_error(priv, "unifi_siwap: not permitted in Mode %d\n",
1188                                       interfacePriv->interfaceMode);
1189        return -EPERM;
1190     }
1191
1192
1193     if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) {
1194         return -EINVAL;
1195     }
1196
1197         unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n",
1198                 wrqu->ap_addr.sa_data);
1199
1200     if (is_zero_ether_addr(wrqu->ap_addr.sa_data)) {
1201         priv->ignore_bssid_join = FALSE;
1202         err = sme_mgt_disconnect(priv);
1203         if (err) {
1204             unifi_trace(priv, UDBG4, "unifi_siwap: Disconnect failed, status %d\n", err);
1205         }
1206         return 0;
1207     }
1208
1209     if (priv->ignore_bssid_join) {
1210         unifi_trace(priv, UDBG4, "unifi_siwap: ignoring second join\n");
1211         priv->ignore_bssid_join = FALSE;
1212     } else {
1213         memcpy(priv->connection_config.bssid.a, wrqu->ap_addr.sa_data, ETH_ALEN);
1214         unifi_trace(priv, UDBG1, "unifi_siwap: Joining %X:%X:%X:%X:%X:%X\n",
1215                     priv->connection_config.bssid.a[0],
1216                     priv->connection_config.bssid.a[1],
1217                     priv->connection_config.bssid.a[2],
1218                     priv->connection_config.bssid.a[3],
1219                     priv->connection_config.bssid.a[4],
1220                     priv->connection_config.bssid.a[5]);
1221         err = sme_mgt_connect(priv);
1222         if (err) {
1223             unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err);
1224             return convert_sme_error(err);
1225         }
1226     }
1227
1228     return 0;
1229 } /* unifi_siwap() */
1230
1231
1232 static int
1233 unifi_giwap(struct net_device *dev, struct iw_request_info *info,
1234         union iwreq_data *wrqu, char *extra)
1235 {
1236     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1237     unifi_priv_t *priv = interfacePriv->privPtr;
1238     CsrWifiSmeConnectionInfo connectionInfo;
1239     int r = 0;
1240     u8 *bssid;
1241
1242     CHECK_INITED(priv);
1243     unifi_trace(priv, UDBG2, "unifi_giwap\n");
1244
1245     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1246        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1247        unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
1248                                       interfacePriv->interfaceMode);
1249        return -EPERM;
1250     }
1251
1252     UF_RTNL_UNLOCK();
1253     r = sme_mgt_connection_info_get(priv, &connectionInfo);
1254     UF_RTNL_LOCK();
1255
1256     if (r == 0) {
1257         bssid = connectionInfo.bssid.a;
1258         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1259                 unifi_trace(priv, UDBG4, "unifi_giwap: BSSID = %pM\n", bssid);
1260
1261         memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
1262     } else {
1263         memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1264     }
1265
1266     return 0;
1267 } /* unifi_giwap() */
1268
1269
1270 static int
1271 unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
1272         union iwreq_data *wrqu, char *extra)
1273 {
1274     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1275     unifi_priv_t *priv = interfacePriv->privPtr;
1276     int r;
1277     CsrWifiSsid scan_ssid;
1278     unsigned char *channel_list = NULL;
1279     int chans_good = 0;
1280 #if WIRELESS_EXT > 17
1281     struct iw_point *data = &wrqu->data;
1282     struct iw_scan_req *req = (struct iw_scan_req *) extra;
1283 #endif
1284
1285     CHECK_INITED(priv);
1286
1287     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1288        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1289        unifi_error(priv, "unifi_siwscan: not permitted in Mode %d\n",
1290                                       interfacePriv->interfaceMode);
1291        return -EPERM;
1292     }
1293
1294
1295 #if WIRELESS_EXT > 17
1296     /* Providing a valid channel list will force an active scan */
1297     if (req) {
1298         if ((req->num_channels > 0) && (req->num_channels < IW_MAX_FREQUENCIES)) {
1299             channel_list = kmalloc(req->num_channels, GFP_KERNEL);
1300             if (channel_list) {
1301                 int i;
1302                 for (i = 0; i < req->num_channels; i++) {
1303                     /* Convert frequency to channel number */
1304                     int ch = wext_freq_to_channel(req->channel_list[i].m,
1305                             req->channel_list[i].e);
1306                     if (ch) {
1307                         channel_list[chans_good++] = ch;
1308                     }
1309                 }
1310                 unifi_trace(priv, UDBG1,
1311                             "SIWSCAN: Scanning %d channels\n", chans_good);
1312             } else {
1313                 /* Fall back to scanning all */
1314                 unifi_error(priv, "SIWSCAN: Can't alloc channel_list (%d)\n",
1315                         req->num_channels);
1316             }
1317         }
1318     }
1319
1320     if (req && (data->flags & IW_SCAN_THIS_ESSID)) {
1321         memcpy(scan_ssid.ssid, req->essid, req->essid_len);
1322         scan_ssid.length = req->essid_len;
1323         unifi_trace(priv, UDBG1,
1324                     "SIWSCAN: Scanning for %.*s\n",
1325                     scan_ssid.length, scan_ssid.ssid);
1326     } else
1327 #endif
1328     {
1329         unifi_trace(priv, UDBG1, "SIWSCAN: Scanning for all APs\n");
1330         scan_ssid.length = 0;
1331     }
1332
1333     r = sme_mgt_scan_full(priv, &scan_ssid, chans_good, channel_list);
1334     if (r) {
1335         unifi_error(priv, "SIWSCAN: Scan returned error %d\n", r);
1336     } else {
1337         unifi_trace(priv, UDBG1, "SIWSCAN: Scan done\n");
1338         wext_send_scan_results_event(priv);
1339     }
1340
1341     if (channel_list) {
1342         kfree(channel_list);
1343     }
1344
1345     return r;
1346
1347 } /* unifi_siwscan() */
1348
1349
1350 static const unsigned char *
1351 unifi_find_info_element(int id, const unsigned char *info, int len)
1352 {
1353     const unsigned char *ie = info;
1354
1355     while (len > 1)
1356     {
1357         int e_id, e_len;
1358         e_id = ie[0];
1359         e_len = ie[1];
1360
1361         /* Return if we find a match */
1362         if (e_id == id)
1363         {
1364             return ie;
1365         }
1366
1367         len -= (e_len + 2);
1368         ie  += (e_len + 2);
1369     }
1370
1371     return NULL;
1372 } /* unifi_find_info_element() */
1373
1374
1375 /*
1376  * Translate scan data returned from the card to a card independent
1377  * format that the Wireless Tools will understand - Jean II
1378  */
1379 int
1380 unifi_translate_scan(struct net_device *dev,
1381                      struct iw_request_info *info,
1382                      char *current_ev, char *end_buf,
1383                      CsrWifiSmeScanResult *scan_data,
1384                      int scan_index)
1385 {
1386     struct iw_event iwe;                /* Temporary buffer */
1387     unsigned char *info_elems;
1388     int info_elem_len;
1389     const unsigned char *elem;
1390     u16 capabilities;
1391     int signal, noise, snr;
1392     char *start_buf = current_ev;
1393     char *current_val;  /* For rates */
1394     int i, r;
1395
1396     info_elems    = scan_data->informationElements;
1397     info_elem_len = scan_data->informationElementsLength;
1398
1399     if (!scan_data->informationElementsLength || !scan_data->informationElements) {
1400         unifi_error(NULL, "*** NULL SCAN IEs ***\n");
1401         return -EIO;
1402     }
1403
1404     /* get capinfo bits */
1405     capabilities = scan_data->capabilityInformation;
1406
1407     unifi_trace(NULL, UDBG5, "Capabilities: 0x%x\n", capabilities);
1408
1409     /* First entry *MUST* be the AP MAC address */
1410     memset(&iwe, 0, sizeof(iwe));
1411     iwe.cmd = SIOCGIWAP;
1412     iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1413     memcpy(iwe.u.ap_addr.sa_data, scan_data->bssid.a, ETH_ALEN);
1414     iwe.len = IW_EV_ADDR_LEN;
1415     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_ADDR_LEN);
1416     if (r < 0) {
1417         return r;
1418     }
1419     start_buf += r;
1420
1421     /* Other entries will be displayed in the order we give them */
1422
1423     /* Add the ESSID */
1424     /* find SSID in Info Elems */
1425     elem = unifi_find_info_element(IE_SSID_ID, info_elems, info_elem_len);
1426     if (elem) {
1427         int e_len = elem[1];
1428         const unsigned char *e_ptr = elem + 2;
1429         unsigned char buf[33];
1430
1431         memset(&iwe, 0, sizeof(iwe));
1432         iwe.cmd = SIOCGIWESSID;
1433         iwe.u.essid.length = e_len;
1434         if (iwe.u.essid.length > 32) {
1435             iwe.u.essid.length = 32;
1436         }
1437         iwe.u.essid.flags = scan_index;
1438         memcpy(buf, e_ptr, iwe.u.essid.length);
1439         buf[iwe.u.essid.length] = '\0';
1440         r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, buf);
1441         if (r < 0) {
1442             return r;
1443         }
1444         start_buf += r;
1445
1446     }
1447
1448     /* Add mode */
1449     memset(&iwe, 0, sizeof(iwe));
1450     iwe.cmd = SIOCGIWMODE;
1451     if (scan_data->bssType == CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE) {
1452         iwe.u.mode = IW_MODE_INFRA;
1453     } else {
1454         iwe.u.mode = IW_MODE_ADHOC;
1455     }
1456     iwe.len = IW_EV_UINT_LEN;
1457     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_UINT_LEN);
1458     if (r < 0) {
1459         return r;
1460     }
1461     start_buf += r;
1462
1463     /* Add frequency. iwlist will convert to channel using table given in giwrange */
1464     memset(&iwe, 0, sizeof(iwe));
1465     iwe.cmd = SIOCGIWFREQ;
1466     iwe.u.freq.m = scan_data->channelFrequency;
1467     iwe.u.freq.e = 6;
1468     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_FREQ_LEN);
1469     if (r < 0) {
1470         return r;
1471     }
1472     start_buf += r;
1473
1474
1475     /* Add quality statistics */
1476     iwe.cmd = IWEVQUAL;
1477     /*
1478      * level and noise below are mapped into an unsigned 8 bit number,
1479      * ranging from [-192; 63]. The way this is achieved is simply to
1480      * add 0x100 onto the number if it is negative,
1481      * once clipped to the correct range.
1482      */
1483     signal = scan_data->rssi; /* This value is in dBm */
1484     /* Clip range of snr */
1485     snr    = (scan_data->snr > 0) ? scan_data->snr : 0; /* In dB relative, from 0 - 255 */
1486     snr    = (snr < 255) ? snr : 255;
1487     noise  = signal - snr;
1488
1489     /* Clip range of signal */
1490     signal = (signal < 63) ? signal : 63;
1491     signal = (signal > -192) ? signal : -192;
1492
1493     /* Clip range of noise */
1494     noise = (noise < 63) ? noise : 63;
1495     noise = (noise > -192) ? noise : -192;
1496
1497     /* Make u8 */
1498     signal = ( signal < 0 ) ? signal + 0x100 : signal;
1499     noise = ( noise < 0 ) ? noise + 0x100 : noise;
1500
1501     iwe.u.qual.level = (u8)signal; /* -192 : 63 */
1502     iwe.u.qual.noise = (u8)noise;  /* -192 : 63 */
1503     iwe.u.qual.qual = snr;         /* 0 : 255 */
1504     iwe.u.qual.updated = 0;
1505 #if WIRELESS_EXT > 16
1506     iwe.u.qual.updated |= IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED |
1507         IW_QUAL_QUAL_UPDATED;
1508 #if WIRELESS_EXT > 18
1509     iwe.u.qual.updated |= IW_QUAL_DBM;
1510 #endif
1511 #endif
1512     r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_QUAL_LEN);
1513     if (r < 0) {
1514         return r;
1515     }
1516     start_buf += r;
1517
1518     /* Add encryption capability */
1519     iwe.cmd = SIOCGIWENCODE;
1520     if (capabilities & SIG_CAP_PRIVACY) {
1521         iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1522     } else {
1523         iwe.u.data.flags = IW_ENCODE_DISABLED;
1524     }
1525     iwe.u.data.length = 0;
1526     iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
1527     r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, "");
1528     if (r < 0) {
1529         return r;
1530     }
1531     start_buf += r;
1532
1533
1534     /*
1535      * Rate : stuffing multiple values in a single event require a bit
1536      * more of magic - Jean II
1537      */
1538     current_val = start_buf + IW_EV_LCP_LEN;
1539
1540     iwe.cmd = SIOCGIWRATE;
1541     /* Those two flags are ignored... */
1542     iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1543
1544     elem = unifi_find_info_element(IE_SUPPORTED_RATES_ID,
1545             info_elems, info_elem_len);
1546     if (elem) {
1547         int e_len = elem[1];
1548         const unsigned char *e_ptr = elem + 2;
1549
1550         /*
1551          * Count how many rates we have.
1552          * Zero marks the end of the list, if the list is not truncated.
1553          */
1554         /* Max 8 values */
1555         for (i = 0; i < e_len; i++) {
1556             if (e_ptr[i] == 0) {
1557                 break;
1558             }
1559             /* Bit rate given in 500 kb/s units (+ 0x80) */
1560             iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1561             /* Add new value to event */
1562             r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1563             if (r < 0) {
1564                 return r;
1565             }
1566             current_val +=r;
1567
1568         }
1569     }
1570     elem = unifi_find_info_element(IE_EXTENDED_SUPPORTED_RATES_ID,
1571             info_elems, info_elem_len);
1572     if (elem) {
1573         int e_len = elem[1];
1574         const unsigned char *e_ptr = elem + 2;
1575
1576         /*
1577          * Count how many rates we have.
1578          * Zero marks the end of the list, if the list is not truncated.
1579          */
1580         /* Max 8 values */
1581         for (i = 0; i < e_len; i++) {
1582             if (e_ptr[i] == 0) {
1583                 break;
1584             }
1585             /* Bit rate given in 500 kb/s units (+ 0x80) */
1586             iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1587             /* Add new value to event */
1588             r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1589             if (r < 0) {
1590                 return r;
1591             }
1592             current_val +=r;
1593         }
1594     }
1595     /* Check if we added any rates event */
1596     if ((current_val - start_buf) > IW_EV_LCP_LEN) {
1597         start_buf = current_val;
1598     }
1599
1600
1601 #if WIRELESS_EXT > 17
1602     memset(&iwe, 0, sizeof(iwe));
1603     iwe.cmd = IWEVGENIE;
1604     iwe.u.data.length = info_elem_len;
1605
1606     r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, info_elems);
1607     if (r < 0) {
1608         return r;
1609     }
1610
1611     start_buf += r;
1612 #endif /* WE > 17 */
1613
1614     return (start_buf - current_ev);
1615 } /* unifi_translate_scan() */
1616
1617
1618
1619 static int
1620 unifi_giwscan(struct net_device *dev, struct iw_request_info *info,
1621               union iwreq_data *wrqu, char *extra)
1622 {
1623     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1624     unifi_priv_t *priv = interfacePriv->privPtr;
1625     struct iw_point *dwrq = &wrqu->data;
1626     int r;
1627
1628     CHECK_INITED(priv);
1629
1630     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1631        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1632        unifi_error(priv, "unifi_giwscan: not permitted in Mode %d\n",
1633                                       interfacePriv->interfaceMode);
1634        return -EPERM;
1635     }
1636
1637
1638     unifi_trace(priv, UDBG1,
1639             "unifi_giwscan: buffer (%d bytes) \n",
1640             dwrq->length);
1641     UF_RTNL_UNLOCK();
1642     r = sme_mgt_scan_results_get_async(priv, info, extra, dwrq->length);
1643     UF_RTNL_LOCK();
1644     if (r < 0) {
1645         unifi_trace(priv, UDBG1,
1646                 "unifi_giwscan: buffer (%d bytes) not big enough.\n",
1647                 dwrq->length);
1648         return r;
1649     }
1650
1651     dwrq->length = r;
1652     dwrq->flags = 0;
1653
1654     return 0;
1655 } /* unifi_giwscan() */
1656
1657
1658 /*
1659  * ---------------------------------------------------------------------------
1660  *  unifi_siwessid
1661  *
1662  *      Request to join a network or start and AdHoc.
1663  *
1664  *  Arguments:
1665  *      dev             Pointer to network device struct.
1666  *      info            Pointer to broken-out ioctl request.
1667  *      data            Pointer to argument data.
1668  *      essid           Pointer to string giving name of network to join
1669  *                      or start
1670  *
1671  *  Returns:
1672  *      0 on success and everything complete
1673  *      -EINPROGRESS to have the higher level call the commit method.
1674  * ---------------------------------------------------------------------------
1675  */
1676 static int
1677 unifi_siwessid(struct net_device *dev, struct iw_request_info *info,
1678                struct iw_point *data, char *essid)
1679 {
1680     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1681     unifi_priv_t *priv = interfacePriv->privPtr;
1682     int len;
1683     int err = 0;
1684
1685     CHECK_INITED(priv);
1686
1687     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1688        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1689        unifi_error(priv, "unifi_siwessid: not permitted in Mode %d\n",
1690                                       interfacePriv->interfaceMode);
1691        return -EPERM;
1692     }
1693
1694
1695     len = 0;
1696     if (data->flags & 1) {
1697         /* Limit length  */
1698         len = data->length;
1699         if (len > UNIFI_MAX_SSID_LEN) {
1700             len = UNIFI_MAX_SSID_LEN;
1701         }
1702     }
1703
1704 #ifdef UNIFI_DEBUG
1705     {
1706         char essid_str[UNIFI_MAX_SSID_LEN+1];
1707         int i;
1708
1709         for (i = 0; i < len; i++) {
1710             essid_str[i] = (isprint(essid[i]) ? essid[i] : '?');
1711         }
1712         essid_str[i] = '\0';
1713
1714         unifi_trace(priv, UDBG1, "unifi_siwessid: asked for '%*s' (%d)\n", len, essid_str, len);
1715         unifi_trace(priv, UDBG2, " with authModeMask = %d", priv->connection_config.authModeMask);
1716     }
1717 #endif
1718
1719     memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1720     if (len) {
1721         if (essid[len - 1] == 0) {
1722             len --;
1723         }
1724
1725         memcpy(priv->connection_config.ssid.ssid, essid, len);
1726         priv->connection_config.ssid.length = len;
1727
1728     } else {
1729         priv->connection_config.ssid.length = 0;
1730     }
1731
1732     UF_RTNL_UNLOCK();
1733     err = sme_mgt_connect(priv);
1734     UF_RTNL_LOCK();
1735     if (err) {
1736         unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err);
1737         return convert_sme_error(err);
1738     }
1739
1740     return 0;
1741 } /* unifi_siwessid() */
1742
1743
1744 static int
1745 unifi_giwessid(struct net_device *dev, struct iw_request_info *info,
1746                union iwreq_data *wrqu, char *essid)
1747 {
1748     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1749     unifi_priv_t *priv = interfacePriv->privPtr;
1750     struct iw_point *data = &wrqu->essid;
1751     CsrWifiSmeConnectionInfo connectionInfo;
1752     int r = 0;
1753
1754     unifi_trace(priv, UDBG2, "unifi_giwessid\n");
1755     CHECK_INITED(priv);
1756
1757     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1758        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1759        unifi_error(priv, "unifi_giwessid: not permitted in Mode %d\n",
1760                                       interfacePriv->interfaceMode);
1761        return -EPERM;
1762     }
1763
1764     UF_RTNL_UNLOCK();
1765     r = sme_mgt_connection_info_get(priv, &connectionInfo);
1766     UF_RTNL_LOCK();
1767
1768     if (r == 0) {
1769         data->length = connectionInfo.ssid.length;
1770         strncpy(essid,
1771                 connectionInfo.ssid.ssid,
1772                 data->length);
1773         data->flags = 1;            /* active */
1774
1775         unifi_trace(priv, UDBG2, "unifi_giwessid: %.*s\n",
1776                 data->length, essid);
1777     }
1778
1779
1780     return 0;
1781 } /* unifi_giwessid() */
1782
1783
1784 static int
1785 unifi_siwrate(struct net_device *dev, struct iw_request_info *info,
1786               union iwreq_data *wrqu, char *extra)
1787 {
1788     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1789     unifi_priv_t *priv = interfacePriv->privPtr;
1790     struct iw_param *args = &wrqu->bitrate;
1791     CsrWifiSmeMibConfig mibConfig;
1792     int r;
1793
1794     CHECK_INITED(priv);
1795     unifi_trace(priv, UDBG2, "unifi_siwrate\n");
1796
1797     /*
1798      * If args->fixed == 0, value is max rate or -1 for best
1799      * If args->fixed == 1, value is rate to set or -1 for best
1800      * args->disabled and args->flags are not used in SIOCSIWRATE
1801      */
1802
1803     /* Get, modify and set the MIB data */
1804     UF_RTNL_UNLOCK();
1805     r = sme_mgt_mib_config_get(priv, &mibConfig);
1806     UF_RTNL_LOCK();
1807     if (r) {
1808         unifi_error(priv, "unifi_siwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1809         return r;
1810     }
1811
1812     /* Default to auto rate algorithm */
1813     /* in 500Kbit/s, 0 means auto */
1814     mibConfig.unifiFixTxDataRate = 0;
1815
1816     if (args->value != -1) {
1817         mibConfig.unifiFixTxDataRate = args->value / 500000;
1818     }
1819
1820     /* 1 means rate is a maximum, 2 means rate is a set value */
1821     if (args->fixed == 1) {
1822         mibConfig.unifiFixMaxTxDataRate = 0;
1823     } else {
1824         mibConfig.unifiFixMaxTxDataRate = 1;
1825     }
1826     UF_RTNL_UNLOCK();
1827     r = sme_mgt_mib_config_set(priv, &mibConfig);
1828     UF_RTNL_LOCK();
1829     if (r) {
1830         unifi_error(priv, "unifi_siwrate: Set CsrWifiSmeMibConfigValue failed.\n");
1831         return r;
1832     }
1833
1834
1835     return 0;
1836 } /* unifi_siwrate() */
1837
1838
1839
1840 static int
1841 unifi_giwrate(struct net_device *dev, struct iw_request_info *info,
1842               union iwreq_data *wrqu, char *extra)
1843 {
1844     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1845     unifi_priv_t *priv = interfacePriv->privPtr;
1846     struct iw_param *args = &wrqu->bitrate;
1847     int r;
1848     int bitrate, flag;
1849     CsrWifiSmeMibConfig mibConfig;
1850     CsrWifiSmeConnectionStats connectionStats;
1851
1852     unifi_trace(priv, UDBG2, "unifi_giwrate\n");
1853     CHECK_INITED(priv);
1854
1855     flag = 0;
1856     bitrate = 0;
1857     UF_RTNL_UNLOCK();
1858     r = sme_mgt_mib_config_get(priv, &mibConfig);
1859     UF_RTNL_LOCK();
1860     if (r) {
1861         unifi_error(priv, "unifi_giwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1862         return r;
1863     }
1864
1865     bitrate = mibConfig.unifiFixTxDataRate;
1866     flag = mibConfig.unifiFixMaxTxDataRate;
1867
1868     /* Used the value returned by the SME if MIB returns 0 */
1869     if (bitrate == 0) {
1870         UF_RTNL_UNLOCK();
1871         r = sme_mgt_connection_stats_get(priv, &connectionStats);
1872         UF_RTNL_LOCK();
1873         /* Ignore errors, we may be disconnected */
1874         if (r == 0) {
1875             bitrate = connectionStats.unifiTxDataRate;
1876         }
1877     }
1878
1879     args->value = bitrate * 500000;
1880     args->fixed = !flag;
1881
1882     return 0;
1883 } /* unifi_giwrate() */
1884
1885
1886 static int
1887 unifi_siwrts(struct net_device *dev, struct iw_request_info *info,
1888              union iwreq_data *wrqu, char *extra)
1889 {
1890     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1891     unifi_priv_t *priv = interfacePriv->privPtr;
1892     int val = wrqu->rts.value;
1893     int r = 0;
1894     CsrWifiSmeMibConfig mibConfig;
1895
1896     unifi_trace(priv, UDBG2, "unifi_siwrts\n");
1897     CHECK_INITED(priv);
1898
1899     if (wrqu->rts.disabled) {
1900         val = 2347;
1901     }
1902
1903     if ( (val < 0) || (val > 2347) )
1904     {
1905         return -EINVAL;
1906     }
1907
1908     /* Get, modify and set the MIB data */
1909     UF_RTNL_UNLOCK();
1910     r = sme_mgt_mib_config_get(priv, &mibConfig);
1911     UF_RTNL_LOCK();
1912     if (r) {
1913         unifi_error(priv, "unifi_siwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1914         return r;
1915     }
1916     mibConfig.dot11RtsThreshold = val;
1917     UF_RTNL_UNLOCK();
1918     r = sme_mgt_mib_config_set(priv, &mibConfig);
1919     UF_RTNL_LOCK();
1920     if (r) {
1921         unifi_error(priv, "unifi_siwrts: Set CsrWifiSmeMibConfigValue failed.\n");
1922         return r;
1923     }
1924
1925     return 0;
1926 }
1927
1928
1929 static int
1930 unifi_giwrts(struct net_device *dev, struct iw_request_info *info,
1931              union iwreq_data *wrqu, char *extra)
1932 {
1933     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1934     unifi_priv_t *priv = interfacePriv->privPtr;
1935     int r;
1936     int rts_thresh;
1937     CsrWifiSmeMibConfig mibConfig;
1938
1939     unifi_trace(priv, UDBG2, "unifi_giwrts\n");
1940     CHECK_INITED(priv);
1941
1942     UF_RTNL_UNLOCK();
1943     r = sme_mgt_mib_config_get(priv, &mibConfig);
1944     UF_RTNL_LOCK();
1945     if (r) {
1946         unifi_error(priv, "unifi_giwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1947         return r;
1948     }
1949
1950     rts_thresh = mibConfig.dot11RtsThreshold;
1951     if (rts_thresh > 2347) {
1952         rts_thresh = 2347;
1953     }
1954
1955     wrqu->rts.value = rts_thresh;
1956     wrqu->rts.disabled = (rts_thresh == 2347);
1957     wrqu->rts.fixed = 1;
1958
1959     return 0;
1960 }
1961
1962
1963 static int
1964 unifi_siwfrag(struct net_device *dev, struct iw_request_info *info,
1965               union iwreq_data *wrqu, char *extra)
1966 {
1967     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1968     unifi_priv_t *priv = interfacePriv->privPtr;
1969     int val = wrqu->frag.value;
1970     int r = 0;
1971     CsrWifiSmeMibConfig mibConfig;
1972
1973     unifi_trace(priv, UDBG2, "unifi_siwfrag\n");
1974     CHECK_INITED(priv);
1975
1976     if (wrqu->frag.disabled)
1977         val = 2346;
1978
1979     if ( (val < 256) || (val > 2347) )
1980         return -EINVAL;
1981
1982     /* Get, modify and set the MIB data */
1983     UF_RTNL_UNLOCK();
1984     r = sme_mgt_mib_config_get(priv, &mibConfig);
1985     UF_RTNL_LOCK();
1986     if (r) {
1987         unifi_error(priv, "unifi_siwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
1988         return r;
1989     }
1990     /* Fragmentation Threashold must be even */
1991     mibConfig.dot11FragmentationThreshold = (val & ~0x1);
1992     UF_RTNL_UNLOCK();
1993     r = sme_mgt_mib_config_set(priv, &mibConfig);
1994     UF_RTNL_LOCK();
1995     if (r) {
1996         unifi_error(priv, "unifi_siwfrag: Set CsrWifiSmeMibConfigValue failed.\n");
1997         return r;
1998     }
1999
2000     return 0;
2001 }
2002
2003
2004 static int
2005 unifi_giwfrag(struct net_device *dev, struct iw_request_info *info,
2006               union iwreq_data *wrqu, char *extra)
2007 {
2008     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2009     unifi_priv_t *priv = interfacePriv->privPtr;
2010     int r;
2011     int frag_thresh;
2012     CsrWifiSmeMibConfig mibConfig;
2013
2014     unifi_trace(priv, UDBG2, "unifi_giwfrag\n");
2015     CHECK_INITED(priv);
2016
2017     UF_RTNL_UNLOCK();
2018     r = sme_mgt_mib_config_get(priv, &mibConfig);
2019     UF_RTNL_LOCK();
2020     if (r) {
2021         unifi_error(priv, "unifi_giwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
2022         return r;
2023     }
2024
2025     frag_thresh = mibConfig.dot11FragmentationThreshold;
2026
2027     /* Build the return structure */
2028     wrqu->frag.value = frag_thresh;
2029     wrqu->frag.disabled = (frag_thresh >= 2346);
2030     wrqu->frag.fixed = 1;
2031
2032     return 0;
2033 }
2034
2035
2036 static int
2037 unifi_siwencode(struct net_device *dev, struct iw_request_info *info,
2038                 union iwreq_data *wrqu, char *extra)
2039 {
2040     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2041     unifi_priv_t *priv = interfacePriv->privPtr;
2042     struct iw_point *erq = &wrqu->encoding;
2043     int index;
2044     int rc = 0;
2045     int privacy = -1;
2046     CsrWifiSmeKey sme_key;
2047
2048     unifi_trace(priv, UDBG2, "unifi_siwencode\n");
2049
2050     CHECK_INITED(priv);
2051
2052     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2053        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2054        unifi_error(priv, "unifi_siwencode: not permitted in Mode %d\n",
2055                                       interfacePriv->interfaceMode);
2056        return -EPERM;
2057     }
2058
2059
2060     /*
2061      * Key index is encoded in the flags.
2062      * 0 - use current default,
2063      * 1-4 - if a key value is given set that key
2064      *       if not use that key
2065      */
2066     index = (erq->flags & IW_ENCODE_INDEX);  /* key number, 1-4 */
2067     if ((index < 0) || (index > 4)) {
2068         unifi_error(priv, "unifi_siwencode: Request to set an invalid key (index:%d)", index);
2069         return -EINVAL;
2070     }
2071
2072     /*
2073      * Basic checking: do we have a key to set ?
2074      * The IW_ENCODE_NOKEY flag is set when no key is present (only change flags),
2075      * but older versions rely on sending a key id 1-4.
2076      */
2077     if (erq->length > 0) {
2078
2079         /* Check the size of the key */
2080         if ((erq->length > LARGE_KEY_SIZE) || (erq->length < SMALL_KEY_SIZE)) {
2081             unifi_error(priv, "unifi_siwencode: Request to set an invalid key (length:%d)",
2082                         erq->length);
2083             return -EINVAL;
2084         }
2085
2086         /* Check the index (none (i.e. 0) means use current) */
2087         if ((index < 1) || (index > 4)) {
2088             /* If we do not have a previous key, use 1 as default */
2089             if (!priv->wep_tx_key_index) {
2090                 priv->wep_tx_key_index = 1;
2091             }
2092             index = priv->wep_tx_key_index;
2093         }
2094
2095         /* If we didn't have a key and a valid index is set, we want to remember it*/
2096         if (!priv->wep_tx_key_index) {
2097             priv->wep_tx_key_index = index;
2098         }
2099
2100         unifi_trace(priv, UDBG1, "Tx key Index is %d\n", priv->wep_tx_key_index);
2101
2102         privacy = 1;
2103
2104         /* Check if the key is not marked as invalid */
2105         if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
2106
2107             unifi_trace(priv, UDBG1, "New %s key (len=%d, index=%d)\n",
2108                         (priv->wep_tx_key_index == index) ? "tx" : "",
2109                         erq->length, index);
2110
2111             sme_key.wepTxKey = (priv->wep_tx_key_index == index);
2112             if (priv->wep_tx_key_index == index) {
2113                 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2114             } else {
2115                 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2116             }
2117             /* Key index is zero based in SME but 1 based in wext */
2118             sme_key.keyIndex = (index - 1);
2119             sme_key.keyLength = erq->length;
2120             sme_key.authenticator = 0;
2121             memset(sme_key.address.a, 0xFF, ETH_ALEN);
2122             memcpy(sme_key.key, extra, erq->length);
2123
2124             UF_RTNL_UNLOCK();
2125             rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2126             UF_RTNL_LOCK();
2127             if (rc) {
2128                 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2129                 return convert_sme_error(rc);
2130             }
2131
2132             /* Store the key to be reported by the SIOCGIWENCODE handler */
2133             priv->wep_keys[index - 1].len = erq->length;
2134             memcpy(priv->wep_keys[index - 1].key, extra, erq->length);
2135         }
2136     } else {
2137         /*
2138          * No additional key data, so it must be a request to change the
2139          * active key.
2140          */
2141         if (index != 0) {
2142             unifi_trace(priv, UDBG1, "Tx key Index is %d\n", index - 1);
2143
2144             /* Store the index to be reported by the SIOCGIWENCODE handler */
2145             priv->wep_tx_key_index = index;
2146
2147             sme_key.wepTxKey = 1;
2148             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2149
2150             /* Key index is zero based in SME but 1 based in wext */
2151             sme_key.keyIndex = (index - 1);
2152             sme_key.keyLength = 0;
2153             sme_key.authenticator = 0;
2154             UF_RTNL_UNLOCK();
2155             rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2156             UF_RTNL_LOCK();
2157             if (rc) {
2158                 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2159                 return convert_sme_error(rc);
2160             }
2161
2162             /* Turn on encryption */
2163             privacy = 1;
2164         }
2165     }
2166
2167     /* Read the flags */
2168     if (erq->flags & IW_ENCODE_DISABLED) {
2169         /* disable encryption */
2170         unifi_trace(priv, UDBG1, "disable WEP encryption\n");
2171         privacy = 0;
2172
2173         priv->wep_tx_key_index = 0;
2174
2175         unifi_trace(priv, UDBG1, "IW_ENCODE_DISABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2176         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2177     }
2178
2179     if (erq->flags & IW_ENCODE_RESTRICTED) {
2180         /* Use shared key auth */
2181         unifi_trace(priv, UDBG1, "IW_ENCODE_RESTRICTED: CSR_WIFI_SME_AUTH_MODE_80211_SHARED\n");
2182         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2183
2184         /* Turn on encryption */
2185         privacy = 1;
2186     }
2187     if (erq->flags & IW_ENCODE_OPEN) {
2188         unifi_trace(priv, UDBG1, "IW_ENCODE_OPEN: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2189         priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2190     }
2191
2192     /* Commit the changes to flags if needed */
2193     if (privacy != -1) {
2194         priv->connection_config.privacyMode = privacy ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2195         priv->connection_config.encryptionModeMask = privacy ? (CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 |
2196                 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 |
2197                 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2198                 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104) :
2199             CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2200     }
2201
2202     return convert_sme_error(rc);
2203
2204 } /* unifi_siwencode() */
2205
2206
2207
2208 static int
2209 unifi_giwencode(struct net_device *dev, struct iw_request_info *info,
2210                 union iwreq_data *wrqu, char *extra)
2211 {
2212     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2213     unifi_priv_t *priv = interfacePriv->privPtr;
2214     struct iw_point *erq = &wrqu->encoding;
2215
2216     unifi_trace(priv, UDBG2, "unifi_giwencode\n");
2217
2218     CHECK_INITED(priv);
2219
2220     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2221        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2222        unifi_error(priv, "unifi_giwencode: not permitted in Mode %d\n",
2223                                       interfacePriv->interfaceMode);
2224        return -EPERM;
2225     }
2226
2227
2228     if (priv->connection_config.authModeMask == CSR_WIFI_SME_AUTH_MODE_80211_SHARED) {
2229         erq->flags = IW_ENCODE_RESTRICTED;
2230     }
2231     else {
2232         if (priv->connection_config.privacyMode == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) {
2233             erq->flags = IW_ENCODE_DISABLED;
2234         } else {
2235             erq->flags = IW_ENCODE_OPEN;
2236         }
2237     }
2238
2239     erq->length = 0;
2240
2241     if (erq->flags != IW_ENCODE_DISABLED) {
2242         int index = priv->wep_tx_key_index;
2243
2244         if ((index > 0) && (index <= NUM_WEPKEYS)) {
2245             erq->flags |= (index & IW_ENCODE_INDEX);
2246             erq->length = priv->wep_keys[index - 1].len;
2247             memcpy(extra, priv->wep_keys[index - 1].key, erq->length);
2248         } else {
2249             unifi_notice(priv, "unifi_giwencode: Surprise, do not have a valid key index (%d)\n",
2250                          index);
2251         }
2252     }
2253
2254     return 0;
2255 } /* unifi_giwencode() */
2256
2257
2258 static int
2259 unifi_siwpower(struct net_device *dev, struct iw_request_info *info,
2260                union iwreq_data *wrqu, char *extra)
2261 {
2262     struct iw_param *args = &wrqu->power;
2263     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2264     unifi_priv_t *priv = interfacePriv->privPtr;
2265     int listen_interval, wake_for_dtim;
2266     int r = 0;
2267     CsrWifiSmePowerConfig powerConfig;
2268
2269     unifi_trace(priv, UDBG2, "unifi_siwpower\n");
2270
2271     CHECK_INITED(priv);
2272
2273     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2274        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2275        unifi_error(priv, "unifi_siwpower: not permitted in Mode %d\n",
2276                                       interfacePriv->interfaceMode);
2277        return -EPERM;
2278     }
2279
2280     UF_RTNL_UNLOCK();
2281     r = sme_mgt_power_config_get(priv, &powerConfig);
2282     UF_RTNL_LOCK();
2283     if (r) {
2284         unifi_error(priv, "unifi_siwpower: Get unifi_PowerConfigValue failed.\n");
2285         return r;
2286     }
2287
2288     listen_interval = -1;
2289     wake_for_dtim = -1;
2290     if (args->disabled) {
2291         powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
2292     }
2293     else
2294     {
2295         powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
2296
2297         switch (args->flags & IW_POWER_TYPE) {
2298             case 0:
2299                 /* not specified */
2300                 break;
2301             case IW_POWER_PERIOD:
2302                 listen_interval = args->value / 1000;
2303                 break;
2304             default:
2305                 return -EINVAL;
2306         }
2307
2308         switch (args->flags & IW_POWER_MODE) {
2309             case 0:
2310                 /* not specified */
2311                 break;
2312             case IW_POWER_UNICAST_R:
2313                 /* not interested in broadcast packets */
2314                 wake_for_dtim = 0;
2315                 break;
2316             case IW_POWER_ALL_R:
2317                 /* yes, we are interested in broadcast packets */
2318                 wake_for_dtim = 1;
2319                 break;
2320             default:
2321                 return -EINVAL;
2322         }
2323     }
2324
2325     if (listen_interval > 0) {
2326         powerConfig.listenIntervalTu = listen_interval;
2327         unifi_trace(priv, UDBG4, "unifi_siwpower: new Listen Interval = %d.\n",
2328                     powerConfig.listenIntervalTu);
2329     }
2330
2331     if (wake_for_dtim >= 0) {
2332         powerConfig.rxDtims = wake_for_dtim;
2333     }
2334     UF_RTNL_UNLOCK();
2335     r = sme_mgt_power_config_set(priv, &powerConfig);
2336     UF_RTNL_LOCK();
2337     if (r) {
2338         unifi_error(priv, "unifi_siwpower: Set unifi_PowerConfigValue failed.\n");
2339         return r;
2340     }
2341
2342     return 0;
2343 } /* unifi_siwpower() */
2344
2345
2346 static int
2347 unifi_giwpower(struct net_device *dev, struct iw_request_info *info,
2348                union iwreq_data *wrqu, char *extra)
2349 {
2350     struct iw_param *args = &wrqu->power;
2351     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2352     unifi_priv_t *priv = interfacePriv->privPtr;
2353     CsrWifiSmePowerConfig powerConfig;
2354     int r;
2355
2356     unifi_trace(priv, UDBG2, "unifi_giwpower\n");
2357
2358     CHECK_INITED(priv);
2359
2360     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2361        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2362        unifi_error(priv, "unifi_giwpower: not permitted in Mode %d\n",
2363                                       interfacePriv->interfaceMode);
2364        return -EPERM;
2365     }
2366
2367
2368     args->flags = 0;
2369     UF_RTNL_UNLOCK();
2370     r = sme_mgt_power_config_get(priv, &powerConfig);
2371     UF_RTNL_LOCK();
2372     if (r) {
2373         unifi_error(priv, "unifi_giwpower: Get unifi_PowerConfigValue failed.\n");
2374         return r;
2375     }
2376
2377     unifi_trace(priv, UDBG4, "unifi_giwpower: mode=%d\n",
2378                 powerConfig.powerSaveLevel);
2379
2380     args->disabled = (powerConfig.powerSaveLevel == CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW);
2381     if (args->disabled) {
2382         args->flags = 0;
2383         return 0;
2384     }
2385
2386     args->value = powerConfig.listenIntervalTu * 1000;
2387     args->flags |= IW_POWER_PERIOD;
2388
2389     if (powerConfig.rxDtims) {
2390         args->flags |= IW_POWER_ALL_R;
2391     } else {
2392         args->flags |= IW_POWER_UNICAST_R;
2393     }
2394
2395     return 0;
2396 } /* unifi_giwpower() */
2397
2398
2399 /*
2400  * ---------------------------------------------------------------------------
2401  *  unifi_siwcommit - handler for SIOCSIWCOMMIT
2402  *
2403  *      Apply all the parameters that have been set.
2404  *      In practice this means:
2405  *       - do a scan
2406  *       - join a network or start an AdHoc
2407  *       - authenticate and associate.
2408  *
2409  *  Arguments:
2410  *      None.
2411  *
2412  *  Returns:
2413  *      None.
2414  * ---------------------------------------------------------------------------
2415  */
2416 static int
2417 unifi_siwcommit(struct net_device *dev, struct iw_request_info *info,
2418                 union iwreq_data *wrqu, char *extra)
2419 {
2420     return 0;
2421 } /* unifi_siwcommit() */
2422
2423
2424
2425 static int
2426 unifi_siwmlme(struct net_device *dev, struct iw_request_info *info,
2427               union iwreq_data *wrqu, char *extra)
2428 {
2429     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2430     unifi_priv_t *priv = interfacePriv->privPtr;
2431     struct iw_mlme *mlme = (struct iw_mlme *)extra;
2432
2433     unifi_trace(priv, UDBG2, "unifi_siwmlme\n");
2434     CHECK_INITED(priv);
2435
2436     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2437        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2438        unifi_error(priv, "unifi_siwmlme: not permitted in Mode %d\n",
2439                                       interfacePriv->interfaceMode);
2440        return -EPERM;
2441     }
2442
2443
2444     switch (mlme->cmd) {
2445         case IW_MLME_DEAUTH:
2446         case IW_MLME_DISASSOC:
2447             UF_RTNL_UNLOCK();
2448             sme_mgt_disconnect(priv);
2449             UF_RTNL_LOCK();
2450             break;
2451         default:
2452             return -EOPNOTSUPP;
2453     }
2454
2455     return 0;
2456 } /* unifi_siwmlme() */
2457
2458
2459 /*
2460  * ---------------------------------------------------------------------------
2461  *  unifi_siwgenie
2462  *  unifi_giwgenie
2463  *
2464  *      WPA : Generic IEEE 802.11 information element (e.g., for WPA/RSN/WMM).
2465  *      Handlers for SIOCSIWGENIE, SIOCGIWGENIE - set/get generic IE
2466  *
2467  *      The host program (e.g. wpa_supplicant) uses this call to set the
2468  *      additional IEs to accompany the next (Associate?) request.
2469  *
2470  *  Arguments:
2471  *      None.
2472  *
2473  *  Returns:
2474  *      None.
2475  *  Notes:
2476  *      From wireless.h:
2477  *        This ioctl uses struct iw_point and data buffer that includes IE id
2478  *        and len fields. More than one IE may be included in the
2479  *        request. Setting the generic IE to empty buffer (len=0) removes the
2480  *        generic IE from the driver.
2481  * ---------------------------------------------------------------------------
2482  */
2483 static int
2484 unifi_siwgenie(struct net_device *dev, struct iw_request_info *info,
2485                union iwreq_data *wrqu, char *extra)
2486 {
2487     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2488     unifi_priv_t *priv = interfacePriv->privPtr;
2489     int len;
2490
2491     unifi_trace(priv, UDBG2, "unifi_siwgenie\n");
2492
2493     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2494        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2495        unifi_error(priv, "unifi_siwgenie: not permitted in Mode %d\n",
2496                                       interfacePriv->interfaceMode);
2497        return -EPERM;
2498     }
2499
2500
2501     if ( priv->connection_config.mlmeAssociateReqInformationElements) {
2502         kfree( priv->connection_config.mlmeAssociateReqInformationElements);
2503     }
2504     priv->connection_config.mlmeAssociateReqInformationElementsLength = 0;
2505     priv->connection_config.mlmeAssociateReqInformationElements = NULL;
2506
2507     len = wrqu->data.length;
2508     if (len == 0) {
2509         return 0;
2510     }
2511
2512     priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL);
2513     if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) {
2514         return -ENOMEM;
2515     }
2516
2517     priv->connection_config.mlmeAssociateReqInformationElementsLength = len;
2518     memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len);
2519
2520     return 0;
2521 } /* unifi_siwgenie() */
2522
2523
2524 static int
2525 unifi_giwgenie(struct net_device *dev, struct iw_request_info *info,
2526                union iwreq_data *wrqu, char *extra)
2527 {
2528     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2529     unifi_priv_t *priv = interfacePriv->privPtr;
2530     int len;
2531
2532     unifi_trace(priv, UDBG2, "unifi_giwgenie\n");
2533
2534     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2535        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2536        unifi_error(priv, "unifi_giwgenie: not permitted in Mode %d\n",
2537                                       interfacePriv->interfaceMode);
2538        return -EPERM;
2539     }
2540
2541
2542     len = priv->connection_config.mlmeAssociateReqInformationElementsLength;
2543
2544     if (len == 0) {
2545         wrqu->data.length = 0;
2546         return 0;
2547     }
2548
2549     if (wrqu->data.length < len) {
2550         return -E2BIG;
2551     }
2552
2553     wrqu->data.length = len;
2554     memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len);
2555
2556     return 0;
2557 } /* unifi_giwgenie() */
2558
2559
2560 /*
2561  * ---------------------------------------------------------------------------
2562  *  unifi_siwauth
2563  *  unifi_giwauth
2564  *
2565  *      Handlers for SIOCSIWAUTH, SIOCGIWAUTH
2566  *      Set/get various authentication parameters.
2567  *
2568  *  Arguments:
2569  *
2570  *
2571  *  Returns:
2572  *      None.
2573  * ---------------------------------------------------------------------------
2574  */
2575 static int
2576 _unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2577                union iwreq_data *wrqu, char *extra)
2578 {
2579     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2580     unifi_priv_t *priv = interfacePriv->privPtr;
2581     CsrWifiSmeAuthModeMask new_auth;
2582
2583     unifi_trace(priv, UDBG2, "unifi_siwauth\n");
2584
2585     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2586        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2587        unifi_error(priv, "unifi_siwauth: not permitted in Mode %d\n",
2588                                       interfacePriv->interfaceMode);
2589        return -EPERM;
2590     }
2591
2592
2593     /*
2594      * This ioctl is safe to call even when UniFi is powered off.
2595      * wpa_supplicant calls it to test whether we support WPA.
2596      */
2597
2598     switch (wrqu->param.flags & IW_AUTH_INDEX) {
2599
2600         case IW_AUTH_WPA_ENABLED:
2601             unifi_trace(priv, UDBG1, "IW_AUTH_WPA_ENABLED: %d\n", wrqu->param.value);
2602
2603             if (wrqu->param.value == 0) {
2604                 unifi_trace(priv, UDBG5, "IW_AUTH_WPA_ENABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2605                 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2606             }
2607             break;
2608
2609         case IW_AUTH_PRIVACY_INVOKED:
2610             unifi_trace(priv, UDBG1, "IW_AUTH_PRIVACY_INVOKED: %d\n", wrqu->param.value);
2611
2612             priv->connection_config.privacyMode = wrqu->param.value ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2613             if (wrqu->param.value == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED)
2614             {
2615                 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2616             }
2617             break;
2618
2619         case IW_AUTH_80211_AUTH_ALG:
2620             /*
2621                IW_AUTH_ALG_OPEN_SYSTEM      0x00000001
2622                IW_AUTH_ALG_SHARED_KEY       0x00000002
2623                IW_AUTH_ALG_LEAP             0x00000004
2624                */
2625             new_auth = 0;
2626             if (wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) {
2627                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_OPEN_SYSTEM)\n", wrqu->param.value);
2628                 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2629             }
2630             if (wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) {
2631                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_SHARED_KEY)\n", wrqu->param.value);
2632                 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2633             }
2634             if (wrqu->param.value & IW_AUTH_ALG_LEAP) {
2635                 /* Initial exchanges using open-system to set EAP */
2636                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_LEAP)\n", wrqu->param.value);
2637                 new_auth |= CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X;
2638             }
2639             if (new_auth == 0) {
2640                 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: invalid value %d\n",
2641                         wrqu->param.value);
2642                 return -EINVAL;
2643             } else {
2644                 priv->connection_config.authModeMask = new_auth;
2645             }
2646             break;
2647
2648         case IW_AUTH_WPA_VERSION:
2649             unifi_trace(priv, UDBG1, "IW_AUTH_WPA_VERSION: %d\n", wrqu->param.value);
2650             priv->ignore_bssid_join = TRUE;
2651             /*
2652                IW_AUTH_WPA_VERSION_DISABLED 0x00000001
2653                IW_AUTH_WPA_VERSION_WPA      0x00000002
2654                IW_AUTH_WPA_VERSION_WPA2     0x00000004
2655                */
2656
2657             if (!(wrqu->param.value & IW_AUTH_WPA_VERSION_DISABLED)) {
2658
2659                 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2660
2661                 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA) {
2662                     unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA, WPA-PSK\n");
2663                     priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK);
2664                 }
2665                 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA2) {
2666                     unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA2, WPA2-PSK\n");
2667                     priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK);
2668                 }
2669             }
2670             break;
2671
2672         case IW_AUTH_CIPHER_PAIRWISE:
2673             unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_PAIRWISE: %d\n", wrqu->param.value);
2674             /*
2675              * one of:
2676              IW_AUTH_CIPHER_NONE        0x00000001
2677              IW_AUTH_CIPHER_WEP40       0x00000002
2678              IW_AUTH_CIPHER_TKIP        0x00000004
2679              IW_AUTH_CIPHER_CCMP        0x00000008
2680              IW_AUTH_CIPHER_WEP104      0x00000010
2681              */
2682
2683             priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2684
2685             if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2686                 priv->connection_config.encryptionModeMask |=
2687                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2688             }
2689             if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2690                 priv->connection_config.encryptionModeMask |=
2691                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2692             }
2693             if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2694                 priv->connection_config.encryptionModeMask |=
2695                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2696             }
2697             if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2698                 priv->connection_config.encryptionModeMask |=
2699                     CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2700             }
2701
2702             break;
2703
2704         case IW_AUTH_CIPHER_GROUP:
2705             unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_GROUP: %d\n", wrqu->param.value);
2706             /*
2707              * Use the WPA version and the group cipher suite to set the permitted
2708              * group key in the MIB. f/w uses this value to validate WPA and RSN IEs
2709              * in the probe responses from the desired BSS(ID)
2710              */
2711
2712             priv->connection_config.encryptionModeMask &= ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2713                     CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 |
2714                     CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP |
2715                     CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP);
2716             if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2717                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2718             }
2719             if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2720                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2721             }
2722             if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2723                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2724             }
2725             if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2726                 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2727             }
2728
2729             break;
2730
2731         case IW_AUTH_KEY_MGMT:
2732             unifi_trace(priv, UDBG1, "IW_AUTH_KEY_MGMT: %d\n", wrqu->param.value);
2733             /*
2734                IW_AUTH_KEY_MGMT_802_1X 1
2735                IW_AUTH_KEY_MGMT_PSK    2
2736                */
2737             if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK)) {
2738                 /* Check for explicitly set mode. */
2739                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2740                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK;
2741                 }
2742                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2743                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA;
2744                 }
2745                 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA: %d\n",
2746                             priv->connection_config.authModeMask);
2747             }
2748             if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK)) {
2749                 /* Check for explicitly set mode. */
2750                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2751                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK;
2752                 }
2753                 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2754                     priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2;
2755                 }
2756                 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA2: %d\n",
2757                             priv->connection_config.authModeMask);
2758             }
2759
2760             break;
2761         case IW_AUTH_TKIP_COUNTERMEASURES:
2762             /*
2763              * Set to true at the start of the 60 second backup-off period
2764              * following 2 MichaelMIC failures within 60s.
2765              */
2766             unifi_trace(priv, UDBG1, "IW_AUTH_TKIP_COUNTERMEASURES: %d\n", wrqu->param.value);
2767             break;
2768
2769         case IW_AUTH_DROP_UNENCRYPTED:
2770             /*
2771              * Set to true on init.
2772              * Set to false just before associate if encryption will not be
2773              * required.
2774              *
2775              * Note this is not the same as the 802.1X controlled port
2776              */
2777             unifi_trace(priv, UDBG1, "IW_AUTH_DROP_UNENCRYPTED: %d\n", wrqu->param.value);
2778             break;
2779
2780         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2781             /*
2782              * This is set by wpa_supplicant to allow unencrypted EAPOL messages
2783              * even if pairwise keys are set when not using WPA. IEEE 802.1X
2784              * specifies that these frames are not encrypted, but WPA encrypts
2785              * them when pairwise keys are in use.
2786              * I think the UniFi f/w handles this decision for us.
2787              */
2788             unifi_trace(priv, UDBG1, "IW_AUTH_RX_UNENCRYPTED_EAPOL: %d\n", wrqu->param.value);
2789             break;
2790
2791         case IW_AUTH_ROAMING_CONTROL:
2792             unifi_trace(priv, UDBG1, "IW_AUTH_ROAMING_CONTROL: %d\n", wrqu->param.value);
2793             break;
2794
2795         default:
2796             unifi_trace(priv, UDBG1, "Unsupported auth param %d to 0x%X\n",
2797                         wrqu->param.flags & IW_AUTH_INDEX,
2798                         wrqu->param.value);
2799             return -EOPNOTSUPP;
2800     }
2801
2802     unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask);
2803
2804     return 0;
2805 } /* _unifi_siwauth() */
2806
2807
2808 static int
2809 unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2810         union iwreq_data *wrqu, char *extra)
2811 {
2812     int err = 0;
2813
2814     UF_RTNL_UNLOCK();
2815     err = _unifi_siwauth(dev, info, wrqu, extra);
2816     UF_RTNL_LOCK();
2817
2818     return err;
2819 } /* unifi_siwauth() */
2820
2821
2822 static int
2823 unifi_giwauth(struct net_device *dev, struct iw_request_info *info,
2824         union iwreq_data *wrqu, char *extra)
2825 {
2826     unifi_trace(NULL, UDBG2, "unifi_giwauth\n");
2827     return -EOPNOTSUPP;
2828 } /* unifi_giwauth() */
2829
2830 /*
2831  * ---------------------------------------------------------------------------
2832  *  unifi_siwencodeext
2833  *  unifi_giwencodeext
2834  *
2835  *      Handlers for SIOCSIWENCODEEXT, SIOCGIWENCODEEXT - set/get
2836  *      encoding token & mode
2837  *
2838  *  Arguments:
2839  *      None.
2840  *
2841  *  Returns:
2842  *      None.
2843  *
2844  *  Notes:
2845  *      For WPA/WPA2 we don't take note of the IW_ENCODE_EXT_SET_TX_KEY flag.
2846  *      This flag means "use this key to encode transmissions"; we just
2847  *      assume only one key will be set and that is the one to use.
2848  * ---------------------------------------------------------------------------
2849  */
2850 static int
2851 _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
2852         union iwreq_data *wrqu, char *extra)
2853 {
2854     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2855     unifi_priv_t *priv = interfacePriv->privPtr;
2856     struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
2857     int r = 0;
2858     unsigned char *keydata;
2859     unsigned char tkip_key[32];
2860     int keyid;
2861     unsigned char *a = (unsigned char *)ext->addr.sa_data;
2862     CsrWifiSmeKey sme_key;
2863     CsrWifiSmeKeyType key_type;
2864
2865     CHECK_INITED(priv);
2866
2867     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2868        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2869        unifi_error(priv, "unifi_siwencodeext: not permitted in Mode %d\n",
2870                                       interfacePriv->interfaceMode);
2871        return -EPERM;
2872     }
2873
2874
2875     unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n",
2876                 wrqu->encoding.flags, ext->alg, ext->ext_flags,
2877                 ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX));
2878         unifi_trace(priv, UDBG3, "              addr=%pM\n", a);
2879
2880     if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
2881         /* This means use a different key (given by key_idx) for Tx. */
2882         /* NYI */
2883         unifi_trace(priv, UDBG1, KERN_ERR "unifi_siwencodeext: NYI should change tx key id here!!\n");
2884         return -ENOTSUPP;
2885     }
2886
2887     memset(&sme_key, 0, sizeof(sme_key));
2888
2889     keydata = (unsigned char *)(ext + 1);
2890     keyid = (wrqu->encoding.flags & IW_ENCODE_INDEX);
2891
2892     /*
2893      * Check for request to delete keys for an address.
2894      */
2895     /* Pick out request for no privacy. */
2896     if (ext->alg == IW_ENCODE_ALG_NONE) {
2897
2898         unifi_trace(priv, UDBG1, "Deleting %s key %d\n",
2899                     (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? "GROUP" : "PAIRWISE",
2900                     keyid);
2901
2902         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
2903             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2904         } else {
2905             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2906         }
2907         sme_key.keyIndex = (keyid - 1);
2908         sme_key.keyLength = 0;
2909         sme_key.authenticator = 0;
2910         memcpy(sme_key.address.a, a, ETH_ALEN);
2911         UF_RTNL_UNLOCK();
2912         r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_REMOVE);
2913         UF_RTNL_LOCK();
2914         if (r) {
2915             unifi_error(priv, "Delete key request was rejected with result %d\n", r);
2916             return convert_sme_error(r);
2917         }
2918
2919         return 0;
2920     }
2921
2922     /*
2923      * Request is to set a key, not delete
2924      */
2925
2926     /* Pick out WEP and use set_wep_key(). */
2927     if (ext->alg == IW_ENCODE_ALG_WEP) {
2928         /* WEP-40, WEP-104 */
2929
2930         /* Check for valid key length */
2931         if (!((ext->key_len == 5) || (ext->key_len == 13))) {
2932             unifi_trace(priv, UDBG1, KERN_ERR "Invalid length for WEP key: %d\n", ext->key_len);
2933             return -EINVAL;
2934         }
2935
2936         unifi_trace(priv, UDBG1, "Setting WEP key %d tx:%d\n",
2937                     keyid, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY);
2938
2939         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
2940             sme_key.wepTxKey = TRUE;
2941             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2942         } else {
2943             sme_key.wepTxKey = FALSE;
2944             sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2945         }
2946         sme_key.keyIndex = (keyid - 1);
2947         sme_key.keyLength = ext->key_len;
2948         sme_key.authenticator = 0;
2949         memset(sme_key.address.a, 0xFF, ETH_ALEN);
2950         memcpy(sme_key.key, keydata, ext->key_len);
2951         UF_RTNL_UNLOCK();
2952         r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2953         UF_RTNL_LOCK();
2954         if (r) {
2955             unifi_error(priv, "siwencodeext: Set key failed (%d)", r);
2956             return convert_sme_error(r);
2957         }
2958
2959         return 0;
2960     }
2961
2962     /*
2963      *
2964      * If we reach here, we are dealing with a WPA/WPA2 key
2965      *
2966      */
2967     if (ext->key_len > 32) {
2968         return -EINVAL;
2969     }
2970
2971     /*
2972      * TKIP keys from wpa_supplicant need swapping.
2973      * What about other supplicants (when they come along)?
2974      */
2975     if ((ext->alg == IW_ENCODE_ALG_TKIP) && (ext->key_len == 32)) {
2976         memcpy(tkip_key, keydata, 16);
2977         memcpy(tkip_key + 16, keydata + 24, 8);
2978         memcpy(tkip_key + 24, keydata + 16, 8);
2979         keydata = tkip_key;
2980     }
2981
2982     key_type = (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ?
2983         CSR_WIFI_SME_KEY_TYPE_GROUP : /* Group Key */
2984         CSR_WIFI_SME_KEY_TYPE_PAIRWISE; /* Pairwise Key */
2985
2986     sme_key.keyType = key_type;
2987     sme_key.keyIndex = (keyid - 1);
2988     sme_key.keyLength = ext->key_len;
2989     sme_key.authenticator = 0;
2990     memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN);
2991     if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
2992
2993                 unifi_trace(priv, UDBG5, "RSC first 6 bytes = %*phC\n",
2994                                          6, ext->rx_seq);
2995
2996         /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */
2997         sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0];
2998         sme_key.keyRsc[1] = ext->rx_seq[3] << 8 | ext->rx_seq[2];
2999         sme_key.keyRsc[2] = ext->rx_seq[5] << 8 | ext->rx_seq[4];
3000         sme_key.keyRsc[3] = ext->rx_seq[7] << 8 | ext->rx_seq[6];
3001
3002     }
3003
3004     memcpy(sme_key.key, keydata, ext->key_len);
3005     UF_RTNL_UNLOCK();
3006     r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
3007     UF_RTNL_LOCK();
3008     if (r) {
3009         unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
3010         return convert_sme_error(r);
3011     }
3012
3013     return r;
3014 } /* _unifi_siwencodeext() */
3015
3016
3017 static int
3018 unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
3019         union iwreq_data *wrqu, char *extra)
3020 {
3021     int err = 0;
3022
3023     err = _unifi_siwencodeext(dev, info, wrqu, extra);
3024
3025     return err;
3026 } /* unifi_siwencodeext() */
3027
3028
3029 static int
3030 unifi_giwencodeext(struct net_device *dev, struct iw_request_info *info,
3031         union iwreq_data *wrqu, char *extra)
3032 {
3033     return -EOPNOTSUPP;
3034 } /* unifi_giwencodeext() */
3035
3036
3037 /*
3038  * ---------------------------------------------------------------------------
3039  *  unifi_siwpmksa
3040  *
3041  *      SIOCSIWPMKSA - PMKSA cache operation
3042  *      The caller passes a pmksa structure:
3043  *        - cmd         one of ADD, REMOVE, FLUSH
3044  *        - bssid       MAC address
3045  *        - pmkid       ID string (16 bytes)
3046  *
3047  *  Arguments:
3048  *      None.
3049  *
3050  *  Returns:
3051  *      None.
3052  *
3053  *  Notes:
3054  *      This is not needed since we provide a siwgenie method.
3055  * ---------------------------------------------------------------------------
3056  */
3057 #define UNIFI_PMKID_KEY_SIZE 16
3058 static int
3059 unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info,
3060         union iwreq_data *wrqu, char *extra)
3061 {
3062     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3063     unifi_priv_t *priv = interfacePriv->privPtr;
3064     struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
3065     CsrResult r = 0;
3066     CsrWifiSmePmkidList pmkid_list;
3067     CsrWifiSmePmkid pmkid;
3068     CsrWifiSmeListAction action;
3069
3070     CHECK_INITED(priv);
3071
3072     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
3073        interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
3074        unifi_error(priv, "unifi_siwpmksa: not permitted in Mode %d\n",
3075                                       interfacePriv->interfaceMode);
3076        return -EPERM;
3077     }
3078
3079
3080         unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %pM\n", pmksa->cmd,
3081                 pmksa->bssid.sa_data);
3082
3083     pmkid_list.pmkids = NULL;
3084     switch (pmksa->cmd) {
3085       case IW_PMKSA_ADD:
3086         pmkid_list.pmkids = &pmkid;
3087         action = CSR_WIFI_SME_LIST_ACTION_ADD;
3088         pmkid_list.pmkidsCount = 1;
3089         memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3090         memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3091         break;
3092       case IW_PMKSA_REMOVE:
3093         pmkid_list.pmkids = &pmkid;
3094         action = CSR_WIFI_SME_LIST_ACTION_REMOVE;
3095         pmkid_list.pmkidsCount = 1;
3096         memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3097         memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3098         break;
3099       case IW_PMKSA_FLUSH:
3100         /* Replace current PMKID's with an empty list */
3101         pmkid_list.pmkidsCount = 0;
3102         action = CSR_WIFI_SME_LIST_ACTION_FLUSH;
3103         break;
3104       default:
3105         unifi_notice(priv, "SIWPMKSA: Unknown command (0x%x)\n", pmksa->cmd);
3106         return -EINVAL;
3107     }
3108
3109     /* Set the Value the pmkid's will have 1 added OR 1 removed OR be cleared at this point */
3110     UF_RTNL_UNLOCK();
3111     r = sme_mgt_pmkid(priv, action, &pmkid_list);
3112     UF_RTNL_LOCK();
3113     if (r) {
3114         unifi_error(priv, "SIWPMKSA: Set PMKID's Failed.\n");
3115     }
3116
3117     return r;
3118
3119 } /* unifi_siwpmksa() */
3120
3121
3122 /*
3123  * ---------------------------------------------------------------------------
3124  *  unifi_get_wireless_stats
3125  *
3126  *      get_wireless_stats method for Linux wireless extensions.
3127  *
3128  *  Arguments:
3129  *      dev             Pointer to associated netdevice.
3130  *
3131  *  Returns:
3132  *      Pointer to iw_statistics struct.
3133  * ---------------------------------------------------------------------------
3134  */
3135 struct iw_statistics *
3136 unifi_get_wireless_stats(struct net_device *dev)
3137 {
3138     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3139     unifi_priv_t *priv = interfacePriv->privPtr;
3140
3141     if (priv->init_progress != UNIFI_INIT_COMPLETED) {
3142         return NULL;
3143     }
3144
3145     return &priv->wext_wireless_stats;
3146 } /* unifi_get_wireless_stats() */
3147
3148
3149 /*
3150  * Structures to export the Wireless Handlers
3151  */
3152
3153 static const struct iw_priv_args unifi_private_args[] = {
3154     /*{ cmd,         set_args,                            get_args, name } */
3155     { SIOCIWS80211POWERSAVEPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3156         IW_PRIV_TYPE_NONE, "iwprivs80211ps" },
3157     { SIOCIWG80211POWERSAVEPRIV, IW_PRIV_TYPE_NONE,
3158         IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IWPRIV_POWER_SAVE_MAX_STRING, "iwprivg80211ps" },
3159     { SIOCIWS80211RELOADDEFAULTSPRIV, IW_PRIV_TYPE_NONE,
3160         IW_PRIV_TYPE_NONE, "iwprivsdefs" },
3161     { SIOCIWSSMEDEBUGPRIV, IW_PRIV_TYPE_CHAR | IWPRIV_SME_DEBUG_MAX_STRING, IW_PRIV_TYPE_NONE, "iwprivssmedebug" },
3162 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3163     { SIOCIWSCONFWAPIPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3164         IW_PRIV_TYPE_NONE, "iwprivsconfwapi" },
3165     { SIOCIWSWAPIKEYPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(unifiio_wapi_key_t),
3166         IW_PRIV_TYPE_NONE, "iwprivswpikey" },
3167 #endif
3168 #ifdef CSR_SUPPORT_WEXT_AP
3169     { SIOCIWSAPCFGPRIV, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_NONE, "AP_SET_CFG" },
3170     { SIOCIWSAPSTARTPRIV, 0,IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING,"AP_BSS_START" },
3171     { SIOCIWSAPSTOPPRIV, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0,
3172       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "AP_BSS_STOP" },
3173 #ifdef ANDROID_BUILD
3174     { SIOCIWSFWRELOADPRIV, IW_PRIV_TYPE_CHAR |256,
3175       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "WL_FW_RELOAD" },
3176     { SIOCIWSSTACKSTART, 0,
3177       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "START" },
3178     { SIOCIWSSTACKSTOP, 0,
3179       IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "STOP" },
3180 #endif /* ANDROID_BUILD */
3181 #endif /* CSR_SUPPORT_WEXT_AP */
3182 };
3183
3184 static const iw_handler unifi_handler[] =
3185 {
3186     (iw_handler) unifi_siwcommit,           /* SIOCSIWCOMMIT */
3187     (iw_handler) unifi_giwname,             /* SIOCGIWNAME */
3188     (iw_handler) NULL,                      /* SIOCSIWNWID */
3189     (iw_handler) NULL,                      /* SIOCGIWNWID */
3190     (iw_handler) unifi_siwfreq,             /* SIOCSIWFREQ */
3191     (iw_handler) unifi_giwfreq,             /* SIOCGIWFREQ */
3192     (iw_handler) unifi_siwmode,             /* SIOCSIWMODE */
3193     (iw_handler) unifi_giwmode,             /* SIOCGIWMODE */
3194     (iw_handler) NULL,                      /* SIOCSIWSENS */
3195     (iw_handler) NULL,                      /* SIOCGIWSENS */
3196     (iw_handler) NULL,                      /* SIOCSIWRANGE */
3197     (iw_handler) unifi_giwrange,            /* SIOCGIWRANGE */
3198     (iw_handler) NULL,                      /* SIOCSIWPRIV */
3199     (iw_handler) NULL,                      /* SIOCGIWPRIV */
3200     (iw_handler) NULL,                      /* SIOCSIWSTATS */
3201     (iw_handler) NULL,                      /* SIOCGIWSTATS */
3202     (iw_handler) NULL,                      /* SIOCSIWSPY */
3203     (iw_handler) NULL,                      /* SIOCGIWSPY */
3204     (iw_handler) NULL,                      /* SIOCSIWTHRSPY */
3205     (iw_handler) NULL,                      /* SIOCGIWTHRSPY */
3206     (iw_handler) unifi_siwap,               /* SIOCSIWAP */
3207     (iw_handler) unifi_giwap,               /* SIOCGIWAP */
3208 #if WIRELESS_EXT > 17
3209     /* WPA : IEEE 802.11 MLME requests */
3210     unifi_siwmlme,              /* SIOCSIWMLME, request MLME operation */
3211 #else
3212     (iw_handler) NULL,                      /* -- hole -- */
3213 #endif
3214     (iw_handler) NULL,                      /* SIOCGIWAPLIST */
3215     (iw_handler) unifi_siwscan,             /* SIOCSIWSCAN */
3216     (iw_handler) unifi_giwscan,             /* SIOCGIWSCAN */
3217     (iw_handler) unifi_siwessid,            /* SIOCSIWESSID */
3218     (iw_handler) unifi_giwessid,            /* SIOCGIWESSID */
3219     (iw_handler) NULL,                      /* SIOCSIWNICKN */
3220     (iw_handler) NULL,                      /* SIOCGIWNICKN */
3221     (iw_handler) NULL,                      /* -- hole -- */
3222     (iw_handler) NULL,                      /* -- hole -- */
3223     unifi_siwrate,                          /* SIOCSIWRATE */
3224     unifi_giwrate,                          /* SIOCGIWRATE */
3225     unifi_siwrts,                           /* SIOCSIWRTS */
3226     unifi_giwrts,                           /* SIOCGIWRTS */
3227     unifi_siwfrag,                          /* SIOCSIWFRAG */
3228     unifi_giwfrag,                          /* SIOCGIWFRAG */
3229     (iw_handler) NULL,                      /* SIOCSIWTXPOW */
3230     (iw_handler) NULL,                      /* SIOCGIWTXPOW */
3231     (iw_handler) NULL,                      /* SIOCSIWRETRY */
3232     (iw_handler) NULL,                      /* SIOCGIWRETRY */
3233     unifi_siwencode,                        /* SIOCSIWENCODE */
3234     unifi_giwencode,                        /* SIOCGIWENCODE */
3235     unifi_siwpower,                         /* SIOCSIWPOWER */
3236     unifi_giwpower,                         /* SIOCGIWPOWER */
3237 #if WIRELESS_EXT > 17
3238     (iw_handler) NULL,                      /* -- hole -- */
3239     (iw_handler) NULL,                      /* -- hole -- */
3240
3241     /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). */
3242     unifi_siwgenie,             /* SIOCSIWGENIE */      /* set generic IE */
3243     unifi_giwgenie,             /* SIOCGIWGENIE */      /* get generic IE */
3244
3245     /* WPA : Authentication mode parameters */
3246     unifi_siwauth,              /* SIOCSIWAUTH */       /* set authentication mode params */
3247     unifi_giwauth,              /* SIOCGIWAUTH */       /* get authentication mode params */
3248
3249     /* WPA : Extended version of encoding configuration */
3250     unifi_siwencodeext,         /* SIOCSIWENCODEEXT */  /* set encoding token & mode */
3251     unifi_giwencodeext,         /* SIOCGIWENCODEEXT */  /* get encoding token & mode */
3252
3253     /* WPA2 : PMKSA cache management */
3254     unifi_siwpmksa,             /* SIOCSIWPMKSA */      /* PMKSA cache operation */
3255     (iw_handler) NULL,          /* -- hole -- */
3256 #endif /* WIRELESS_EXT > 17 */
3257 };
3258
3259
3260 static const iw_handler unifi_private_handler[] =
3261 {
3262     iwprivs80211ps,                 /* SIOCIWFIRSTPRIV */
3263     iwprivg80211ps,                 /* SIOCIWFIRSTPRIV + 1 */
3264     iwprivsdefs,                    /* SIOCIWFIRSTPRIV + 2 */
3265     (iw_handler) NULL,
3266 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3267     iwprivsconfwapi,                /* SIOCIWFIRSTPRIV + 4 */
3268     (iw_handler) NULL,              /* SIOCIWFIRSTPRIV + 5 */
3269     iwprivswpikey,                  /* SIOCIWFIRSTPRIV + 6 */
3270 #else
3271     (iw_handler) NULL,
3272     (iw_handler) NULL,
3273     (iw_handler) NULL,
3274 #endif
3275     (iw_handler) NULL,
3276     iwprivssmedebug,                /* SIOCIWFIRSTPRIV + 8 */
3277 #ifdef CSR_SUPPORT_WEXT_AP
3278     (iw_handler) NULL,
3279     iwprivsapconfig,
3280     (iw_handler) NULL,
3281     iwprivsapstart,
3282     (iw_handler) NULL,
3283     iwprivsapstop,
3284     (iw_handler) NULL,
3285 #ifdef ANDROID_BUILD
3286     iwprivsapfwreload,
3287     (iw_handler) NULL,
3288     iwprivsstackstart,
3289     (iw_handler) NULL,
3290     iwprivsstackstop,
3291 #else
3292     (iw_handler) NULL,
3293     (iw_handler) NULL,
3294     (iw_handler) NULL,
3295     (iw_handler) NULL,
3296     (iw_handler) NULL,
3297 #endif /* ANDROID_BUILD */
3298 #else
3299     (iw_handler) NULL,
3300     (iw_handler) NULL,
3301     (iw_handler) NULL,
3302     (iw_handler) NULL,
3303     (iw_handler) NULL,
3304     (iw_handler) NULL,
3305     (iw_handler) NULL,
3306     (iw_handler) NULL,
3307     (iw_handler) NULL,
3308     (iw_handler) NULL,
3309     (iw_handler) NULL,
3310     (iw_handler) NULL,
3311 #endif /* CSR_SUPPORT_WEXT_AP */
3312 };
3313
3314 struct iw_handler_def unifi_iw_handler_def =
3315 {
3316     .num_standard       = sizeof(unifi_handler) / sizeof(iw_handler),
3317     .num_private        = sizeof(unifi_private_handler) / sizeof(iw_handler),
3318     .num_private_args   = sizeof(unifi_private_args) / sizeof(struct iw_priv_args),
3319     .standard           = (iw_handler *) unifi_handler,
3320     .private            = (iw_handler *) unifi_private_handler,
3321     .private_args       = (struct iw_priv_args *) unifi_private_args,
3322 #if IW_HANDLER_VERSION >= 6
3323     .get_wireless_stats = unifi_get_wireless_stats,
3324 #endif
3325 };
3326
3327