/* * Copies the multicast address list from device to driver. * * This function does not validate the destination memory for * size, and the calling function must ensure enough memory is * available.
*/ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, struct net_device *dev)
{ int i = 0; struct netdev_hw_addr *ha;
/* * Wait queue completion handler. * * This function waits on a cmd wait queue. It also cancels the pending * request after waking up, in case of errors.
*/ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_queued)
{ int status;
/* Wait for completion */
status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait,
*(cmd_queued->condition),
(12 * HZ)); if (status <= 0) { if (status == 0)
status = -ETIMEDOUT;
mwifiex_dbg(adapter, ERROR, "cmd_wait_q terminated: %d\n",
status);
mwifiex_cancel_all_pending_cmd(adapter); return status;
}
status = adapter->cmd_wait_q.status;
adapter->cmd_wait_q.status = 0;
return status;
}
/* * This function prepares the correct firmware command and * issues it to set the multicast list. * * This function can be used to enable promiscuous mode, or enable all * multicast packets, or to enable selective multicast.
*/ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, struct mwifiex_multicast_list *mcast_list)
{ int ret = 0;
u16 old_pkt_filter;
/* * This function fills bss descriptor structure using provided * information. * beacon_ie buffer is allocated in this function. It is caller's * responsibility to free the memory.
*/ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, struct cfg80211_bss *bss, struct mwifiex_bssdescriptor *bss_desc)
{
u8 *beacon_ie;
size_t beacon_ie_len; struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; conststruct cfg80211_bss_ies *ies;
if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
HostCmd_ACT_GEN_SET, 0, NULL, false)) {
mwifiex_dbg(priv->adapter, ERROR, "11D: setting domain info in FW fail\n"); return -1;
}
mwifiex_dnld_txpwr_table(priv);
return 0;
}
/* * In Ad-Hoc mode, the IBSS is created if not found in scan list. * In both Ad-Hoc and infra mode, an deauthentication is performed * first.
*/ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, struct cfg80211_ssid *req_ssid)
{ int ret; struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_bssdescriptor *bss_desc = NULL;
priv->scan_block = false;
if (bss) { if (adapter->region_code == 0x00 &&
mwifiex_process_country_ie(priv, bss)) return -EINVAL;
/* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
GFP_KERNEL); if (!bss_desc) return -ENOMEM;
ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc); if (ret) goto done;
}
if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands))
adapter->config_bands = config_bands;
ret = mwifiex_check_network_compatibility(priv, bss_desc); if (ret) goto done;
if (mwifiex_11h_get_csa_closed_channel(priv) ==
(u8)bss_desc->channel) {
mwifiex_dbg(adapter, ERROR, "Attempt to reconnect on csa closed chan(%d)\n",
bss_desc->channel);
ret = -1; goto done;
}
mwifiex_dbg(adapter, INFO, "info: SSID found in scan list ...\t" "associating...\n");
mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
/* Clear any past association response stored for
* application retrieval */
priv->assoc_rsp_size = 0;
ret = mwifiex_associate(priv, bss_desc);
/* If auth type is auto and association fails using open mode,
* try to connect using shared mode */ if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
priv->sec_info.is_authtype_auto &&
priv->sec_info.wep_enabled) {
priv->sec_info.authentication_mode =
NL80211_AUTHTYPE_SHARED_KEY;
ret = mwifiex_associate(priv, bss_desc);
}
if (bss && !priv->adapter->host_mlme_enabled)
cfg80211_put_bss(priv->adapter->wiphy, bss);
} else { /* Adhoc mode */ /* If the requested SSID matches current SSID, return */ if (bss_desc && bss_desc->ssid.ssid_len &&
cfg80211_ssid_eq(&priv->curr_bss_params.bss_descriptor.ssid,
&bss_desc->ssid)) {
ret = 0; goto done;
}
ret = mwifiex_check_network_compatibility(priv, bss_desc);
mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
if (!ret) {
mwifiex_dbg(adapter, INFO, "info: network found in scan\t" " list. Joining...\n");
ret = mwifiex_adhoc_join(priv, bss_desc); if (bss)
cfg80211_put_bss(priv->adapter->wiphy, bss);
} else {
mwifiex_dbg(adapter, INFO, "info: Network not found in\t" "the list, creating adhoc with ssid = %s\n",
req_ssid->ssid);
ret = mwifiex_adhoc_start(priv, req_ssid);
}
}
done: /* beacon_ie buffer was allocated in function * mwifiex_fill_new_bss_desc(). Free it now.
*/ if (bss_desc)
kfree(bss_desc->beacon_buf);
kfree(bss_desc);
if (ret < 0)
priv->attempted_bss_desc = NULL;
return ret;
}
/* * IOCTL request handler to set host sleep configuration. * * This function prepares the correct firmware command and * issues it.
*/ int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
{ struct mwifiex_adapter *adapter = priv->adapter; int status = 0;
u32 prev_cond = 0;
if (!hs_cfg) return -ENOMEM;
switch (action) { case HostCmd_ACT_GEN_SET: if (adapter->pps_uapsd_mode) {
mwifiex_dbg(adapter, INFO, "info: Host Sleep IOCTL\t" "is blocked in UAPSD/PPS mode\n");
status = -1; break;
} if (hs_cfg->is_invoke_hostcmd) { if (hs_cfg->conditions == HS_CFG_CANCEL) { if (!test_bit(MWIFIEX_IS_HS_CONFIGURED,
&adapter->work_flags)) /* Already cancelled */ break; /* Save previous condition */
prev_cond = le32_to_cpu(adapter->hs_cfg
.conditions);
adapter->hs_cfg.conditions =
cpu_to_le32(hs_cfg->conditions);
} elseif (hs_cfg->conditions) {
adapter->hs_cfg.conditions =
cpu_to_le32(hs_cfg->conditions);
adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; if (hs_cfg->gap)
adapter->hs_cfg.gap = (u8)hs_cfg->gap;
} elseif (adapter->hs_cfg.conditions ==
cpu_to_le32(HS_CFG_CANCEL)) { /* Return failure if no parameters for HS
enable */
status = -1; break;
}
status = mwifiex_send_cmd(priv,
HostCmd_CMD_802_11_HS_CFG_ENH,
HostCmd_ACT_GEN_SET, 0,
&adapter->hs_cfg,
cmd_type == MWIFIEX_SYNC_CMD);
/* * Sends IOCTL request to cancel the existing Host Sleep configuration. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)
{ struct mwifiex_ds_hs_cfg hscfg;
/* * Sends IOCTL request to cancel the existing Host Sleep configuration. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
{ struct mwifiex_ds_hs_cfg hscfg; struct mwifiex_private *priv; int i;
if (disconnect_on_suspend) { for (i = 0; i < adapter->priv_num; i++) {
priv = adapter->priv[i];
mwifiex_deauthenticate(priv, NULL);
}
}
/* * IOCTL request handler to get BSS information. * * This function collates the information from different driver structures * to send to the user.
*/ int mwifiex_get_bss_info(struct mwifiex_private *priv, struct mwifiex_bss_info *info)
{ struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_bssdescriptor *bss_desc;
/* * The function disables auto deep sleep mode.
*/ int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
{ struct mwifiex_ds_auto_ds auto_ds = {
.auto_ds = DEEP_SLEEP_OFF,
};
/* * Sends IOCTL request to get the data rate. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate)
{ int ret;
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL, true);
if (!ret) { if (priv->is_data_rate_auto)
*rate = mwifiex_index_to_data_rate(priv, priv->tx_rate,
priv->tx_htinfo); else
*rate = priv->data_rate;
}
return ret;
}
/* * IOCTL request handler to set tx power configuration. * * This function prepares the correct firmware command and * issues it. * * For non-auto power mode, all the following power groups are set - * - Modulation class HR/DSSS * - Modulation class OFDM * - Modulation class HTBW20 * - Modulation class HTBW40
*/ int mwifiex_set_tx_power(struct mwifiex_private *priv, struct mwifiex_power_cfg *power_cfg)
{ int ret; struct host_cmd_ds_txpwr_cfg *txp_cfg; struct mwifiex_types_power_group *pg_tlv; struct mwifiex_power_group *pg;
u8 *buf;
u16 dbm = 0;
if (!power_cfg->is_power_auto) {
dbm = (u16) power_cfg->power_level; if ((dbm < priv->min_tx_power_level) ||
(dbm > priv->max_tx_power_level)) {
mwifiex_dbg(priv->adapter, ERROR, "txpower value %d dBm\t" "is out of range (%d dBm-%d dBm)\n",
dbm, priv->min_tx_power_level,
priv->max_tx_power_level); return -1;
}
}
buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL); if (!buf) return -ENOMEM;
txp_cfg->mode = cpu_to_le32(1);
pg_tlv = (struct mwifiex_types_power_group *)
(buf + sizeof(struct host_cmd_ds_txpwr_cfg));
pg_tlv->type = cpu_to_le16(TLV_TYPE_POWER_GROUP);
pg_tlv->length =
cpu_to_le16(4 * sizeof(struct mwifiex_power_group));
pg = (struct mwifiex_power_group *)
(buf + sizeof(struct host_cmd_ds_txpwr_cfg)
+ sizeof(struct mwifiex_types_power_group)); /* Power group for modulation class HR/DSSS */
pg->first_rate_code = 0x00;
pg->last_rate_code = 0x03;
pg->modulation_class = MOD_CLASS_HR_DSSS;
pg->power_step = 0;
pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg++; /* Power group for modulation class OFDM */
pg->first_rate_code = 0x00;
pg->last_rate_code = 0x07;
pg->modulation_class = MOD_CLASS_OFDM;
pg->power_step = 0;
pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg++; /* Power group for modulation class HTBW20 */
pg->first_rate_code = 0x00;
pg->last_rate_code = 0x20;
pg->modulation_class = MOD_CLASS_HT;
pg->power_step = 0;
pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg->ht_bandwidth = HT_BW_20;
pg++; /* Power group for modulation class HTBW40 */
pg->first_rate_code = 0x00;
pg->last_rate_code = 0x20;
pg->modulation_class = MOD_CLASS_HT;
pg->power_step = 0;
pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg->ht_bandwidth = HT_BW_40;
}
ret = mwifiex_send_cmd(priv, HostCmd_CMD_TXPWR_CFG,
HostCmd_ACT_GEN_SET, 0, buf, true);
kfree(buf); return ret;
}
/* * IOCTL request handler to get power save mode. * * This function prepares the correct firmware command and * issues it.
*/ int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode)
{ int ret; struct mwifiex_adapter *adapter = priv->adapter;
u16 sub_cmd;
if (*ps_mode)
adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; else
adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS;
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
sub_cmd, BITMAP_STA_PS, NULL, true); if ((!ret) && (sub_cmd == DIS_AUTO_PS))
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
GET_PS, 0, NULL, false);
return ret;
}
/* * IOCTL request handler to set/reset WPA IE. * * The supplied WPA IE is treated as a opaque buffer. Only the first field * is checked to determine WPA version. If buffer length is zero, the existing * WPA IE is reset.
*/ staticint mwifiex_set_wpa_ie(struct mwifiex_private *priv,
u8 *ie_data_ptr, u16 ie_len)
{ if (ie_len) { if (ie_len > sizeof(priv->wpa_ie)) {
mwifiex_dbg(priv->adapter, ERROR, "failed to copy WPA IE, too big\n"); return -1;
}
memcpy(priv->wpa_ie, ie_data_ptr, ie_len);
priv->wpa_ie_len = ie_len;
mwifiex_dbg(priv->adapter, CMD, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
priv->wpa_ie_len, priv->wpa_ie[0]);
/* * IOCTL request handler to set/reset WAPI IE. * * The supplied WAPI IE is treated as a opaque buffer. Only the first field * is checked to internally enable WAPI. If buffer length is zero, the existing * WAPI IE is reset.
*/ staticint mwifiex_set_wapi_ie(struct mwifiex_private *priv,
u8 *ie_data_ptr, u16 ie_len)
{ if (ie_len) { if (ie_len > sizeof(priv->wapi_ie)) {
mwifiex_dbg(priv->adapter, ERROR, "info: failed to copy WAPI IE, too big\n"); return -1;
}
memcpy(priv->wapi_ie, ie_data_ptr, ie_len);
priv->wapi_ie_len = ie_len;
mwifiex_dbg(priv->adapter, CMD, "cmd: Set wapi_ie_len=%d IE=%#x\n",
priv->wapi_ie_len, priv->wapi_ie[0]);
/* * IOCTL request handler to set/reset WPS IE. * * The supplied WPS IE is treated as a opaque buffer. Only the first field * is checked to internally enable WPS. If buffer length is zero, the existing * WPS IE is reset.
*/ staticint mwifiex_set_wps_ie(struct mwifiex_private *priv,
u8 *ie_data_ptr, u16 ie_len)
{ if (ie_len) { if (ie_len > MWIFIEX_MAX_VSIE_LEN) {
mwifiex_dbg(priv->adapter, ERROR, "info: failed to copy WPS IE, too big\n"); return -1;
}
priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL); if (!priv->wps_ie) return -ENOMEM;
/* * IOCTL request handler to set WAPI key. * * This function prepares the correct firmware command and * issues it.
*/ staticint mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key)
{
/* Send request to firmware */
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_GEN_SET, 0, enc_key, false); if (ret) return ret;
}
done: if (priv->sec_info.wep_enabled)
priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; else
priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
HostCmd_ACT_GEN_SET, 0,
&priv->curr_pkt_filter, true);
return ret;
}
/* * IOCTL request handler to set WPA key. * * This function prepares the correct firmware command and * issues it, after validation checks. * * Current driver only supports key length of up to 32 bytes. * * This function can also be used to disable a currently set key.
*/ staticint mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key)
{ int ret;
u8 remove_key = false; struct host_cmd_ds_802_11_key_material *ibss_key;
/* Current driver only supports key length of up to 32 bytes */ if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) {
mwifiex_dbg(priv->adapter, ERROR, "key length too long\n"); return -1;
}
if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { /* * IBSS/WPA-None uses only one key (Group) for both receiving * and sending unicast and multicast packets.
*/ /* Send the key as PTK to firmware */
encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_GEN_SET,
KEY_INFO_ENABLED, encrypt_key, false); if (ret) return ret;
ibss_key = &priv->aes_key;
memset(ibss_key, 0, sizeof(struct host_cmd_ds_802_11_key_material)); /* Copy the key in the driver */
memcpy(ibss_key->key_param_set.key, encrypt_key->key_material,
encrypt_key->key_len);
memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len, sizeof(ibss_key->key_param_set.key_len));
ibss_key->key_param_set.key_type_id
= cpu_to_le16(KEY_TYPE_ID_TKIP);
ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED);
/* Send the key as GTK to firmware */
encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST;
}
if (!encrypt_key->key_index)
encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
if (remove_key)
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_GEN_SET,
!KEY_INFO_ENABLED, encrypt_key, true); else
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_GEN_SET,
KEY_INFO_ENABLED, encrypt_key, true);
return ret;
}
/* * IOCTL request handler to set/get network keys. * * This is a generic key handling function which supports WEP, WPA * and WAPI.
*/ staticint
mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key)
{ int status;
if (encrypt_key->is_wapi_key)
status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); elseif (encrypt_key->key_len > WLAN_KEY_LEN_WEP104)
status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key); else
status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key); return status;
}
/* * This function returns the driver version.
*/ int
mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, int max_len)
{ union {
__le32 l;
u8 c[4];
} ver; char fw_ver[32];
/* * Sends IOCTL request to set encoding parameters. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, const u8 *key, int key_len, u8 key_index, const u8 *mac_addr, int disable)
{ struct mwifiex_ds_encrypt_key encrypt_key;
/* * Sends IOCTL request to get extended version. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int
mwifiex_get_ver_ext(struct mwifiex_private *priv, u32 version_str_sel)
{ struct mwifiex_ver_ext ver_ext;
roc_cfg.channel =
ieee80211_frequency_to_channel(chan->center_freq);
roc_cfg.duration = cpu_to_le32(duration);
} if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN,
action, 0, &roc_cfg, true)) {
mwifiex_dbg(priv->adapter, ERROR, "failed to remain on channel\n"); return -1;
}
return roc_cfg.status;
}
/* * Sends IOCTL request to get statistics information. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int
mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log)
{ return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_GET_LOG,
HostCmd_ACT_GEN_GET, 0, log, true);
}
/* * IOCTL request handler to read/write register. * * This function prepares the correct firmware command and * issues it. * * Access to the following registers are supported - * - MAC * - BBP * - RF * - PMIC * - CAU
*/ staticint mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, struct mwifiex_ds_reg_rw *reg_rw,
u16 action)
{
u16 cmd_no;
switch (reg_rw->type) { case MWIFIEX_REG_MAC:
cmd_no = HostCmd_CMD_MAC_REG_ACCESS; break; case MWIFIEX_REG_BBP:
cmd_no = HostCmd_CMD_BBP_REG_ACCESS; break; case MWIFIEX_REG_RF:
cmd_no = HostCmd_CMD_RF_REG_ACCESS; break; case MWIFIEX_REG_PMIC:
cmd_no = HostCmd_CMD_PMIC_REG_ACCESS; break; case MWIFIEX_REG_CAU:
cmd_no = HostCmd_CMD_CAU_REG_ACCESS; break; default: return -1;
}
/* * Sends IOCTL request to write to a register. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int
mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
u32 reg_offset, u32 reg_value)
{ struct mwifiex_ds_reg_rw reg_rw;
/* * Sends IOCTL request to read from a register. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int
mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
u32 reg_offset, u32 *value)
{ int ret; struct mwifiex_ds_reg_rw reg_rw;
/* * Sends IOCTL request to read from EEPROM. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int
mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
u8 *value)
{ int ret; struct mwifiex_ds_read_eeprom rd_eeprom;
/* Send request to firmware */
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS,
HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true);
if (!ret)
memcpy(value, rd_eeprom.value, min((u16)MAX_EEPROM_DATA,
rd_eeprom.byte_count)); return ret;
}
/* * This function sets a generic IE. In addition to generic IE, it can * also handle WPA, WPA2 and WAPI IEs.
*/ staticint
mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
u16 ie_len)
{ struct ieee_types_vendor_header *pvendor_ie; staticconst u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 }; staticconst u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
u16 unparsed_len = ie_len, cur_ie_len;
/* If the passed length is zero, reset the buffer */ if (!ie_len) {
priv->gen_ie_buf_len = 0;
priv->wps.session_enable = false; return 0;
} elseif (!ie_data_ptr ||
ie_len <= sizeof(struct ieee_types_header)) { return -1;
}
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
while (pvendor_ie) {
cur_ie_len = pvendor_ie->len + sizeof(struct ieee_types_header);
if (pvendor_ie->element_id == WLAN_EID_RSN) { /* IE is a WPA/WPA2 IE so call set_wpa function */
mwifiex_set_wpa_ie(priv, (u8 *)pvendor_ie, cur_ie_len);
priv->wps.session_enable = false; goto next_ie;
}
if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) { /* IE is a WAPI IE so call set_wapi function */
mwifiex_set_wapi_ie(priv, (u8 *)pvendor_ie,
cur_ie_len); goto next_ie;
}
if (pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) { /* Test to see if it is a WPA IE, if not, then * it is a gen IE
*/ if (!memcmp(&pvendor_ie->oui, wpa_oui, sizeof(wpa_oui))) { /* IE is a WPA/WPA2 IE so call set_wpa function
*/
mwifiex_set_wpa_ie(priv, (u8 *)pvendor_ie,
cur_ie_len);
priv->wps.session_enable = false; goto next_ie;
}
if (!memcmp(&pvendor_ie->oui, wps_oui, sizeof(wps_oui))) { /* Test to see if it is a WPS IE, * if so, enable wps session flag
*/
priv->wps.session_enable = true;
mwifiex_dbg(priv->adapter, MSG, "WPS Session Enabled.\n");
mwifiex_set_wps_ie(priv, (u8 *)pvendor_ie,
cur_ie_len); goto next_ie;
}
}
/* Saved in gen_ie, such as P2P IE.etc.*/
/* Verify that the passed length is not larger than the * available space remaining in the buffer
*/ if (cur_ie_len <
(sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) { /* Append the passed data to the end * of the genIeBuffer
*/
memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len,
(u8 *)pvendor_ie, cur_ie_len); /* Increment the stored buffer length by the * size passed
*/
priv->gen_ie_buf_len += cur_ie_len;
}
/* * IOCTL request handler to set/get generic IE. * * In addition to various generic IEs, this function can also be * used to set the ARP filter.
*/ staticint mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, struct mwifiex_ds_misc_gen_ie *gen_ie,
u16 action)
{ struct mwifiex_adapter *adapter = priv->adapter;
/* * Sends IOCTL request to set a generic IE. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler.
*/ int
mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len)
{ struct mwifiex_ds_misc_gen_ie gen_ie;
/* This function get Host Sleep wake up reason. *
*/ int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, int cmd_type, struct mwifiex_ds_wakeup_reason *wakeup_reason)
{ int status = 0;
status = mwifiex_send_cmd(priv, HostCmd_CMD_HS_WAKEUP_REASON,
HostCmd_ACT_GEN_GET, 0, wakeup_reason,
cmd_type == MWIFIEX_SYNC_CMD);
return status;
}
int mwifiex_get_chan_info(struct mwifiex_private *priv, struct mwifiex_channel_band *channel_band)
{ int status = 0;
status = mwifiex_send_cmd(priv, HostCmd_CMD_STA_CONFIGURE,
HostCmd_ACT_GEN_GET, 0, channel_band,
MWIFIEX_SYNC_CMD);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.