lbs_deb_enter(LBS_DEB_ASSOC);
+ /* FIXME: take channel into account when picking SSIDs if a channel
+ * is set.
+ */
+
lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid);
if (assoc_req->mode == IW_MODE_INFRA) {
if (adapter->prescan) {
}
+static int update_channel(wlan_private * priv)
+{
+ /* the channel in f/w could be out of sync, get the current channel */
+ return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+ cmd_opt_802_11_rf_channel_get,
+ cmd_option_waitforrsp, 0, NULL);
+}
+
+static int assoc_helper_channel(wlan_private *priv,
+ struct assoc_request * assoc_req)
+{
+ wlan_adapter *adapter = priv->adapter;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ ret = update_channel(priv);
+ if (ret < 0) {
+ lbs_deb_assoc("ASSOC: channel: error getting channel.");
+ }
+
+ if (assoc_req->channel == adapter->curbssparams.channel)
+ goto done;
+
+ lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
+ adapter->curbssparams.channel, assoc_req->channel);
+
+ ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+ cmd_opt_802_11_rf_channel_set,
+ cmd_option_waitforrsp, 0, &assoc_req->channel);
+ if (ret < 0) {
+ lbs_deb_assoc("ASSOC: channel: error setting channel.");
+ }
+
+ ret = update_channel(priv);
+ if (ret < 0) {
+ lbs_deb_assoc("ASSOC: channel: error getting channel.");
+ }
+
+ if (assoc_req->channel != adapter->curbssparams.channel) {
+ lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
+ assoc_req->channel);
+ goto done;
+ }
+
+ if ( assoc_req->secinfo.wep_enabled
+ && (assoc_req->wep_keys[0].len
+ || assoc_req->wep_keys[1].len
+ || assoc_req->wep_keys[2].len
+ || assoc_req->wep_keys[3].len)) {
+ /* Make sure WEP keys are re-sent to firmware */
+ set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
+ }
+
+ /* Must restart/rejoin adhoc networks after channel change */
+ set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
+
+done:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+ return ret;
+}
+
+
static int assoc_helper_wep_keys(wlan_private *priv,
struct assoc_request * assoc_req)
{
return 1;
}
+ if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+ if (assoc_req->channel != adapter->curbssparams.channel)
+ return 1;
+ }
+
return 0;
}
}
}
+ if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+ ret = assoc_helper_channel(priv, assoc_req);
+ if (ret) {
+ lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
+ __LINE__, ret);
+ goto out;
+ }
+ }
+
if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
|| test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
ret = assoc_helper_wep_keys(priv, assoc_req);
libertas_set_radio_control(priv);
- lbs_deb_join("Adhoc channel = %d\n", adapter->adhocchannel);
lbs_deb_join("curbssparams.channel = %d\n",
adapter->curbssparams.channel);
lbs_deb_join("curbssparams.band = %d\n", adapter->curbssparams.band);
adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
- WARN_ON(!adapter->adhocchannel);
+ WARN_ON(!adapter->curbssparams.channel);
lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
- adapter->adhocchannel);
-
- adapter->curbssparams.channel = adapter->adhocchannel;
+ adapter->curbssparams.channel);
- pbssdesc->channel = adapter->adhocchannel;
- adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
+ pbssdesc->channel = adapter->curbssparams.channel;
+ adhs->phyparamset.dsparamset.currentchan = adapter->curbssparams.channel;
memcpy(&pbssdesc->phyparamset,
&adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
- lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
+ lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
lbs_deb_join("ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
padhocresult->BSSID[0], padhocresult->BSSID[1],
padhocresult->BSSID[2], padhocresult->BSSID[3],
return cfp;
}
-static int updatecurrentchannel(wlan_private * priv)
-{
- int ret;
-
- /*
- ** the channel in f/w could be out of sync, get the current channel
- */
- ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
- cmd_opt_802_11_rf_channel_get,
- cmd_option_waitforrsp, 0, NULL);
-
- lbs_deb_wext("current channel %d\n",
- priv->adapter->curbssparams.channel);
-
- return ret;
-}
-
-static int setcurrentchannel(wlan_private * priv, int channel)
-{
- lbs_deb_wext("set channel %d\n", channel);
-
- /*
- ** Current channel is not set to adhocchannel requested, set channel
- */
- return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
- cmd_opt_802_11_rf_channel_set,
- cmd_option_waitforrsp, 0, &channel));
-}
-
-static int changeadhocchannel(wlan_private * priv, int channel)
-{
- int ret = 0;
- struct WLAN_802_11_SSID curadhocssid;
- struct bss_descriptor * join_bss = NULL;
- wlan_adapter *adapter = priv->adapter;
-
- adapter->adhocchannel = channel;
-
- updatecurrentchannel(priv);
-
- if (adapter->curbssparams.channel == adapter->adhocchannel) {
- /* adhocchannel is set to the current channel already */
- goto out;
- }
-
- lbs_deb_wext("updating channel from %d to %d\n",
- adapter->curbssparams.channel, adapter->adhocchannel);
-
- setcurrentchannel(priv, adapter->adhocchannel);
-
- updatecurrentchannel(priv);
-
- if (adapter->curbssparams.channel != adapter->adhocchannel) {
- lbs_deb_wext("failed to updated channel to %d, channel = %d\n",
- adapter->adhocchannel, adapter->curbssparams.channel);
- ret = -1;
- goto out;
- }
-
- if (adapter->connect_status != libertas_connected)
- goto out;
-
- lbs_deb_wext("channel changed while in IBSS\n");
-
- /* Copy the current ssid */
- memcpy(&curadhocssid, &adapter->curbssparams.ssid,
- sizeof(struct WLAN_802_11_SSID));
-
- /* Exit Adhoc mode */
- lbs_deb_wext("in changeadhocchannel(): sending Adhoc stop\n");
- ret = libertas_stop_adhoc_network(priv);
- if (ret)
- goto out;
-
- /* Scan for the network, do not save previous results. Stale
- * scan data will cause us to join a non-existant adhoc network
- */
- libertas_send_specific_SSID_scan(priv, &curadhocssid, 1);
-
- /* find out the BSSID that matches the current SSID */
- join_bss = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
- IW_MODE_ADHOC);
-
- if (join_bss) {
- lbs_deb_wext("SSID found in list, so join\n");
- libertas_join_adhoc_network(priv, join_bss);
- } else {
- lbs_deb_wext("SSID not found in list, "
- "creating AdHoc with SSID '%s'\n",
- curadhocssid.ssid);
- libertas_start_adhoc_network(priv, &curadhocssid);
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
/**
* @brief Set Radio On/OFF
static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
- int ret = 0;
+ int ret = -EINVAL;
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- int rc = -EINPROGRESS; /* Call commit handler */
struct chan_freq_power *cfp;
+ struct assoc_request * assoc_req;
lbs_deb_enter(LBS_DEB_WEXT);
- /*
- * If setting by frequency, convert to a channel
- */
- if (fwrq->e == 1) {
+ mutex_lock(&adapter->lock);
+ assoc_req = wlan_get_association_request(adapter);
+ if (!assoc_req) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ /* If setting by frequency, convert to a channel */
+ if (fwrq->e == 1) {
long f = fwrq->m / 100000;
- int c = 0;
cfp = find_cfp_by_band_and_freq(adapter, 0, f);
if (!cfp) {
lbs_deb_wext("invalid freq %ld\n", f);
- return -EINVAL;
+ goto out;
}
- c = (int)cfp->channel;
-
- if (c < 0)
- return -EINVAL;
-
fwrq->e = 0;
- fwrq->m = c;
+ fwrq->m = (int) cfp->channel;
}
- /*
- * Setting by channel number
- */
+ /* Setting by channel number */
if (fwrq->m > 1000 || fwrq->e > 0) {
- rc = -EOPNOTSUPP;
- } else {
- int channel = fwrq->m;
+ goto out;
+ }
- cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel);
- if (!cfp) {
- rc = -EINVAL;
- } else {
- if (adapter->mode == IW_MODE_ADHOC) {
- rc = changeadhocchannel(priv, channel);
- /* If station is WEP enabled, send the
- * command to set WEP in firmware
- */
- if (adapter->secinfo.wep_enabled) {
- lbs_deb_wext("set_freq: WEP enabled\n");
- ret = libertas_prepare_and_send_command(priv,
- cmd_802_11_set_wep,
- cmd_act_add,
- cmd_option_waitforrsp,
- 0,
- NULL);
-
- if (ret) {
- rc = ret;
- goto out;
- }
-
- adapter->currentpacketfilter |=
- cmd_act_mac_wep_enable;
-
- libertas_set_mac_packet_filter(priv);
- }
- } else {
- rc = -EOPNOTSUPP;
- }
- }
+ cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
+ if (!cfp) {
+ goto out;
}
+ assoc_req->channel = fwrq->m;
+ ret = 0;
+
out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", rc);
- return rc;
+ if (ret == 0) {
+ set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
+ wlan_postpone_association_work(priv);
+ } else {
+ wlan_cancel_association_work(priv);
+ }
+ mutex_unlock(&adapter->lock);
+
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
/**