diff options
author | Karl Relton <karllinuxtest.relton@ntlworld.com> | 2010-06-03 23:04:06 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-06-18 15:22:55 -0700 |
commit | cb3126e60ffc1b7658a6ff4f6874585098bf9887 (patch) | |
tree | 41d38b199cf0c48607d379b36289c6799856bab2 /drivers/staging/wlan-ng | |
parent | 9c770f3b881c5066ff014968473ffbbafee82247 (diff) |
Staging: wlan-ng: Switch from wext to cfg80211
Switch driver over from wext to cfg80211 interface.
Some Notes:
- This patch moves the driver wholesale from wext to cfg80211. Wext
support is still provided through the cfg80211 provided wext
compatability layer.
- Currently only infrastructure mode is implemented. Ad hoc mode is not
yet implemented, but can be added.
- It does not support connecting to a specified bssid, instead roaming
is handled by the card itself. This matches the behaviour of the
existing driver.
- It has been tested using NetworkManager (via wpa_supplicant)
configured to use the wext compatability layer, and then again with the
native nl80211 layer.
Signed-off-by: Karl Relton <karllinuxtest.relton@ntlworld.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/wlan-ng')
-rw-r--r-- | drivers/staging/wlan-ng/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/cfg80211.c | 735 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/hfa384x.h | 2 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211metastruct.h | 2 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211netdev.c | 49 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211netdev.h | 3 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211wext.c | 1690 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/prism2mgmt.c | 2 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/prism2sta.c | 64 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/prism2usb.c | 2 |
10 files changed, 825 insertions, 1725 deletions
diff --git a/drivers/staging/wlan-ng/Makefile b/drivers/staging/wlan-ng/Makefile index 5edac5c8d4ee..db5d597563f8 100644 --- a/drivers/staging/wlan-ng/Makefile +++ b/drivers/staging/wlan-ng/Makefile @@ -4,5 +4,4 @@ prism2_usb-objs := prism2usb.o \ p80211conv.o \ p80211req.o \ p80211wep.o \ - p80211wext.o \ p80211netdev.o diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c new file mode 100644 index 000000000000..b0792f78ac96 --- /dev/null +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -0,0 +1,735 @@ +/* cfg80211 Interface for prism2_usb module */ + + +/* Prism2 channell/frequency/bitrate declarations */ +static const struct ieee80211_channel prism2_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + +static const struct ieee80211_rate prism2_rates[] = { + { .bitrate = 10 }, + { .bitrate = 20 }, + { .bitrate = 55 }, + { .bitrate = 110 } +}; + +#define PRISM2_NUM_CIPHER_SUITES 2 +static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104 +}; + + +/* prism2 device private data */ +struct prism2_wiphy_private { + wlandevice_t *wlandev; + + struct ieee80211_supported_band band; + struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)]; + struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)]; + + struct cfg80211_scan_request *scan_request; +}; + +static const void * const prism2_wiphy_privid = &prism2_wiphy_privid; + + +/* Helper Functions */ +static int prism2_result2err(int prism2_result) +{ + int err = 0; + + switch (prism2_result) { + case P80211ENUM_resultcode_invalid_parameters: + err = -EINVAL; + break; + case P80211ENUM_resultcode_implementation_failure: + err = -EIO; + break; + case P80211ENUM_resultcode_not_supported: + err = -EOPNOTSUPP; + break; + default: + err = 0; + break; + } + + return err; +} + +static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) +{ + p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem->did = did; + mibitem->data = data; + + return p80211req_dorequest(wlandev, (u8 *) & msg); +} + +static int prism2_domibset_pstr32(wlandevice_t *wlandev, + u32 did, u8 len, u8 *data) +{ + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t *mibitem = (p80211item_pstr32_t *) &msg.mibattribute.data; + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem->did = did; + mibitem->data.len = len; + memcpy(mibitem->data.data, data, len); + + return p80211req_dorequest(wlandev, (u8 *) & msg); +} + + +/* The interface functions, called by the cfg80211 layer */ +int prism2_change_virtual_intf(struct wiphy *wiphy, + struct net_device *dev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + wlandevice_t *wlandev = dev->ml_priv; + u32 data; + int result; + int err = 0; + + switch (type) { + case NL80211_IFTYPE_ADHOC: + if (wlandev->macmode == WLAN_MACMODE_IBSS_STA) goto exit; + wlandev->macmode = WLAN_MACMODE_IBSS_STA; + data = 0; + break; + case NL80211_IFTYPE_STATION: + if (wlandev->macmode == WLAN_MACMODE_ESS_STA) goto exit; + wlandev->macmode = WLAN_MACMODE_ESS_STA; + data = 1; + break; + default: + printk(KERN_WARNING "Operation mode: %d not support\n", type); + return -EOPNOTSUPP; + } + + /* Set Operation mode to the PORT TYPE RID */ + result = prism2_domibset_uint32(wlandev, DIDmib_p2_p2Static_p2CnfPortType, data); + + if (result) + err = -EFAULT; + + dev->ieee80211_ptr->iftype = type; + +exit: + return err; +} + +int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, const u8 *mac_addr, + struct key_params *params) { + wlandevice_t *wlandev = dev->ml_priv; + u32 did; + + int err = 0; + int result = 0; + + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + key_index); + if (result) goto exit; + + /* send key to driver */ + switch (key_index) { + case 0: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key); + if (result) goto exit; + break; + + default: + pr_debug("Unsupported cipher suite\n"); + result = 1; + } + +exit: + if (result) err = -EFAULT; + + return err; +} + +int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params*)) { + wlandevice_t *wlandev = dev->ml_priv; + struct key_params params; + int len; + + if(key_index >= NUM_WEPKEYS) return -EINVAL; + + len = wlandev->wep_keylens[key_index]; + memset(¶ms, 0, sizeof(params)); + + if (len == 13) { + params.cipher = WLAN_CIPHER_SUITE_WEP104; + } else if (len == 5) { + params.cipher = WLAN_CIPHER_SUITE_WEP104; + } else return -ENOENT; + params.key_len = len; + params.key = wlandev->wep_keys[key_index]; + + callback(cookie, ¶ms); + return 0; +} + +int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, const u8 *mac_addr) { + wlandevice_t *wlandev = dev->ml_priv; + u32 did; + int err = 0; + int result = 0; + + /* There is no direct way in the hardware (AFAIK) of removing + a key, so we will cheat by setting the key to a bogus value */ + /* send key to driver */ + switch (key_index) { + case 0: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000"); + +exit: + if (result) err = -EFAULT; + + return err; +} + +int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index) { + wlandevice_t *wlandev = dev->ml_priv; + + int err = 0; + int result = 0; + + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + key_index); + + if (result) err = -EFAULT; + + return err; +} + + +int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) { + wlandevice_t *wlandev = dev->ml_priv; + p80211msg_lnxreq_commsquality_t quality; + int result; + + memset(sinfo, 0, sizeof(*sinfo)); + + if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) + return -EOPNOTSUPP; + + /* build request message */ + quality.msgcode = DIDmsg_lnxreq_commsquality; + quality.dbm.data = P80211ENUM_truth_true; + quality.dbm.status = P80211ENUM_msgitem_status_data_ok; + + /* send message to nsd */ + if (wlandev->mlmerequest == NULL) + return -EOPNOTSUPP; + + result = wlandev->mlmerequest(wlandev, (p80211msg_t *) & quality); + + + if (result == 0) { + sinfo->txrate.legacy = quality.txrate.data; + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->signal = quality.level.data; + sinfo->filled |= STATION_INFO_SIGNAL; + } + + return result; +} + +int prism2_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) +{ + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = dev->ml_priv; + p80211msg_dot11req_scan_t msg1; + p80211msg_dot11req_scan_results_t msg2; + int result; + int err = 0; + int numbss = 0; + int i = 0; + u8 ie_buf[46]; + int ie_len; + + if (!request) + return -EINVAL; + + if (priv->scan_request && priv->scan_request != request) + return -EBUSY; + + if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { + printk(KERN_ERR "Can't scan in AP mode\n"); + return -EOPNOTSUPP; + } + + priv->scan_request = request; + + memset(&msg1, 0x00, sizeof(p80211msg_dot11req_scan_t)); + msg1.msgcode = DIDmsg_dot11req_scan; + msg1.bsstype.data = P80211ENUM_bsstype_any; + + memset(&(msg1.bssid.data), 0xFF, sizeof(p80211item_pstr6_t)); + msg1.bssid.data.len = 6; + + if (request->n_ssids > 0) { + msg1.scantype.data = P80211ENUM_scantype_active; + msg1.ssid.data.len = request->ssids->ssid_len; + memcpy(msg1.ssid.data.data, request->ssids->ssid, request->ssids->ssid_len); + } else { + msg1.scantype.data = 0; + } + msg1.probedelay.data = 0; + + for (i = 0; + (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels); + i++) + msg1.channellist.data.data[i] = + ieee80211_frequency_to_channel(request->channels[i]->center_freq); + msg1.channellist.data.len = request->n_channels; + + msg1.maxchanneltime.data = 250; + msg1.minchanneltime.data = 200; + + result = p80211req_dorequest(wlandev, (u8 *) &msg1); + if (result) { + err = prism2_result2err(msg1.resultcode.data); + goto exit; + } + /* Now retrieve scan results */ + numbss = msg1.numbss.data; + + for (i = 0; i < numbss; i++) { + memset(&msg2, 0, sizeof(msg2)); + msg2.msgcode = DIDmsg_dot11req_scan_results; + msg2.bssindex.data = i; + + result = p80211req_dorequest(wlandev, (u8 *) &msg2); + if ((result != 0) || + (msg2.resultcode.data != P80211ENUM_resultcode_success)) { + break; + } + + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = msg2.ssid.data.len; + ie_len = ie_buf[1] + 2; + memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); + cfg80211_inform_bss(wiphy, + ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)), + (const u8 *) &(msg2.bssid.data.data), + msg2.timestamp.data, msg2.capinfo.data, + msg2.beaconperiod.data, + ie_buf, + ie_len, + (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ + GFP_KERNEL + ); + } + + if (result) { + err = prism2_result2err(msg2.resultcode.data); + } + +exit: + cfg80211_scan_done(request, err ? 1 : 0); + priv->scan_request = NULL; + return err; +} + +int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) { + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = priv->wlandev; + u32 data; + int result; + int err = 0; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + if (wiphy->rts_threshold == -1) + data = 2347; + else + data = wiphy->rts_threshold; + + result = + prism2_domibset_uint32(wlandev, + DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + data); + if (result) { + err = -EFAULT; + goto exit; + } + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + + if (wiphy->frag_threshold == -1) + data = 2346; + else + data = wiphy->frag_threshold; + + result = + prism2_domibset_uint32(wlandev, + DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + data); + if (result) { + err = -EFAULT; + goto exit; + } + } + +exit: + return err; +} + +int prism2_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) { + wlandevice_t *wlandev = dev->ml_priv; + struct ieee80211_channel *channel = sme->channel; + p80211msg_lnxreq_autojoin_t msg_join; + u32 did; + int length = sme->ssid_len; + int chan = -1; + int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || + (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104); + int result; + int err = 0; + + /* Set the channel */ + if (channel) { + chan = ieee80211_frequency_to_channel(channel->center_freq); + + result = + prism2_domibset_uint32(wlandev, + DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + chan); + + if (result) goto exit; + } + + /* Set the authorisation */ + if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) || + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_opensystem; + else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) || + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_sharedkey; + else printk(KERN_WARNING "Unhandled authorisation type for connect (%d)\n", sme->auth_type); + + /* Set the encryption - we only support wep */ + if (is_wep) { + + if (sme->key) { + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + sme->key_idx); + if (result) goto exit; + + /* send key to driver */ + switch (sme->key_idx) { + case 0: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + result = prism2_domibset_pstr32(wlandev, did, sme->key_len, (u8 *) sme->key); + if (result) goto exit; + + } + + /* Assume we should set privacy invoked and exclude unencrypted + We could possibly use sme->privacy here, but the assumption + seems reasonable anyway */ + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_true); + if (result) goto exit; + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_true); + if (result) goto exit; + + } else { + /* Assume we should unset privacy invoked and exclude unencrypted */ + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_false); + if (result) goto exit; + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_false); + if (result) goto exit; + + } + + /* Now do the actual join. Note there is no way that I can + see to request a specific bssid */ + msg_join.msgcode = DIDmsg_lnxreq_autojoin; + + memcpy(msg_join.ssid.data.data, sme->ssid, length); + msg_join.ssid.data.len = length; + + result = p80211req_dorequest(wlandev, (u8 *) & msg_join); + +exit: + if (result) err = -EFAULT; + + return err; +} + +int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) { + wlandevice_t *wlandev = dev->ml_priv; + p80211msg_lnxreq_autojoin_t msg_join; + int result; + int err = 0; + + + /* Do a join, with a bogus ssid. Thats the only way I can think of */ + msg_join.msgcode = DIDmsg_lnxreq_autojoin; + + memcpy(msg_join.ssid.data.data, "---", 3); + msg_join.ssid.data.len = 3; + + result = p80211req_dorequest(wlandev, (u8 *) & msg_join); + + if (result) err = -EFAULT; + + return err; +} + + +int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) { + return -EOPNOTSUPP; +} + +int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { + return -EOPNOTSUPP; +} + + +int prism2_set_tx_power(struct wiphy *wiphy, + enum tx_power_setting type, int dbm) { + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = priv->wlandev; + u32 data; + int result; + int err = 0; + + if (type == TX_POWER_AUTOMATIC) + data = 30; + else + data = dbm; + + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, + data); + + if (result) { + err = -EFAULT; + goto exit; + } + +exit: + return err; +} + +int prism2_get_tx_power(struct wiphy *wiphy, int *dbm) { + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = priv->wlandev; + p80211msg_dot11req_mibget_t msg; + p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + int result; + int err = 0; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem->did = + DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; + + result = p80211req_dorequest(wlandev, (u8 *) & msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + *dbm = mibitem->data; + +exit: + return err; +} + + + + +/* Interface callback functions, passing data back up to the cfg80211 layer */ +void prism2_connect_result(wlandevice_t *wlandev, u8 failed) { + + cfg80211_connect_result(wlandev->netdev, wlandev->bssid, + NULL, 0, NULL, 0, + failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS, GFP_KERNEL); +} + +void prism2_disconnected(wlandevice_t *wlandev) { + + cfg80211_disconnected(wlandev->netdev, 0, NULL, + 0, GFP_KERNEL); +} + +void prism2_roamed(wlandevice_t *wlandev) { + + cfg80211_roamed(wlandev->netdev, wlandev->bssid, + NULL, 0, NULL, 0, GFP_KERNEL); +} + + +/* Structures for declaring wiphy interface */ +static const struct cfg80211_ops prism2_usb_cfg_ops = { + .change_virtual_intf = prism2_change_virtual_intf, + .add_key = prism2_add_key, + .get_key = prism2_get_key, + .del_key = prism2_del_key, + .set_default_key = prism2_set_default_key, + .get_station = prism2_get_station, + .scan = prism2_scan, + .set_wiphy_params = prism2_set_wiphy_params, + .connect = prism2_connect, + .disconnect = prism2_disconnect, + .join_ibss = prism2_join_ibss, + .leave_ibss = prism2_leave_ibss, + .set_tx_power = prism2_set_tx_power, + .get_tx_power = prism2_get_tx_power, +}; + + +/* Functions to create/free wiphy interface */ +struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) +{ + struct wiphy *wiphy; + struct prism2_wiphy_private *priv; + wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(struct prism2_wiphy_private)); + if (!wiphy) + return NULL; + + priv = wiphy_priv(wiphy); + priv->wlandev = wlandev; + memcpy(priv->channels, prism2_channels, sizeof(prism2_channels)); + memcpy(priv->rates, prism2_rates, sizeof(prism2_rates)); + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(prism2_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); + wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + set_wiphy_dev(wiphy, dev); + wiphy->privid = prism2_wiphy_privid; + wiphy->max_scan_ssids = 1; + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES; + wiphy->cipher_suites = prism2_cipher_suites; + + if (wiphy_register(wiphy) < 0) + return NULL; + + return wiphy; +} + + +void wlan_free_wiphy(struct wiphy *wiphy) +{ + wiphy_unregister(wiphy); + wiphy_free(wiphy); +} diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1fa42e01e8cb..ab9bfaab8b6b 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1284,6 +1284,8 @@ typedef struct hfa384x { u16 link_status_new; struct sk_buff_head authq; + u32 txrate; + /* And here we have stuff that used to be in priv */ /* State variables */ diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index db12713eeaa9..e2e344c4ed82 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -113,6 +113,7 @@ typedef struct p80211msg_dot11req_scan_results { p80211item_uint32_t cfpollable; p80211item_uint32_t cfpollreq; p80211item_uint32_t privacy; + p80211item_uint32_t capinfo; p80211item_uint32_t basicrate1; p80211item_uint32_t basicrate2; p80211item_uint32_t basicrate3; @@ -209,6 +210,7 @@ typedef struct p80211msg_lnxreq_commsquality { p80211item_uint32_t link; p80211item_uint32_t level; p80211item_uint32_t noise; + p80211item_uint32_t txrate; } __attribute__ ((packed)) p80211msg_lnxreq_commsquality_t; typedef struct p80211msg_lnxreq_autojoin { diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 763ab1187a1c..31308b434344 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -75,6 +75,7 @@ #include <net/iw_handler.h> #include <net/net_namespace.h> +#include <net/cfg80211.h> #include "p80211types.h" #include "p80211hdr.h" @@ -87,6 +88,8 @@ #include "p80211metastruct.h" #include "p80211metadef.h" +#include "cfg80211.c" + /* Support functions */ static void p80211netdev_rx_bh(unsigned long arg); @@ -732,6 +735,7 @@ static const struct net_device_ops p80211_netdev_ops = { * Arguments: * wlandev ptr to the wlandev structure for the * interface. +* physdev ptr to usb device * Returns: * zero on success, non-zero otherwise. * Call Context: @@ -740,10 +744,12 @@ static const struct net_device_ops p80211_netdev_ops = { * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -int wlan_setup(wlandevice_t *wlandev) +int wlan_setup(wlandevice_t *wlandev, struct device *physdev) { int result = 0; - netdevice_t *dev; + netdevice_t *netdev; + struct wiphy *wiphy; + struct wireless_dev *wdev; /* Set up the wlandev */ wlandev->state = WLAN_DEVICE_CLOSED; @@ -755,20 +761,30 @@ int wlan_setup(wlandevice_t *wlandev) tasklet_init(&wlandev->rx_bh, p80211netdev_rx_bh, (unsigned long)wlandev); + /* Allocate and initialize the wiphy struct */ + wiphy = wlan_create_wiphy(physdev, wlandev); + if (wiphy == NULL) { + printk(KERN_ERR "Failed to alloc wiphy.\n"); + return 1; + } + /* Allocate and initialize the struct device */ - dev = alloc_netdev(0, "wlan%d", ether_setup); - if (dev == NULL) { + netdev = alloc_netdev(sizeof(struct wireless_dev), "wlan%d", ether_setup); + if (netdev == NULL) { printk(KERN_ERR "Failed to alloc netdev.\n"); + wlan_free_wiphy(wiphy); result = 1; } else { - wlandev->netdev = dev; - dev->ml_priv = wlandev; - dev->netdev_ops = &p80211_netdev_ops; - - dev->wireless_handlers = &p80211wext_handler_def; - - netif_stop_queue(dev); - netif_carrier_off(dev); + wlandev->netdev = netdev; + netdev->ml_priv = wlandev; + netdev->netdev_ops = &p80211_netdev_ops; + wdev = netdev_priv(netdev); + wdev->wiphy = wiphy; + wdev->iftype = NL80211_IFTYPE_STATION; + netdev->ieee80211_ptr = wdev; + + netif_stop_queue(netdev); + netif_carrier_off(netdev); } return result; @@ -797,14 +813,13 @@ int wlan_setup(wlandevice_t *wlandev) ----------------------------------------------------------------*/ int wlan_unsetup(wlandevice_t *wlandev) { - int result = 0; + struct wireless_dev *wdev; tasklet_kill(&wlandev->rx_bh); - if (wlandev->netdev == NULL) { - printk(KERN_ERR "called without wlandev->netdev set.\n"); - result = 1; - } else { + if (wlandev->netdev) { + wdev = netdev_priv(wlandev->netdev); + if(wdev->wiphy) wlan_free_wiphy(wdev->wiphy); free_netdev(wlandev->netdev); wlandev->netdev = NULL; } diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 3c8c64800567..098ccf71e035 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -148,6 +148,7 @@ int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); #define MAX_KEYLEN 32 #define HOSTWEP_DEFAULTKEY_MASK (BIT(1)|BIT(0)) +#define HOSTWEP_SHAREDKEY BIT(3) #define HOSTWEP_DECRYPT BIT(4) #define HOSTWEP_ENCRYPT BIT(5) #define HOSTWEP_PRIVACYINVOKED BIT(6) @@ -233,7 +234,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv); -int wlan_setup(wlandevice_t *wlandev); +int wlan_setup(wlandevice_t *wlandev, struct device *physdev); int wlan_unsetup(wlandevice_t *wlandev); int register_wlandev(wlandevice_t *wlandev); int unregister_wlandev(wlandevice_t *wlandev); diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c deleted file mode 100644 index 387194d4a6eb..000000000000 --- a/drivers/staging/wlan-ng/p80211wext.c +++ /dev/null @@ -1,1690 +0,0 @@ -/* src/p80211/p80211wext.c -* -* Glue code to make linux-wlan-ng a happy wireless extension camper. -* -* original author: Reyk Floeter <reyk@synack.de> -* Completely re-written by Solomon Peachy <solomon@linux-wlan.com> -* -* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -*/ - -/*================================================================*/ -/* System Includes */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/wireless.h> -#include <net/iw_handler.h> -#include <linux/if_arp.h> -#include <linux/bitops.h> -#include <linux/uaccess.h> -#include <asm/byteorder.h> -#include <linux/if_ether.h> - -#include "p80211types.h" -#include "p80211hdr.h" -#include "p80211conv.h" -#include "p80211mgmt.h" -#include "p80211msg.h" -#include "p80211metastruct.h" -#include "p80211metadef.h" -#include "p80211netdev.h" -#include "p80211ioctl.h" -#include "p80211req.h" - -static int p80211wext_giwrate(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra); -static int p80211wext_giwessid(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid); - -static u8 p80211_mhz_to_channel(u16 mhz) -{ - if (mhz >= 5000) - return (mhz - 5000) / 5; - - if (mhz == 2484) - return 14; - - if (mhz >= 2407) - return (mhz - 2407) / 5; - - return 0; -} - -static u16 p80211_channel_to_mhz(u8 ch, int dot11a) -{ - - if (ch == 0) - return 0; - if (ch > 200) - return 0; - - /* 5G */ - if (dot11a) - return 5000 + (5 * ch); - - /* 2.4G */ - if (ch == 14) - return 2484; - - if ((ch < 14) && (ch > 0)) - return 2407 + (5 * ch); - - return 0; -} - -/* taken from orinoco.c ;-) */ -static const long p80211wext_channel_freq[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; - -#define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq) - -/* steal a spare bit to store the shared/opensystems state. - should default to open if not set */ -#define HOSTWEP_SHAREDKEY BIT(3) - -static int qual_as_percent(int snr) -{ - if (snr <= 0) - return 0; - if (snr <= 40) - return snr * 5 / 2; - return 100; -} - -static int p80211wext_setmib(wlandevice_t *wlandev, u32 did, u32 data) -{ - p80211msg_dot11req_mibset_t msg; - p80211item_uint32_t *mibitem = - (p80211item_uint32_t *)&msg.mibattribute.data; - int result; - - msg.msgcode = DIDmsg_dot11req_mibset; - memset(mibitem, 0, sizeof(*mibitem)); - mibitem->did = did; - mibitem->data = data; - result = p80211req_dorequest(wlandev, (u8 *) &msg); - - return result; -} - -/* - * get a 32 bit mib value - */ -static int p80211wext_getmib(wlandevice_t *wlandev, u32 did, u32 *data) -{ - p80211msg_dot11req_mibset_t msg; - p80211item_uint32_t *mibitem = - (p80211item_uint32_t *)&msg.mibattribute.data; - int result; - - msg.msgcode = DIDmsg_dot11req_mibget; - memset(mibitem, 0, sizeof(*mibitem)); - mibitem->did = did; |