1cb3126e6SKarl Relton /* cfg80211 Interface for prism2_usb module */ 26eaf0788STair Rzayev #include "hfa384x.h" 36eaf0788STair Rzayev #include "prism2mgmt.h" 4cb3126e6SKarl Relton 5cb3126e6SKarl Relton 6d34602deSJustin P. Mattock /* Prism2 channel/frequency/bitrate declarations */ 7cb3126e6SKarl Relton static const struct ieee80211_channel prism2_channels[] = { 8cb3126e6SKarl Relton { .center_freq = 2412 }, 9cb3126e6SKarl Relton { .center_freq = 2417 }, 10cb3126e6SKarl Relton { .center_freq = 2422 }, 11cb3126e6SKarl Relton { .center_freq = 2427 }, 12cb3126e6SKarl Relton { .center_freq = 2432 }, 13cb3126e6SKarl Relton { .center_freq = 2437 }, 14cb3126e6SKarl Relton { .center_freq = 2442 }, 15cb3126e6SKarl Relton { .center_freq = 2447 }, 16cb3126e6SKarl Relton { .center_freq = 2452 }, 17cb3126e6SKarl Relton { .center_freq = 2457 }, 18cb3126e6SKarl Relton { .center_freq = 2462 }, 19cb3126e6SKarl Relton { .center_freq = 2467 }, 20cb3126e6SKarl Relton { .center_freq = 2472 }, 21cb3126e6SKarl Relton { .center_freq = 2484 }, 22cb3126e6SKarl Relton }; 23cb3126e6SKarl Relton 24cb3126e6SKarl Relton static const struct ieee80211_rate prism2_rates[] = { 25cb3126e6SKarl Relton { .bitrate = 10 }, 26cb3126e6SKarl Relton { .bitrate = 20 }, 27cb3126e6SKarl Relton { .bitrate = 55 }, 28cb3126e6SKarl Relton { .bitrate = 110 } 29cb3126e6SKarl Relton }; 30cb3126e6SKarl Relton 31cb3126e6SKarl Relton #define PRISM2_NUM_CIPHER_SUITES 2 32cb3126e6SKarl Relton static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = { 33cb3126e6SKarl Relton WLAN_CIPHER_SUITE_WEP40, 34cb3126e6SKarl Relton WLAN_CIPHER_SUITE_WEP104 35cb3126e6SKarl Relton }; 36cb3126e6SKarl Relton 37cb3126e6SKarl Relton 38cb3126e6SKarl Relton /* prism2 device private data */ 39cb3126e6SKarl Relton struct prism2_wiphy_private { 40cb3126e6SKarl Relton wlandevice_t *wlandev; 41cb3126e6SKarl Relton 42cb3126e6SKarl Relton struct ieee80211_supported_band band; 43cb3126e6SKarl Relton struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)]; 44cb3126e6SKarl Relton struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)]; 45cb3126e6SKarl Relton 46cb3126e6SKarl Relton struct cfg80211_scan_request *scan_request; 47cb3126e6SKarl Relton }; 48cb3126e6SKarl Relton 49cb3126e6SKarl Relton static const void * const prism2_wiphy_privid = &prism2_wiphy_privid; 50cb3126e6SKarl Relton 51cb3126e6SKarl Relton 52cb3126e6SKarl Relton /* Helper Functions */ 53cb3126e6SKarl Relton static int prism2_result2err(int prism2_result) 54cb3126e6SKarl Relton { 55cb3126e6SKarl Relton int err = 0; 56cb3126e6SKarl Relton 57cb3126e6SKarl Relton switch (prism2_result) { 58cb3126e6SKarl Relton case P80211ENUM_resultcode_invalid_parameters: 59cb3126e6SKarl Relton err = -EINVAL; 60cb3126e6SKarl Relton break; 61cb3126e6SKarl Relton case P80211ENUM_resultcode_implementation_failure: 62cb3126e6SKarl Relton err = -EIO; 63cb3126e6SKarl Relton break; 64cb3126e6SKarl Relton case P80211ENUM_resultcode_not_supported: 65cb3126e6SKarl Relton err = -EOPNOTSUPP; 66cb3126e6SKarl Relton break; 67cb3126e6SKarl Relton default: 68cb3126e6SKarl Relton err = 0; 69cb3126e6SKarl Relton break; 70cb3126e6SKarl Relton } 71cb3126e6SKarl Relton 72cb3126e6SKarl Relton return err; 73cb3126e6SKarl Relton } 74cb3126e6SKarl Relton 75cb3126e6SKarl Relton static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) 76cb3126e6SKarl Relton { 77b6bb56e6SEdgardo Hames struct p80211msg_dot11req_mibset msg; 78bb1da756SHimangi Saraogi p80211item_uint32_t *mibitem = 79bb1da756SHimangi Saraogi (p80211item_uint32_t *) &msg.mibattribute.data; 80cb3126e6SKarl Relton 81cb3126e6SKarl Relton msg.msgcode = DIDmsg_dot11req_mibset; 82cb3126e6SKarl Relton mibitem->did = did; 83cb3126e6SKarl Relton mibitem->data = data; 84cb3126e6SKarl Relton 85cb3126e6SKarl Relton return p80211req_dorequest(wlandev, (u8 *) &msg); 86cb3126e6SKarl Relton } 87cb3126e6SKarl Relton 88cb3126e6SKarl Relton static int prism2_domibset_pstr32(wlandevice_t *wlandev, 89c1e5f471SJohannes Berg u32 did, u8 len, const u8 *data) 90cb3126e6SKarl Relton { 91b6bb56e6SEdgardo Hames struct p80211msg_dot11req_mibset msg; 92bb1da756SHimangi Saraogi p80211item_pstr32_t *mibitem = 93bb1da756SHimangi Saraogi (p80211item_pstr32_t *) &msg.mibattribute.data; 94cb3126e6SKarl Relton 95cb3126e6SKarl Relton msg.msgcode = DIDmsg_dot11req_mibset; 96cb3126e6SKarl Relton mibitem->did = did; 97cb3126e6SKarl Relton mibitem->data.len = len; 98cb3126e6SKarl Relton memcpy(mibitem->data.data, data, len); 99cb3126e6SKarl Relton 100cb3126e6SKarl Relton return p80211req_dorequest(wlandev, (u8 *) &msg); 101cb3126e6SKarl Relton } 102cb3126e6SKarl Relton 103cb3126e6SKarl Relton 104cb3126e6SKarl Relton /* The interface functions, called by the cfg80211 layer */ 10555da06ebSTeodora Baluta static int prism2_change_virtual_intf(struct wiphy *wiphy, 106cb3126e6SKarl Relton struct net_device *dev, 107cb3126e6SKarl Relton enum nl80211_iftype type, u32 *flags, 108cb3126e6SKarl Relton struct vif_params *params) 109cb3126e6SKarl Relton { 110cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 111cb3126e6SKarl Relton u32 data; 112cb3126e6SKarl Relton int result; 113cb3126e6SKarl Relton int err = 0; 114cb3126e6SKarl Relton 115cb3126e6SKarl Relton switch (type) { 116cb3126e6SKarl Relton case NL80211_IFTYPE_ADHOC: 1178dd82ebeSEdgardo Hames if (wlandev->macmode == WLAN_MACMODE_IBSS_STA) 1188dd82ebeSEdgardo Hames goto exit; 119cb3126e6SKarl Relton wlandev->macmode = WLAN_MACMODE_IBSS_STA; 120cb3126e6SKarl Relton data = 0; 121cb3126e6SKarl Relton break; 122cb3126e6SKarl Relton case NL80211_IFTYPE_STATION: 1238dd82ebeSEdgardo Hames if (wlandev->macmode == WLAN_MACMODE_ESS_STA) 1248dd82ebeSEdgardo Hames goto exit; 125cb3126e6SKarl Relton wlandev->macmode = WLAN_MACMODE_ESS_STA; 126cb3126e6SKarl Relton data = 1; 127cb3126e6SKarl Relton break; 128cb3126e6SKarl Relton default: 129eed88971SAvinash Kumar netdev_warn(dev, "Operation mode: %d not support\n", type); 130cb3126e6SKarl Relton return -EOPNOTSUPP; 131cb3126e6SKarl Relton } 132cb3126e6SKarl Relton 133cb3126e6SKarl Relton /* Set Operation mode to the PORT TYPE RID */ 1348aac4d44SDevendra Naga result = prism2_domibset_uint32(wlandev, 1358aac4d44SDevendra Naga DIDmib_p2_p2Static_p2CnfPortType, 1368aac4d44SDevendra Naga data); 137cb3126e6SKarl Relton 138cb3126e6SKarl Relton if (result) 139cb3126e6SKarl Relton err = -EFAULT; 140cb3126e6SKarl Relton 141cb3126e6SKarl Relton dev->ieee80211_ptr->iftype = type; 142cb3126e6SKarl Relton 143cb3126e6SKarl Relton exit: 144cb3126e6SKarl Relton return err; 145cb3126e6SKarl Relton } 146cb3126e6SKarl Relton 14755da06ebSTeodora Baluta static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, 14834a488c1SBen Hutchings u8 key_index, bool pairwise, const u8 *mac_addr, 1498dd82ebeSEdgardo Hames struct key_params *params) 1508dd82ebeSEdgardo Hames { 151cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 152cb3126e6SKarl Relton u32 did; 153cb3126e6SKarl Relton 154cb3126e6SKarl Relton int err = 0; 155cb3126e6SKarl Relton int result = 0; 156cb3126e6SKarl Relton 157cb3126e6SKarl Relton switch (params->cipher) { 158cb3126e6SKarl Relton case WLAN_CIPHER_SUITE_WEP40: 159cb3126e6SKarl Relton case WLAN_CIPHER_SUITE_WEP104: 160cb3126e6SKarl Relton result = prism2_domibset_uint32(wlandev, 161cb3126e6SKarl Relton DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, 162cb3126e6SKarl Relton key_index); 1638dd82ebeSEdgardo Hames if (result) 1648dd82ebeSEdgardo Hames goto exit; 165cb3126e6SKarl Relton 166cb3126e6SKarl Relton /* send key to driver */ 167cb3126e6SKarl Relton switch (key_index) { 168cb3126e6SKarl Relton case 0: 1698dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; 170cb3126e6SKarl Relton break; 171cb3126e6SKarl Relton 172cb3126e6SKarl Relton case 1: 1738dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; 174cb3126e6SKarl Relton break; 175cb3126e6SKarl Relton 176cb3126e6SKarl Relton case 2: 1778dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; 178cb3126e6SKarl Relton break; 179cb3126e6SKarl Relton 180cb3126e6SKarl Relton case 3: 1818dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; 182cb3126e6SKarl Relton break; 183cb3126e6SKarl Relton 184cb3126e6SKarl Relton default: 185cb3126e6SKarl Relton err = -EINVAL; 186cb3126e6SKarl Relton goto exit; 187cb3126e6SKarl Relton } 188cb3126e6SKarl Relton 189bb1da756SHimangi Saraogi result = prism2_domibset_pstr32(wlandev, did, 190bb1da756SHimangi Saraogi params->key_len, params->key); 1918dd82ebeSEdgardo Hames if (result) 1928dd82ebeSEdgardo Hames goto exit; 193cb3126e6SKarl Relton break; 194cb3126e6SKarl Relton 195cb3126e6SKarl Relton default: 196cb3126e6SKarl Relton pr_debug("Unsupported cipher suite\n"); 197cb3126e6SKarl Relton result = 1; 198cb3126e6SKarl Relton } 199cb3126e6SKarl Relton 200cb3126e6SKarl Relton exit: 2018dd82ebeSEdgardo Hames if (result) 2028dd82ebeSEdgardo Hames err = -EFAULT; 203cb3126e6SKarl Relton 204cb3126e6SKarl Relton return err; 205cb3126e6SKarl Relton } 206cb3126e6SKarl Relton 20755da06ebSTeodora Baluta static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, 20855da06ebSTeodora Baluta u8 key_index, bool pairwise, 20955da06ebSTeodora Baluta const u8 *mac_addr, void *cookie, 2108dd82ebeSEdgardo Hames void (*callback)(void *cookie, struct key_params*)) 2118dd82ebeSEdgardo Hames { 212cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 213cb3126e6SKarl Relton struct key_params params; 214cb3126e6SKarl Relton int len; 215cb3126e6SKarl Relton 2168dd82ebeSEdgardo Hames if (key_index >= NUM_WEPKEYS) 2178dd82ebeSEdgardo Hames return -EINVAL; 218cb3126e6SKarl Relton 219cb3126e6SKarl Relton len = wlandev->wep_keylens[key_index]; 220cb3126e6SKarl Relton memset(¶ms, 0, sizeof(params)); 221cb3126e6SKarl Relton 2228dd82ebeSEdgardo Hames if (len == 13) 223cb3126e6SKarl Relton params.cipher = WLAN_CIPHER_SUITE_WEP104; 2248dd82ebeSEdgardo Hames else if (len == 5) 225cb3126e6SKarl Relton params.cipher = WLAN_CIPHER_SUITE_WEP104; 2268dd82ebeSEdgardo Hames else 2278dd82ebeSEdgardo Hames return -ENOENT; 228cb3126e6SKarl Relton params.key_len = len; 229cb3126e6SKarl Relton params.key = wlandev->wep_keys[key_index]; 230aff3ea4eSKarl Relton params.seq_len = 0; 231cb3126e6SKarl Relton 232cb3126e6SKarl Relton callback(cookie, ¶ms); 2338dd82ebeSEdgardo Hames 234cb3126e6SKarl Relton return 0; 235cb3126e6SKarl Relton } 236cb3126e6SKarl Relton 23755da06ebSTeodora Baluta static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, 23834a488c1SBen Hutchings u8 key_index, bool pairwise, const u8 *mac_addr) 2398dd82ebeSEdgardo Hames { 240cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 241cb3126e6SKarl Relton u32 did; 242cb3126e6SKarl Relton int err = 0; 243cb3126e6SKarl Relton int result = 0; 244cb3126e6SKarl Relton 245cb3126e6SKarl Relton /* There is no direct way in the hardware (AFAIK) of removing 246cb3126e6SKarl Relton a key, so we will cheat by setting the key to a bogus value */ 247cb3126e6SKarl Relton /* send key to driver */ 248cb3126e6SKarl Relton switch (key_index) { 249cb3126e6SKarl Relton case 0: 250cb3126e6SKarl Relton did = 251cb3126e6SKarl Relton DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; 252cb3126e6SKarl Relton break; 253cb3126e6SKarl Relton 254cb3126e6SKarl Relton case 1: 255cb3126e6SKarl Relton did = 256cb3126e6SKarl Relton DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; 257cb3126e6SKarl Relton break; 258cb3126e6SKarl Relton 259cb3126e6SKarl Relton case 2: 260cb3126e6SKarl Relton did = 261cb3126e6SKarl Relton DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; 262cb3126e6SKarl Relton break; 263cb3126e6SKarl Relton 264cb3126e6SKarl Relton case 3: 265cb3126e6SKarl Relton did = 266cb3126e6SKarl Relton DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; 267cb3126e6SKarl Relton break; 268cb3126e6SKarl Relton 269cb3126e6SKarl Relton default: 270cb3126e6SKarl Relton err = -EINVAL; 271cb3126e6SKarl Relton goto exit; 272cb3126e6SKarl Relton } 273cb3126e6SKarl Relton 274cb3126e6SKarl Relton result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000"); 275cb3126e6SKarl Relton 276cb3126e6SKarl Relton exit: 2778dd82ebeSEdgardo Hames if (result) 2788dd82ebeSEdgardo Hames err = -EFAULT; 279cb3126e6SKarl Relton 280cb3126e6SKarl Relton return err; 281cb3126e6SKarl Relton } 282cb3126e6SKarl Relton 28355da06ebSTeodora Baluta static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, 2849005fcd8SHarry Wei u8 key_index, bool unicast, bool multicast) 2858dd82ebeSEdgardo Hames { 286cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 287cb3126e6SKarl Relton 288cb3126e6SKarl Relton int err = 0; 289cb3126e6SKarl Relton int result = 0; 290cb3126e6SKarl Relton 291cb3126e6SKarl Relton result = prism2_domibset_uint32(wlandev, 292cb3126e6SKarl Relton DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, 293cb3126e6SKarl Relton key_index); 294cb3126e6SKarl Relton 2958dd82ebeSEdgardo Hames if (result) 2968dd82ebeSEdgardo Hames err = -EFAULT; 297cb3126e6SKarl Relton 298cb3126e6SKarl Relton return err; 299cb3126e6SKarl Relton } 300cb3126e6SKarl Relton 301cb3126e6SKarl Relton 30255da06ebSTeodora Baluta static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, 3033b3a0162SJohannes Berg const u8 *mac, struct station_info *sinfo) 3048dd82ebeSEdgardo Hames { 305cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 306b6bb56e6SEdgardo Hames struct p80211msg_lnxreq_commsquality quality; 307cb3126e6SKarl Relton int result; 308cb3126e6SKarl Relton 309cb3126e6SKarl Relton memset(sinfo, 0, sizeof(*sinfo)); 310cb3126e6SKarl Relton 311cb3126e6SKarl Relton if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) 312cb3126e6SKarl Relton return -EOPNOTSUPP; 313cb3126e6SKarl Relton 314cb3126e6SKarl Relton /* build request message */ 315cb3126e6SKarl Relton quality.msgcode = DIDmsg_lnxreq_commsquality; 316cb3126e6SKarl Relton quality.dbm.data = P80211ENUM_truth_true; 317cb3126e6SKarl Relton quality.dbm.status = P80211ENUM_msgitem_status_data_ok; 318cb3126e6SKarl Relton 319cb3126e6SKarl Relton /* send message to nsd */ 320cb3126e6SKarl Relton if (wlandev->mlmerequest == NULL) 321cb3126e6SKarl Relton return -EOPNOTSUPP; 322cb3126e6SKarl Relton 3233d049431SEdgardo Hames result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality); 324cb3126e6SKarl Relton 325cb3126e6SKarl Relton 326cb3126e6SKarl Relton if (result == 0) { 327cb3126e6SKarl Relton sinfo->txrate.legacy = quality.txrate.data; 328319090bfSJohannes Berg sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); 329cb3126e6SKarl Relton sinfo->signal = quality.level.data; 330319090bfSJohannes Berg sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); 331cb3126e6SKarl Relton } 332cb3126e6SKarl Relton 333cb3126e6SKarl Relton return result; 334cb3126e6SKarl Relton } 335cb3126e6SKarl Relton 336bb1da756SHimangi Saraogi static int prism2_scan(struct wiphy *wiphy, 337bb1da756SHimangi Saraogi struct cfg80211_scan_request *request) 338cb3126e6SKarl Relton { 3395d5d7c3bSEmil Goode struct net_device *dev; 340cb3126e6SKarl Relton struct prism2_wiphy_private *priv = wiphy_priv(wiphy); 3415d5d7c3bSEmil Goode wlandevice_t *wlandev; 342b6bb56e6SEdgardo Hames struct p80211msg_dot11req_scan msg1; 343b6bb56e6SEdgardo Hames struct p80211msg_dot11req_scan_results msg2; 34419f798adSKrzysztof Wilczynski struct cfg80211_bss *bss; 345cb3126e6SKarl Relton int result; 346cb3126e6SKarl Relton int err = 0; 347cb3126e6SKarl Relton int numbss = 0; 348cb3126e6SKarl Relton int i = 0; 349cb3126e6SKarl Relton u8 ie_buf[46]; 350cb3126e6SKarl Relton int ie_len; 351cb3126e6SKarl Relton 352cb3126e6SKarl Relton if (!request) 353cb3126e6SKarl Relton return -EINVAL; 354cb3126e6SKarl Relton 3555d5d7c3bSEmil Goode dev = request->wdev->netdev; 3565d5d7c3bSEmil Goode wlandev = dev->ml_priv; 3575d5d7c3bSEmil Goode 358cb3126e6SKarl Relton if (priv->scan_request && priv->scan_request != request) 359cb3126e6SKarl Relton return -EBUSY; 360cb3126e6SKarl Relton 361cb3126e6SKarl Relton if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { 362eed88971SAvinash Kumar netdev_err(dev, "Can't scan in AP mode\n"); 363cb3126e6SKarl Relton return -EOPNOTSUPP; 364cb3126e6SKarl Relton } 365cb3126e6SKarl Relton 366cb3126e6SKarl Relton priv->scan_request = request; 367cb3126e6SKarl Relton 368b6bb56e6SEdgardo Hames memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan)); 369cb3126e6SKarl Relton msg1.msgcode = DIDmsg_dot11req_scan; 370cb3126e6SKarl Relton msg1.bsstype.data = P80211ENUM_bsstype_any; 371cb3126e6SKarl Relton 372625aeb3aSDan Carpenter memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data)); 373cb3126e6SKarl Relton msg1.bssid.data.len = 6; 374cb3126e6SKarl Relton 375cb3126e6SKarl Relton if (request->n_ssids > 0) { 376cb3126e6SKarl Relton msg1.scantype.data = P80211ENUM_scantype_active; 377cb3126e6SKarl Relton msg1.ssid.data.len = request->ssids->ssid_len; 3788aac4d44SDevendra Naga memcpy(msg1.ssid.data.data, 3798aac4d44SDevendra Naga request->ssids->ssid, request->ssids->ssid_len); 380cb3126e6SKarl Relton } else { 381cb3126e6SKarl Relton msg1.scantype.data = 0; 382cb3126e6SKarl Relton } 383cb3126e6SKarl Relton msg1.probedelay.data = 0; 384cb3126e6SKarl Relton 385cb3126e6SKarl Relton for (i = 0; 386cb3126e6SKarl Relton (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels); 387cb3126e6SKarl Relton i++) 388cb3126e6SKarl Relton msg1.channellist.data.data[i] = 389bb1da756SHimangi Saraogi ieee80211_frequency_to_channel( 390bb1da756SHimangi Saraogi request->channels[i]->center_freq); 391cb3126e6SKarl Relton msg1.channellist.data.len = request->n_channels; 392cb3126e6SKarl Relton 393cb3126e6SKarl Relton msg1.maxchanneltime.data = 250; 394cb3126e6SKarl Relton msg1.minchanneltime.data = 200; 395cb3126e6SKarl Relton 396cb3126e6SKarl Relton result = p80211req_dorequest(wlandev, (u8 *) &msg1); 397cb3126e6SKarl Relton if (result) { 398cb3126e6SKarl Relton err = prism2_result2err(msg1.resultcode.data); 399cb3126e6SKarl Relton goto exit; 400cb3126e6SKarl Relton } 401cb3126e6SKarl Relton /* Now retrieve scan results */ 402cb3126e6SKarl Relton numbss = msg1.numbss.data; 403cb3126e6SKarl Relton 404cb3126e6SKarl Relton for (i = 0; i < numbss; i++) { 4054e5e9d7cSZhao, Gang int freq; 4064e5e9d7cSZhao, Gang 407cb3126e6SKarl Relton memset(&msg2, 0, sizeof(msg2)); 408cb3126e6SKarl Relton msg2.msgcode = DIDmsg_dot11req_scan_results; 409cb3126e6SKarl Relton msg2.bssindex.data = i; 410cb3126e6SKarl Relton 411cb3126e6SKarl Relton result = p80211req_dorequest(wlandev, (u8 *) &msg2); 412cb3126e6SKarl Relton if ((result != 0) || 413cb3126e6SKarl Relton (msg2.resultcode.data != P80211ENUM_resultcode_success)) { 414cb3126e6SKarl Relton break; 415cb3126e6SKarl Relton } 416cb3126e6SKarl Relton 417cb3126e6SKarl Relton ie_buf[0] = WLAN_EID_SSID; 418cb3126e6SKarl Relton ie_buf[1] = msg2.ssid.data.len; 419cb3126e6SKarl Relton ie_len = ie_buf[1] + 2; 420cb3126e6SKarl Relton memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); 4214e5e9d7cSZhao, Gang freq = ieee80211_channel_to_frequency(msg2.dschannel.data, 4224e5e9d7cSZhao, Gang IEEE80211_BAND_2GHZ); 42319f798adSKrzysztof Wilczynski bss = cfg80211_inform_bss(wiphy, 4244e5e9d7cSZhao, Gang ieee80211_get_channel(wiphy, freq), 4255bc8c1f2SJohannes Berg CFG80211_BSS_FTYPE_UNKNOWN, 426cb3126e6SKarl Relton (const u8 *) &(msg2.bssid.data.data), 427cb3126e6SKarl Relton msg2.timestamp.data, msg2.capinfo.data, 428cb3126e6SKarl Relton msg2.beaconperiod.data, 429cb3126e6SKarl Relton ie_buf, 430cb3126e6SKarl Relton ie_len, 431cb3126e6SKarl Relton (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ 432cb3126e6SKarl Relton GFP_KERNEL 433cb3126e6SKarl Relton ); 43419f798adSKrzysztof Wilczynski 43519f798adSKrzysztof Wilczynski if (!bss) { 43619f798adSKrzysztof Wilczynski err = -ENOMEM; 43719f798adSKrzysztof Wilczynski goto exit; 43819f798adSKrzysztof Wilczynski } 43919f798adSKrzysztof Wilczynski 4405b112d3dSJohannes Berg cfg80211_put_bss(wiphy, bss); 441cb3126e6SKarl Relton } 442cb3126e6SKarl Relton 4438dd82ebeSEdgardo Hames if (result) 444cb3126e6SKarl Relton err = prism2_result2err(msg2.resultcode.data); 445cb3126e6SKarl Relton 446cb3126e6SKarl Relton exit: 447cb3126e6SKarl Relton cfg80211_scan_done(request, err ? 1 : 0); 448cb3126e6SKarl Relton priv->scan_request = NULL; 449cb3126e6SKarl Relton return err; 450cb3126e6SKarl Relton } 451cb3126e6SKarl Relton 45255da06ebSTeodora Baluta static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) 4538dd82ebeSEdgardo Hames { 454cb3126e6SKarl Relton struct prism2_wiphy_private *priv = wiphy_priv(wiphy); 455cb3126e6SKarl Relton wlandevice_t *wlandev = priv->wlandev; 456cb3126e6SKarl Relton u32 data; 457cb3126e6SKarl Relton int result; 458cb3126e6SKarl Relton int err = 0; 459cb3126e6SKarl Relton 460cb3126e6SKarl Relton if (changed & WIPHY_PARAM_RTS_THRESHOLD) { 461cb3126e6SKarl Relton if (wiphy->rts_threshold == -1) 462cb3126e6SKarl Relton data = 2347; 463cb3126e6SKarl Relton else 464cb3126e6SKarl Relton data = wiphy->rts_threshold; 465cb3126e6SKarl Relton 4668dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 467cb3126e6SKarl Relton DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, 468cb3126e6SKarl Relton data); 469cb3126e6SKarl Relton if (result) { 470cb3126e6SKarl Relton err = -EFAULT; 471cb3126e6SKarl Relton goto exit; 472cb3126e6SKarl Relton } 473cb3126e6SKarl Relton } 474cb3126e6SKarl Relton 475cb3126e6SKarl Relton if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { 476cb3126e6SKarl Relton if (wiphy->frag_threshold == -1) 477cb3126e6SKarl Relton data = 2346; 478cb3126e6SKarl Relton else 479cb3126e6SKarl Relton data = wiphy->frag_threshold; 480cb3126e6SKarl Relton 4818dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 482cb3126e6SKarl Relton DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, 483cb3126e6SKarl Relton data); 484cb3126e6SKarl Relton if (result) { 485cb3126e6SKarl Relton err = -EFAULT; 486cb3126e6SKarl Relton goto exit; 487cb3126e6SKarl Relton } 488cb3126e6SKarl Relton } 489cb3126e6SKarl Relton 490cb3126e6SKarl Relton exit: 491cb3126e6SKarl Relton return err; 492cb3126e6SKarl Relton } 493cb3126e6SKarl Relton 49455da06ebSTeodora Baluta static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, 4958dd82ebeSEdgardo Hames struct cfg80211_connect_params *sme) 4968dd82ebeSEdgardo Hames { 497cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 498cb3126e6SKarl Relton struct ieee80211_channel *channel = sme->channel; 499b6bb56e6SEdgardo Hames struct p80211msg_lnxreq_autojoin msg_join; 500cb3126e6SKarl Relton u32 did; 501cb3126e6SKarl Relton int length = sme->ssid_len; 502cb3126e6SKarl Relton int chan = -1; 503cb3126e6SKarl Relton int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || 504cb3126e6SKarl Relton (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104); 505cb3126e6SKarl Relton int result; 506cb3126e6SKarl Relton int err = 0; 507cb3126e6SKarl Relton 508cb3126e6SKarl Relton /* Set the channel */ 509cb3126e6SKarl Relton if (channel) { 510cb3126e6SKarl Relton chan = ieee80211_frequency_to_channel(channel->center_freq); 5118dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 512cb3126e6SKarl Relton DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, 513cb3126e6SKarl Relton chan); 5148dd82ebeSEdgardo Hames if (result) 5158dd82ebeSEdgardo Hames goto exit; 516cb3126e6SKarl Relton } 517cb3126e6SKarl Relton 518d34602deSJustin P. Mattock /* Set the authorization */ 519cb3126e6SKarl Relton if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) || 520cb3126e6SKarl Relton ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) 521cb3126e6SKarl Relton msg_join.authtype.data = P80211ENUM_authalg_opensystem; 522cb3126e6SKarl Relton else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) || 523cb3126e6SKarl Relton ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) 524cb3126e6SKarl Relton msg_join.authtype.data = P80211ENUM_authalg_sharedkey; 5258dd82ebeSEdgardo Hames else 526eed88971SAvinash Kumar netdev_warn(dev, 5278dd82ebeSEdgardo Hames "Unhandled authorisation type for connect (%d)\n", 5288dd82ebeSEdgardo Hames sme->auth_type); 529cb3126e6SKarl Relton 530cb3126e6SKarl Relton /* Set the encryption - we only support wep */ 531cb3126e6SKarl Relton if (is_wep) { 532cb3126e6SKarl Relton if (sme->key) { 533cb3126e6SKarl Relton result = prism2_domibset_uint32(wlandev, 534cb3126e6SKarl Relton DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, 535cb3126e6SKarl Relton sme->key_idx); 5368dd82ebeSEdgardo Hames if (result) 5378dd82ebeSEdgardo Hames goto exit; 538cb3126e6SKarl Relton 539cb3126e6SKarl Relton /* send key to driver */ 540cb3126e6SKarl Relton switch (sme->key_idx) { 541cb3126e6SKarl Relton case 0: 5428dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; 543cb3126e6SKarl Relton break; 544cb3126e6SKarl Relton 545cb3126e6SKarl Relton case 1: 5468dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; 547cb3126e6SKarl Relton break; 548cb3126e6SKarl Relton 549cb3126e6SKarl Relton case 2: 5508dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; 551cb3126e6SKarl Relton break; 552cb3126e6SKarl Relton 553cb3126e6SKarl Relton case 3: 5548dd82ebeSEdgardo Hames did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; 555cb3126e6SKarl Relton break; 556cb3126e6SKarl Relton 557cb3126e6SKarl Relton default: 558cb3126e6SKarl Relton err = -EINVAL; 559cb3126e6SKarl Relton goto exit; 560cb3126e6SKarl Relton } 561cb3126e6SKarl Relton 5628aac4d44SDevendra Naga result = prism2_domibset_pstr32(wlandev, 5638aac4d44SDevendra Naga did, sme->key_len, 5648aac4d44SDevendra Naga (u8 *)sme->key); 5658dd82ebeSEdgardo Hames if (result) 5668dd82ebeSEdgardo Hames goto exit; 567cb3126e6SKarl Relton 568cb3126e6SKarl Relton } 569cb3126e6SKarl Relton 570cb3126e6SKarl Relton /* Assume we should set privacy invoked and exclude unencrypted 571cb3126e6SKarl Relton We could possibly use sme->privacy here, but the assumption 572cb3126e6SKarl Relton seems reasonable anyway */ 5738dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 5748dd82ebeSEdgardo Hames DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, 575cb3126e6SKarl Relton P80211ENUM_truth_true); 5768dd82ebeSEdgardo Hames if (result) 5778dd82ebeSEdgardo Hames goto exit; 5788dd82ebeSEdgardo Hames 5798dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 5808dd82ebeSEdgardo Hames DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, 581cb3126e6SKarl Relton P80211ENUM_truth_true); 5828dd82ebeSEdgardo Hames if (result) 5838dd82ebeSEdgardo Hames goto exit; 584cb3126e6SKarl Relton 585cb3126e6SKarl Relton } else { 5868dd82ebeSEdgardo Hames /* Assume we should unset privacy invoked 5878dd82ebeSEdgardo Hames and exclude unencrypted */ 5888dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 5898dd82ebeSEdgardo Hames DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, 590cb3126e6SKarl Relton P80211ENUM_truth_false); 5918dd82ebeSEdgardo Hames if (result) 5928dd82ebeSEdgardo Hames goto exit; 5938dd82ebeSEdgardo Hames 5948dd82ebeSEdgardo Hames result = prism2_domibset_uint32(wlandev, 5958dd82ebeSEdgardo Hames DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, 596cb3126e6SKarl Relton P80211ENUM_truth_false); 5978dd82ebeSEdgardo Hames if (result) 5988dd82ebeSEdgardo Hames goto exit; 599cb3126e6SKarl Relton 600cb3126e6SKarl Relton } 601cb3126e6SKarl Relton 602cb3126e6SKarl Relton /* Now do the actual join. Note there is no way that I can 603cb3126e6SKarl Relton see to request a specific bssid */ 604cb3126e6SKarl Relton msg_join.msgcode = DIDmsg_lnxreq_autojoin; 605cb3126e6SKarl Relton 606cb3126e6SKarl Relton memcpy(msg_join.ssid.data.data, sme->ssid, length); 607cb3126e6SKarl Relton msg_join.ssid.data.len = length; 608cb3126e6SKarl Relton 609cb3126e6SKarl Relton result = p80211req_dorequest(wlandev, (u8 *) &msg_join); 610cb3126e6SKarl Relton 611cb3126e6SKarl Relton exit: 6128dd82ebeSEdgardo Hames if (result) 6138dd82ebeSEdgardo Hames err = -EFAULT; 614cb3126e6SKarl Relton 615cb3126e6SKarl Relton return err; 616cb3126e6SKarl Relton } 617cb3126e6SKarl Relton 61855da06ebSTeodora Baluta static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, 6198dd82ebeSEdgardo Hames u16 reason_code) 6208dd82ebeSEdgardo Hames { 621cb3126e6SKarl Relton wlandevice_t *wlandev = dev->ml_priv; 622b6bb56e6SEdgardo Hames struct p80211msg_lnxreq_autojoin msg_join; 623cb3126e6SKarl Relton int result; 624cb3126e6SKarl Relton int err = 0; 625cb3126e6SKarl Relton 626cb3126e6SKarl Relton 627cb3126e6SKarl Relton /* Do a join, with a bogus ssid. Thats the only way I can think of */ 628cb3126e6SKarl Relton msg_join.msgcode = DIDmsg_lnxreq_autojoin; 629cb3126e6SKarl Relton 630cb3126e6SKarl Relton memcpy(msg_join.ssid.data.data, "---", 3); 631cb3126e6SKarl Relton msg_join.ssid.data.len = 3; 632cb3126e6SKarl Relton 633cb3126e6SKarl Relton result = p80211req_dorequest(wlandev, (u8 *) &msg_join); 634cb3126e6SKarl Relton 6358dd82ebeSEdgardo Hames if (result) 6368dd82ebeSEdgardo Hames err = -EFAULT; 637cb3126e6SKarl Relton 638cb3126e6SKarl Relton return err; 639cb3126e6SKarl Relton } 640cb3126e6SKarl Relton 641cb3126e6SKarl Relton 64255da06ebSTeodora Baluta static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev, 6438dd82ebeSEdgardo Hames struct cfg80211_ibss_params *params) 6448dd82ebeSEdgardo Hames { 645cb3126e6SKarl Relton return -EOPNOTSUPP; 646cb3126e6SKarl Relton } 647cb3126e6SKarl Relton 64855da06ebSTeodora Baluta static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) 6498dd82ebeSEdgardo Hames { 650cb3126e6SKarl Relton return -EOPNOTSUPP; 651cb3126e6SKarl Relton } 652cb3126e6SKarl Relton 653cb3126e6SKarl Relton 65455da06ebSTeodora Baluta static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, 6555f3b361aSEmil Goode enum nl80211_tx_power_setting type, int mbm) 6568dd82ebeSEdgardo Hames { 657cb3126e6SKarl Relton struct prism2_wiphy_private *priv = wiphy_priv(wiphy); 658cb3126e6SKarl Relton wlandevice_t *wlandev = priv->wlandev; 659cb3126e6SKarl Relton u32 data; 660cb3126e6SKarl Relton int result; 661cb3126e6SKarl Relton int err = 0; 662cb3126e6SKarl Relton 6639015e499SChristoph Fritz if (type == NL80211_TX_POWER_AUTOMATIC) 664cb3126e6SKarl Relton data = 30; 665cb3126e6SKarl Relton else 6669015e499SChristoph Fritz data = MBM_TO_DBM(mbm); 667cb3126e6SKarl Relton 668cb3126e6SKarl Relton result = prism2_domibset_uint32(wlandev, 669cb3126e6SKarl Relton DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, 670cb3126e6SKarl Relton data); 671cb3126e6SKarl Relton 672cb3126e6SKarl Relton if (result) { 673cb3126e6SKarl Relton err = -EFAULT; 674cb3126e6SKarl Relton goto exit; 675cb3126e6SKarl Relton } 676cb3126e6SKarl Relton 677cb3126e6SKarl Relton exit: 678cb3126e6SKarl Relton return err; 679cb3126e6SKarl Relton } 680cb3126e6SKarl Relton 68155da06ebSTeodora Baluta static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, 6825f3b361aSEmil Goode int *dbm) 6838dd82ebeSEdgardo Hames { 684cb3126e6SKarl Relton struct prism2_wiphy_private *priv = wiphy_priv(wiphy); 685cb3126e6SKarl Relton wlandevice_t *wlandev = priv->wlandev; 686b6bb56e6SEdgardo Hames struct p80211msg_dot11req_mibget msg; 6878aac4d44SDevendra Naga p80211item_uint32_t *mibitem; 688cb3126e6SKarl Relton int result; 689cb3126e6SKarl Relton int err = 0; 690cb3126e6SKarl Relton 6918aac4d44SDevendra Naga mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; 692cb3126e6SKarl Relton msg.msgcode = DIDmsg_dot11req_mibget; 693cb3126e6SKarl Relton mibitem->did = 694cb3126e6SKarl Relton DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; 695cb3126e6SKarl Relton 696cb3126e6SKarl Relton result = p80211req_dorequest(wlandev, (u8 *) &msg); 697cb3126e6SKarl Relton 698cb3126e6SKarl Relton if (result) { 699cb3126e6SKarl Relton err = -EFAULT; 700cb3126e6SKarl Relton goto exit; 701cb3126e6SKarl Relton } 702cb3126e6SKarl Relton 703cb3126e6SKarl Relton *dbm = mibitem->data; 704cb3126e6SKarl Relton 705cb3126e6SKarl Relton exit: 706cb3126e6SKarl Relton return err; 707cb3126e6SKarl Relton } 708cb3126e6SKarl Relton 709cb3126e6SKarl Relton 710cb3126e6SKarl Relton 711cb3126e6SKarl Relton 712cb3126e6SKarl Relton /* Interface callback functions, passing data back up to the cfg80211 layer */ 7138dd82ebeSEdgardo Hames void prism2_connect_result(wlandevice_t *wlandev, u8 failed) 7148dd82ebeSEdgardo Hames { 7158aac4d44SDevendra Naga u16 status = failed ? 7168aac4d44SDevendra Naga WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS; 717cb3126e6SKarl Relton 718cb3126e6SKarl Relton cfg80211_connect_result(wlandev->netdev, wlandev->bssid, 7198dd82ebeSEdgardo Hames NULL, 0, NULL, 0, status, GFP_KERNEL); 720cb3126e6SKarl Relton } 721cb3126e6SKarl Relton 7228dd82ebeSEdgardo Hames void prism2_disconnected(wlandevice_t *wlandev) 7238dd82ebeSEdgardo Hames { 724cb3126e6SKarl Relton cfg80211_disconnected(wlandev->netdev, 0, NULL, 72580279fb7SJohannes Berg 0, false, GFP_KERNEL); 726cb3126e6SKarl Relton } 727cb3126e6SKarl Relton 7288dd82ebeSEdgardo Hames void prism2_roamed(wlandevice_t *wlandev) 7298dd82ebeSEdgardo Hames { 730ed9d0102SJouni Malinen cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid, 731cb3126e6SKarl Relton NULL, 0, NULL, 0, GFP_KERNEL); 732cb3126e6SKarl Relton } 733cb3126e6SKarl Relton 734cb3126e6SKarl Relton 735cb3126e6SKarl Relton /* Structures for declaring wiphy interface */ 736cb3126e6SKarl Relton static const struct cfg80211_ops prism2_usb_cfg_ops = { 737cb3126e6SKarl Relton .change_virtual_intf = prism2_change_virtual_intf, 738cb3126e6SKarl Relton .add_key = prism2_add_key, 739cb3126e6SKarl Relton .get_key = prism2_get_key, 740cb3126e6SKarl Relton .del_key = prism2_del_key, 741cb3126e6SKarl Relton .set_default_key = prism2_set_default_key, 742cb3126e6SKarl Relton .get_station = prism2_get_station, 743cb3126e6SKarl Relton .scan = prism2_scan, 744cb3126e6SKarl Relton .set_wiphy_params = prism2_set_wiphy_params, 745cb3126e6SKarl Relton .connect = prism2_connect, 746cb3126e6SKarl Relton .disconnect = prism2_disconnect, 747cb3126e6SKarl Relton .join_ibss = prism2_join_ibss, 748cb3126e6SKarl Relton .leave_ibss = prism2_leave_ibss, 749cb3126e6SKarl Relton .set_tx_power = prism2_set_tx_power, 750cb3126e6SKarl Relton .get_tx_power = prism2_get_tx_power, 751cb3126e6SKarl Relton }; 752cb3126e6SKarl Relton 753cb3126e6SKarl Relton 754cb3126e6SKarl Relton /* Functions to create/free wiphy interface */ 75536d9c250STugce Sirin static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) 756cb3126e6SKarl Relton { 757cb3126e6SKarl Relton struct wiphy *wiphy; 758cb3126e6SKarl Relton struct prism2_wiphy_private *priv; 7598aac4d44SDevendra Naga 7608aac4d44SDevendra Naga wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv)); 761cb3126e6SKarl Relton if (!wiphy) 762cb3126e6SKarl Relton return NULL; 763cb3126e6SKarl Relton 764cb3126e6SKarl Relton priv = wiphy_priv(wiphy); 765cb3126e6SKarl Relton priv->wlandev = wlandev; 766cb3126e6SKarl Relton memcpy(priv->channels, prism2_channels, sizeof(prism2_channels)); 767cb3126e6SKarl Relton memcpy(priv->rates, prism2_rates, sizeof(prism2_rates)); 768cb3126e6SKarl Relton priv->band.channels = priv->channels; 769cb3126e6SKarl Relton priv->band.n_channels = ARRAY_SIZE(prism2_channels); 770cb3126e6SKarl Relton priv->band.bitrates = priv->rates; 771cb3126e6SKarl Relton priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); 772aff3ea4eSKarl Relton priv->band.band = IEEE80211_BAND_2GHZ; 773aff3ea4eSKarl Relton priv->band.ht_cap.ht_supported = false; 774cb3126e6SKarl Relton wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; 775cb3126e6SKarl Relton 776cb3126e6SKarl Relton set_wiphy_dev(wiphy, dev); 777cb3126e6SKarl Relton wiphy->privid = prism2_wiphy_privid; 778cb3126e6SKarl Relton wiphy->max_scan_ssids = 1; 7798dd82ebeSEdgardo Hames wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) 7808dd82ebeSEdgardo Hames | BIT(NL80211_IFTYPE_ADHOC); 781cb3126e6SKarl Relton wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 782cb3126e6SKarl Relton wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES; 783cb3126e6SKarl Relton wiphy->cipher_suites = prism2_cipher_suites; 784cb3126e6SKarl Relton 785cb3126e6SKarl Relton if (wiphy_register(wiphy) < 0) 786cb3126e6SKarl Relton return NULL; 787cb3126e6SKarl Relton 788cb3126e6SKarl Relton return wiphy; 789cb3126e6SKarl Relton } 790cb3126e6SKarl Relton 791cb3126e6SKarl Relton 79236d9c250STugce Sirin static void wlan_free_wiphy(struct wiphy *wiphy) 793cb3126e6SKarl Relton { 794cb3126e6SKarl Relton wiphy_unregister(wiphy); 795cb3126e6SKarl Relton wiphy_free(wiphy); 796cb3126e6SKarl Relton } 797