Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Karl Relton | 2868 | 87.98% | 2 | 3.39% |
Claudiu Beznea | 48 | 1.47% | 2 | 3.39% |
sayli karnik | 38 | 1.17% | 1 | 1.69% |
Avraham Stern | 33 | 1.01% | 2 | 3.39% |
Chris Opperman | 30 | 0.92% | 1 | 1.69% |
Emil Goode | 29 | 0.89% | 3 | 5.08% |
Edgardo Hames | 28 | 0.86% | 3 | 5.08% |
Krzysztof Wilczynski | 27 | 0.83% | 1 | 1.69% |
Tim Collier | 24 | 0.74% | 15 | 25.42% |
Johannes Berg | 17 | 0.52% | 7 | 11.86% |
Zhao, Gang | 16 | 0.49% | 1 | 1.69% |
Teodora Baluta | 14 | 0.43% | 1 | 1.69% |
Sergio Paracuellos | 13 | 0.40% | 3 | 5.08% |
Devendra Naga | 13 | 0.40% | 1 | 1.69% |
Avinash Kumar | 9 | 0.28% | 1 | 1.69% |
Ben Hutchings | 9 | 0.28% | 1 | 1.69% |
Dan Carpenter | 9 | 0.28% | 2 | 3.39% |
Christoph Fritz | 7 | 0.21% | 1 | 1.69% |
Tair Rzayev | 6 | 0.18% | 1 | 1.69% |
Harry Wei | 6 | 0.18% | 1 | 1.69% |
Gavin O'Leary | 4 | 0.12% | 2 | 3.39% |
Sandhya Bankar | 2 | 0.06% | 1 | 1.69% |
Omer Efrat | 2 | 0.06% | 1 | 1.69% |
Colin Ian King | 2 | 0.06% | 1 | 1.69% |
Tugce Sirin | 2 | 0.06% | 1 | 1.69% |
Justin P. Mattock | 2 | 0.06% | 1 | 1.69% |
Greg Kroah-Hartman | 1 | 0.03% | 1 | 1.69% |
Hariprasad Kelam | 1 | 0.03% | 1 | 1.69% |
Total | 3260 | 59 |
// SPDX-License-Identifier: GPL-2.0 /* cfg80211 Interface for prism2_usb module */ #include "hfa384x.h" #include "prism2mgmt.h" /* Prism2 channel/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 { struct wlandevice *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(struct wlandevice *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *)&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(struct wlandevice *wlandev, u32 did, u8 len, const u8 *data) { struct p80211msg_dot11req_mibset msg; struct p80211item_pstr32 *mibitem = (struct p80211item_pstr32 *)&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 */ static int prism2_change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, enum nl80211_iftype type, struct vif_params *params) { struct wlandevice *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: netdev_warn(dev, "Operation mode: %d not support\n", type); return -EOPNOTSUPP; } /* Set Operation mode to the PORT TYPE RID */ result = prism2_domibset_uint32(wlandev, DIDMIB_P2_STATIC_CNFPORTTYPE, data); if (result) err = -EFAULT; dev->ieee80211_ptr->iftype = type; exit: return err; } static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { struct wlandevice *wlandev = dev->ml_priv; u32 did; if (key_index >= NUM_WEPKEYS) return -EINVAL; if (params->cipher != WLAN_CIPHER_SUITE_WEP40 && params->cipher != WLAN_CIPHER_SUITE_WEP104) { pr_debug("Unsupported cipher suite\n"); return -EFAULT; } if (prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID, key_index)) return -EFAULT; /* send key to driver */ did = didmib_dot11smt_wepdefaultkeystable_key(key_index + 1); if (prism2_domibset_pstr32(wlandev, did, params->key_len, params->key)) return -EFAULT; return 0; } static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*)) { struct wlandevice *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]; params.seq_len = 0; callback(cookie, ¶ms); return 0; } static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr) { struct wlandevice *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 */ if (key_index >= NUM_WEPKEYS) return -EINVAL; /* send key to driver */ did = didmib_dot11smt_wepdefaultkeystable_key(key_index + 1); result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000"); if (result) err = -EFAULT; return err; } static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool unicast, bool multicast) { struct wlandevice *wlandev = dev->ml_priv; return prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID, key_index); } static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_info *sinfo) { struct wlandevice *wlandev = dev->ml_priv; struct p80211msg_lnxreq_commsquality quality; int result; memset(sinfo, 0, sizeof(*sinfo)); if (!wlandev || (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) return -EOPNOTSUPP; result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality); if (result == 0) { sinfo->txrate.legacy = quality.txrate.data; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); sinfo->signal = quality.level.data; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); } return result; } static int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); struct wlandevice *wlandev; struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan_results msg2; struct cfg80211_bss *bss; struct cfg80211_scan_info info = {}; int result; int err = 0; int numbss = 0; int i = 0; u8 ie_buf[46]; int ie_len; if (!request) return -EINVAL; dev = request->wdev->netdev; wlandev = dev->ml_priv; if (priv->scan_request && priv->scan_request != request) return -EBUSY; if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { netdev_err(dev, "Can't scan in AP mode\n"); return -EOPNOTSUPP; } priv->scan_request = request; memset(&msg1, 0x00, sizeof(msg1)); msg1.msgcode = DIDMSG_DOT11REQ_SCAN; msg1.bsstype.data = P80211ENUM_bsstype_any; memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data)); 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++) { int freq; 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); freq = ieee80211_channel_to_frequency(msg2.dschannel.data, NL80211_BAND_2GHZ); bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, (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 (!bss) { err = -ENOMEM; goto exit; } cfg80211_put_bss(wiphy, bss); } if (result) err = prism2_result2err(msg2.resultcode.data); exit: info.aborted = !!(err); cfg80211_scan_done(request, &info); priv->scan_request = NULL; return err; } static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); struct wlandevice *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_OPERATIONTABLE_RTSTHRESHOLD, 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_OPERATIONTABLE_FRAGMENTATIONTHRESHOLD, data); if (result) { err = -EFAULT; goto exit; } } exit: return err; } static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct wlandevice *wlandev = dev->ml_priv; struct ieee80211_channel *channel = sme->channel; struct p80211msg_lnxreq_autojoin 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_DSSSTABLE_CURRENTCHANNEL, chan); if (result) goto exit; } /* Set the authorization */ 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 netdev_warn(dev, "Unhandled authorisation type for connect (%d)\n", sme->auth_type); /* Set the encryption - we only support wep */ if (is_wep) { if (sme->key) { if (sme->key_idx >= NUM_WEPKEYS) return -EINVAL; result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID, sme->key_idx); if (result) goto exit; /* send key to driver */ did = didmib_dot11smt_wepdefaultkeystable_key( sme->key_idx + 1); 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 possible use sme->privacy here, but the assumption * seems reasonable anyways */ result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED, P80211ENUM_truth_true); if (result) goto exit; result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED, P80211ENUM_truth_true); if (result) goto exit; } else { /* Assume we should unset privacy invoked * and exclude unencrypted */ result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED, P80211ENUM_truth_false); if (result) goto exit; result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED, 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; } static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) { struct wlandevice *wlandev = dev->ml_priv; struct p80211msg_lnxreq_autojoin 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; } static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) { return -EOPNOTSUPP; } static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { return -EOPNOTSUPP; } static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); struct wlandevice *wlandev = priv->wlandev; u32 data; int result; int err = 0; if (type == NL80211_TX_POWER_AUTOMATIC) data = 30; else data = MBM_TO_DBM(mbm); result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL, data); if (result) { err = -EFAULT; goto exit; } exit: return err; } static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); struct wlandevice *wlandev = priv->wlandev; struct p80211msg_dot11req_mibget msg; struct p80211item_uint32 *mibitem; int result; int err = 0; mibitem = (struct p80211item_uint32 *)&msg.mibattribute.data; msg.msgcode = DIDMSG_DOT11REQ_MIBGET; mibitem->did = DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL; 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(struct wlandevice *wlandev, u8 failed) { u16 status = failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS; cfg80211_connect_result(wlandev->netdev, wlandev->bssid, NULL, 0, NULL, 0, status, GFP_KERNEL); } void prism2_disconnected(struct wlandevice *wlandev) { cfg80211_disconnected(wlandev->netdev, 0, NULL, 0, false, GFP_KERNEL); } void prism2_roamed(struct wlandevice *wlandev) { struct cfg80211_roam_info roam_info = { .bssid = wlandev->bssid, }; cfg80211_roamed(wlandev->netdev, &roam_info, 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 */ static struct wiphy *wlan_create_wiphy(struct device *dev, struct wlandevice *wlandev) { struct wiphy *wiphy; struct prism2_wiphy_private *priv; wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv)); 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); priv->band.band = NL80211_BAND_2GHZ; priv->band.ht_cap.ht_supported = false; wiphy->bands[NL80211_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) { wiphy_free(wiphy); return NULL; } return wiphy; } static void wlan_free_wiphy(struct wiphy *wiphy) { wiphy_unregister(wiphy); wiphy_free(wiphy); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1