linux/drivers/staging/wlan-ng/cfg80211.c
<<
>>
Prefs
   1/* cfg80211 Interface for prism2_usb module */
   2
   3
   4/* Prism2 channell/frequency/bitrate declarations */
   5static const struct ieee80211_channel prism2_channels[] = {
   6        { .center_freq = 2412 },
   7        { .center_freq = 2417 },
   8        { .center_freq = 2422 },
   9        { .center_freq = 2427 },
  10        { .center_freq = 2432 },
  11        { .center_freq = 2437 },
  12        { .center_freq = 2442 },
  13        { .center_freq = 2447 },
  14        { .center_freq = 2452 },
  15        { .center_freq = 2457 },
  16        { .center_freq = 2462 },
  17        { .center_freq = 2467 },
  18        { .center_freq = 2472 },
  19        { .center_freq = 2484 },
  20};
  21
  22static const struct ieee80211_rate prism2_rates[] = {
  23        { .bitrate = 10 },
  24        { .bitrate = 20 },
  25        { .bitrate = 55 },
  26        { .bitrate = 110 }
  27};
  28
  29#define PRISM2_NUM_CIPHER_SUITES 2
  30static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = {
  31        WLAN_CIPHER_SUITE_WEP40,
  32        WLAN_CIPHER_SUITE_WEP104
  33};
  34
  35
  36/* prism2 device private data */
  37struct prism2_wiphy_private {
  38        wlandevice_t *wlandev;
  39
  40        struct ieee80211_supported_band band;
  41        struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)];
  42        struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)];
  43
  44        struct cfg80211_scan_request *scan_request;
  45};
  46
  47static const void * const prism2_wiphy_privid = &prism2_wiphy_privid;
  48
  49
  50/* Helper Functions */
  51static int prism2_result2err(int prism2_result)
  52{
  53        int err = 0;
  54
  55        switch (prism2_result) {
  56        case P80211ENUM_resultcode_invalid_parameters:
  57                err = -EINVAL;
  58                break;
  59        case P80211ENUM_resultcode_implementation_failure:
  60                err = -EIO;
  61                break;
  62        case P80211ENUM_resultcode_not_supported:
  63                err = -EOPNOTSUPP;
  64                break;
  65        default:
  66                err = 0;
  67                break;
  68        }
  69
  70        return err;
  71}
  72
  73static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data)
  74{
  75        struct p80211msg_dot11req_mibset msg;
  76        p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
  77
  78        msg.msgcode = DIDmsg_dot11req_mibset;
  79        mibitem->did = did;
  80        mibitem->data = data;
  81
  82        return p80211req_dorequest(wlandev, (u8 *) &msg);
  83}
  84
  85static int prism2_domibset_pstr32(wlandevice_t *wlandev,
  86                                  u32 did, u8 len, u8 *data)
  87{
  88        struct p80211msg_dot11req_mibset msg;
  89        p80211item_pstr32_t *mibitem = (p80211item_pstr32_t *) &msg.mibattribute.data;
  90
  91        msg.msgcode = DIDmsg_dot11req_mibset;
  92        mibitem->did = did;
  93        mibitem->data.len = len;
  94        memcpy(mibitem->data.data, data, len);
  95
  96        return p80211req_dorequest(wlandev, (u8 *) &msg);
  97}
  98
  99
 100/* The interface functions, called by the cfg80211 layer */
 101int prism2_change_virtual_intf(struct wiphy *wiphy,
 102                               struct net_device *dev,
 103                               enum nl80211_iftype type, u32 *flags,
 104                               struct vif_params *params)
 105{
 106        wlandevice_t *wlandev = dev->ml_priv;
 107        u32 data;
 108        int result;
 109        int err = 0;
 110
 111        switch (type) {
 112        case NL80211_IFTYPE_ADHOC:
 113                if (wlandev->macmode == WLAN_MACMODE_IBSS_STA)
 114                        goto exit;
 115                wlandev->macmode = WLAN_MACMODE_IBSS_STA;
 116                data = 0;
 117                break;
 118        case NL80211_IFTYPE_STATION:
 119                if (wlandev->macmode == WLAN_MACMODE_ESS_STA)
 120                        goto exit;
 121                wlandev->macmode = WLAN_MACMODE_ESS_STA;
 122                data = 1;
 123                break;
 124        default:
 125                printk(KERN_WARNING "Operation mode: %d not support\n", type);
 126                return -EOPNOTSUPP;
 127        }
 128
 129        /* Set Operation mode to the PORT TYPE RID */
 130        result = prism2_domibset_uint32(wlandev, DIDmib_p2_p2Static_p2CnfPortType, data);
 131
 132        if (result)
 133                err = -EFAULT;
 134
 135        dev->ieee80211_ptr->iftype = type;
 136
 137exit:
 138        return err;
 139}
 140
 141int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
 142                   u8 key_index, bool pairwise, const u8 *mac_addr,
 143                   struct key_params *params)
 144{
 145        wlandevice_t *wlandev = dev->ml_priv;
 146        u32 did;
 147
 148        int err = 0;
 149        int result = 0;
 150
 151        switch (params->cipher) {
 152        case WLAN_CIPHER_SUITE_WEP40:
 153        case WLAN_CIPHER_SUITE_WEP104:
 154                result = prism2_domibset_uint32(wlandev,
 155                                                DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
 156                                                key_index);
 157                if (result)
 158                        goto exit;
 159
 160                /* send key to driver */
 161                switch (key_index) {
 162                case 0:
 163                        did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
 164                        break;
 165
 166                case 1:
 167                        did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
 168                        break;
 169
 170                case 2:
 171                        did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
 172                        break;
 173
 174                case 3:
 175                        did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
 176                        break;
 177
 178                default:
 179                        err = -EINVAL;
 180                        goto exit;
 181                }
 182
 183                result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key);
 184                if (result)
 185                        goto exit;
 186                break;
 187
 188        default:
 189                pr_debug("Unsupported cipher suite\n");
 190                result = 1;
 191        }
 192
 193exit:
 194        if (result)
 195                err = -EFAULT;
 196
 197        return err;
 198}
 199
 200int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
 201                   u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
 202                   void (*callback)(void *cookie, struct key_params*))
 203{
 204        wlandevice_t *wlandev = dev->ml_priv;
 205        struct key_params params;
 206        int len;
 207
 208        if (key_index >= NUM_WEPKEYS)
 209                return -EINVAL;
 210
 211        len = wlandev->wep_keylens[key_index];
 212        memset(&params, 0, sizeof(params));
 213
 214        if (len == 13)
 215                params.cipher = WLAN_CIPHER_SUITE_WEP104;
 216        else if (len == 5)
 217                params.cipher = WLAN_CIPHER_SUITE_WEP104;
 218        else
 219                return -ENOENT;
 220        params.key_len = len;
 221        params.key = wlandev->wep_keys[key_index];
 222        params.seq_len = 0;
 223
 224        callback(cookie, &params);
 225
 226        return 0;
 227}
 228
 229int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
 230                   u8 key_index, bool pairwise, const u8 *mac_addr)
 231{
 232        wlandevice_t *wlandev = dev->ml_priv;
 233        u32 did;
 234        int err = 0;
 235        int result = 0;
 236
 237        /* There is no direct way in the hardware (AFAIK) of removing
 238           a key, so we will cheat by setting the key to a bogus value */
 239        /* send key to driver */
 240        switch (key_index) {
 241        case 0:
 242                did =
 243                    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
 244                break;
 245
 246        case 1:
 247                did =
 248                    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
 249                break;
 250
 251        case 2:
 252                did =
 253                    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
 254                break;
 255
 256        case 3:
 257                did =
 258                    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
 259                break;
 260
 261        default:
 262                err = -EINVAL;
 263                goto exit;
 264        }
 265
 266        result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000");
 267
 268exit:
 269        if (result)
 270                err = -EFAULT;
 271
 272        return err;
 273}
 274
 275int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
 276                           u8 key_index)
 277{
 278        wlandevice_t *wlandev = dev->ml_priv;
 279
 280        int err = 0;
 281        int result = 0;
 282
 283        result = prism2_domibset_uint32(wlandev,
 284                DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
 285                key_index);
 286
 287        if (result)
 288                err = -EFAULT;
 289
 290        return err;
 291}
 292
 293
 294int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
 295                       u8 *mac, struct station_info *sinfo)
 296{
 297        wlandevice_t *wlandev = dev->ml_priv;
 298        struct p80211msg_lnxreq_commsquality quality;
 299        int result;
 300
 301        memset(sinfo, 0, sizeof(*sinfo));
 302
 303        if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
 304                return -EOPNOTSUPP;
 305
 306        /* build request message */
 307        quality.msgcode = DIDmsg_lnxreq_commsquality;
 308        quality.dbm.data = P80211ENUM_truth_true;
 309        quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
 310
 311        /* send message to nsd */
 312        if (wlandev->mlmerequest == NULL)
 313                return -EOPNOTSUPP;
 314
 315        result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality);
 316
 317
 318        if (result == 0) {
 319                sinfo->txrate.legacy = quality.txrate.data;
 320                sinfo->filled |= STATION_INFO_TX_BITRATE;
 321                sinfo->signal = quality.level.data;
 322                sinfo->filled |= STATION_INFO_SIGNAL;
 323        }
 324
 325        return result;
 326}
 327
 328int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
 329                struct cfg80211_scan_request *request)
 330{
 331        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 332        wlandevice_t *wlandev = dev->ml_priv;
 333        struct p80211msg_dot11req_scan msg1;
 334        struct p80211msg_dot11req_scan_results msg2;
 335        int result;
 336        int err = 0;
 337        int numbss = 0;
 338        int i = 0;
 339        u8 ie_buf[46];
 340        int ie_len;
 341
 342        if (!request)
 343                return -EINVAL;
 344
 345        if (priv->scan_request && priv->scan_request != request)
 346                return -EBUSY;
 347
 348        if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
 349                printk(KERN_ERR "Can't scan in AP mode\n");
 350                return -EOPNOTSUPP;
 351        }
 352
 353        priv->scan_request = request;
 354
 355        memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan));
 356        msg1.msgcode = DIDmsg_dot11req_scan;
 357        msg1.bsstype.data = P80211ENUM_bsstype_any;
 358
 359        memset(&(msg1.bssid.data), 0xFF, sizeof(p80211item_pstr6_t));
 360        msg1.bssid.data.len = 6;
 361
 362        if (request->n_ssids > 0) {
 363                msg1.scantype.data = P80211ENUM_scantype_active;
 364                msg1.ssid.data.len = request->ssids->ssid_len;
 365                memcpy(msg1.ssid.data.data, request->ssids->ssid, request->ssids->ssid_len);
 366        } else {
 367                msg1.scantype.data = 0;
 368        }
 369        msg1.probedelay.data = 0;
 370
 371        for (i = 0;
 372                (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
 373                i++)
 374                msg1.channellist.data.data[i] =
 375                        ieee80211_frequency_to_channel(request->channels[i]->center_freq);
 376        msg1.channellist.data.len = request->n_channels;
 377
 378        msg1.maxchanneltime.data = 250;
 379        msg1.minchanneltime.data = 200;
 380
 381        result = p80211req_dorequest(wlandev, (u8 *) &msg1);
 382        if (result) {
 383                err = prism2_result2err(msg1.resultcode.data);
 384                goto exit;
 385        }
 386        /* Now retrieve scan results */
 387        numbss = msg1.numbss.data;
 388
 389        for (i = 0; i < numbss; i++) {
 390                memset(&msg2, 0, sizeof(msg2));
 391                msg2.msgcode = DIDmsg_dot11req_scan_results;
 392                msg2.bssindex.data = i;
 393
 394                result = p80211req_dorequest(wlandev, (u8 *) &msg2);
 395                if ((result != 0) ||
 396                    (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
 397                        break;
 398                }
 399
 400                ie_buf[0] = WLAN_EID_SSID;
 401                ie_buf[1] = msg2.ssid.data.len;
 402                ie_len = ie_buf[1] + 2;
 403                memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
 404                cfg80211_inform_bss(wiphy,
 405                        ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)),
 406                        (const u8 *) &(msg2.bssid.data.data),
 407                        msg2.timestamp.data, msg2.capinfo.data,
 408                        msg2.beaconperiod.data,
 409                        ie_buf,
 410                        ie_len,
 411                        (msg2.signal.data - 65536) * 100, /* Conversion to signed type */
 412                        GFP_KERNEL
 413                );
 414        }
 415
 416        if (result)
 417                err = prism2_result2err(msg2.resultcode.data);
 418
 419exit:
 420        cfg80211_scan_done(request, err ? 1 : 0);
 421        priv->scan_request = NULL;
 422        return err;
 423}
 424
 425int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 426{
 427        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 428        wlandevice_t *wlandev = priv->wlandev;
 429        u32 data;
 430        int result;
 431        int err = 0;
 432
 433        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
 434                if (wiphy->rts_threshold == -1)
 435                        data = 2347;
 436                else
 437                        data = wiphy->rts_threshold;
 438
 439                result = prism2_domibset_uint32(wlandev,
 440                                                DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
 441                                                data);
 442                if (result) {
 443                        err = -EFAULT;
 444                        goto exit;
 445                }
 446        }
 447
 448        if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
 449                if (wiphy->frag_threshold == -1)
 450                        data = 2346;
 451                else
 452                        data = wiphy->frag_threshold;
 453
 454                result = prism2_domibset_uint32(wlandev,
 455                                                DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
 456                                                data);
 457                if (result) {
 458                        err = -EFAULT;
 459                        goto exit;
 460                }
 461        }
 462
 463exit:
 464        return err;
 465}
 466
 467int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
 468                   struct cfg80211_connect_params *sme)
 469{
 470        wlandevice_t *wlandev = dev->ml_priv;
 471        struct ieee80211_channel *channel = sme->channel;
 472        struct p80211msg_lnxreq_autojoin msg_join;
 473        u32 did;
 474        int length = sme->ssid_len;
 475        int chan = -1;
 476        int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
 477            (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
 478        int result;
 479        int err = 0;
 480
 481        /* Set the channel */
 482        if (channel) {
 483                chan = ieee80211_frequency_to_channel(channel->center_freq);
 484                result = prism2_domibset_uint32(wlandev,
 485                                                DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
 486                                                chan);
 487                if (result)
 488                        goto exit;
 489        }
 490
 491        /* Set the authorisation */
 492        if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
 493                ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
 494                        msg_join.authtype.data = P80211ENUM_authalg_opensystem;
 495        else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
 496                ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
 497                        msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
 498        else
 499                printk(KERN_WARNING
 500                        "Unhandled authorisation type for connect (%d)\n",
 501                        sme->auth_type);
 502
 503        /* Set the encryption - we only support wep */
 504        if (is_wep) {
 505                if (sme->key) {
 506                        result = prism2_domibset_uint32(wlandev,
 507                                DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
 508                                sme->key_idx);
 509                        if (result)
 510                                goto exit;
 511
 512                        /* send key to driver */
 513                        switch (sme->key_idx) {
 514                        case 0:
 515                                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
 516                                break;
 517
 518                        case 1:
 519                                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
 520                                break;
 521
 522                        case 2:
 523                                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
 524                                break;
 525
 526                        case 3:
 527                                did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
 528                                break;
 529
 530                        default:
 531                                err = -EINVAL;
 532                                goto exit;
 533                        }
 534
 535                        result = prism2_domibset_pstr32(wlandev, did, sme->key_len, (u8 *) sme->key);
 536                        if (result)
 537                                goto exit;
 538
 539                }
 540
 541                /* Assume we should set privacy invoked and exclude unencrypted
 542                   We could possibly use sme->privacy here, but the assumption
 543                   seems reasonable anyway */
 544                result = prism2_domibset_uint32(wlandev,
 545                                                DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
 546                                                P80211ENUM_truth_true);
 547                if (result)
 548                        goto exit;
 549
 550                result = prism2_domibset_uint32(wlandev,
 551                                                DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
 552                                                P80211ENUM_truth_true);
 553                if (result)
 554                        goto exit;
 555
 556        } else {
 557                /* Assume we should unset privacy invoked
 558                   and exclude unencrypted */
 559                result = prism2_domibset_uint32(wlandev,
 560                                                DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
 561                                                P80211ENUM_truth_false);
 562                if (result)
 563                        goto exit;
 564
 565                result = prism2_domibset_uint32(wlandev,
 566                                                DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
 567                                                P80211ENUM_truth_false);
 568                if (result)
 569                        goto exit;
 570
 571        }
 572
 573        /* Now do the actual join. Note there is no way that I can
 574           see to request a specific bssid */
 575        msg_join.msgcode = DIDmsg_lnxreq_autojoin;
 576
 577        memcpy(msg_join.ssid.data.data, sme->ssid, length);
 578        msg_join.ssid.data.len = length;
 579
 580        result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
 581
 582exit:
 583        if (result)
 584                err = -EFAULT;
 585
 586        return err;
 587}
 588
 589int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
 590                      u16 reason_code)
 591{
 592        wlandevice_t *wlandev = dev->ml_priv;
 593        struct p80211msg_lnxreq_autojoin msg_join;
 594        int result;
 595        int err = 0;
 596
 597
 598        /* Do a join, with a bogus ssid. Thats the only way I can think of */
 599        msg_join.msgcode = DIDmsg_lnxreq_autojoin;
 600
 601        memcpy(msg_join.ssid.data.data, "---", 3);
 602        msg_join.ssid.data.len = 3;
 603
 604        result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
 605
 606        if (result)
 607                err = -EFAULT;
 608
 609        return err;
 610}
 611
 612
 613int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 614                     struct cfg80211_ibss_params *params)
 615{
 616        return -EOPNOTSUPP;
 617}
 618
 619int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 620{
 621        return -EOPNOTSUPP;
 622}
 623
 624
 625int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
 626                        int mbm)
 627{
 628        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 629        wlandevice_t *wlandev = priv->wlandev;
 630        u32 data;
 631        int result;
 632        int err = 0;
 633
 634        if (type == NL80211_TX_POWER_AUTOMATIC)
 635                data = 30;
 636        else
 637                data = MBM_TO_DBM(mbm);
 638
 639        result = prism2_domibset_uint32(wlandev,
 640                DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
 641                data);
 642
 643        if (result) {
 644                err = -EFAULT;
 645                goto exit;
 646        }
 647
 648exit:
 649        return err;
 650}
 651
 652int prism2_get_tx_power(struct wiphy *wiphy, int *dbm)
 653{
 654        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 655        wlandevice_t *wlandev = priv->wlandev;
 656        struct p80211msg_dot11req_mibget msg;
 657        p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
 658        int result;
 659        int err = 0;
 660
 661        msg.msgcode = DIDmsg_dot11req_mibget;
 662        mibitem->did =
 663            DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
 664
 665        result = p80211req_dorequest(wlandev, (u8 *) &msg);
 666
 667        if (result) {
 668                err = -EFAULT;
 669                goto exit;
 670        }
 671
 672        *dbm = mibitem->data;
 673
 674exit:
 675        return err;
 676}
 677
 678
 679
 680
 681/* Interface callback functions, passing data back up to the cfg80211 layer */
 682void prism2_connect_result(wlandevice_t *wlandev, u8 failed)
 683{
 684        u16 status = failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS;
 685
 686        cfg80211_connect_result(wlandev->netdev, wlandev->bssid,
 687                                NULL, 0, NULL, 0, status, GFP_KERNEL);
 688}
 689
 690void prism2_disconnected(wlandevice_t *wlandev)
 691{
 692        cfg80211_disconnected(wlandev->netdev, 0, NULL,
 693                0, GFP_KERNEL);
 694}
 695
 696void prism2_roamed(wlandevice_t *wlandev)
 697{
 698        cfg80211_roamed(wlandev->netdev, wlandev->bssid,
 699                NULL, 0, NULL, 0, GFP_KERNEL);
 700}
 701
 702
 703/* Structures for declaring wiphy interface */
 704static const struct cfg80211_ops prism2_usb_cfg_ops = {
 705        .change_virtual_intf = prism2_change_virtual_intf,
 706        .add_key = prism2_add_key,
 707        .get_key = prism2_get_key,
 708        .del_key = prism2_del_key,
 709        .set_default_key = prism2_set_default_key,
 710        .get_station = prism2_get_station,
 711        .scan = prism2_scan,
 712        .set_wiphy_params = prism2_set_wiphy_params,
 713        .connect = prism2_connect,
 714        .disconnect = prism2_disconnect,
 715        .join_ibss = prism2_join_ibss,
 716        .leave_ibss = prism2_leave_ibss,
 717        .set_tx_power = prism2_set_tx_power,
 718        .get_tx_power = prism2_get_tx_power,
 719};
 720
 721
 722/* Functions to create/free wiphy interface */
 723struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev)
 724{
 725        struct wiphy *wiphy;
 726        struct prism2_wiphy_private *priv;
 727        wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(struct prism2_wiphy_private));
 728        if (!wiphy)
 729                return NULL;
 730
 731        priv = wiphy_priv(wiphy);
 732        priv->wlandev = wlandev;
 733        memcpy(priv->channels, prism2_channels, sizeof(prism2_channels));
 734        memcpy(priv->rates, prism2_rates, sizeof(prism2_rates));
 735        priv->band.channels = priv->channels;
 736        priv->band.n_channels = ARRAY_SIZE(prism2_channels);
 737        priv->band.bitrates = priv->rates;
 738        priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
 739        priv->band.band = IEEE80211_BAND_2GHZ;
 740        priv->band.ht_cap.ht_supported = false;
 741        wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
 742
 743        set_wiphy_dev(wiphy, dev);
 744        wiphy->privid = prism2_wiphy_privid;
 745        wiphy->max_scan_ssids = 1;
 746        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
 747                                 | BIT(NL80211_IFTYPE_ADHOC);
 748        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 749        wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES;
 750        wiphy->cipher_suites = prism2_cipher_suites;
 751
 752        if (wiphy_register(wiphy) < 0)
 753                return NULL;
 754
 755        return wiphy;
 756}
 757
 758
 759void wlan_free_wiphy(struct wiphy *wiphy)
 760{
 761        wiphy_unregister(wiphy);
 762        wiphy_free(wiphy);
 763}
 764