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