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

Archive Download this file



interactive