#include "decl.h"
#include "hostcmd.h"
#include "host.h"
+#include "cmd.h"
static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static int update_channel(struct lbs_private *priv)
{
int ret;
+
/* the channel in f/w could be out of sync, get the current channel */
lbs_deb_enter(LBS_DEB_ASSOC);
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL,
- CMD_OPT_802_11_RF_CHANNEL_GET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
+
+ ret = lbs_get_channel(priv);
+ if (ret > 0)
+ priv->curbssparams.channel = (u8) ret;
+
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
priv->curbssparams.channel, assoc_req->channel);
- ret = lbs_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) {
+ ret = lbs_set_channel(priv, assoc_req->channel);
+ if (ret < 0)
lbs_deb_assoc("ASSOC: channel: error setting channel.");
- }
+ /* FIXME: shouldn't need to grab the channel _again_ after setting
+ * it since the firmware is supposed to return the new channel, but
+ * whatever... */
ret = update_channel(priv);
- if (ret < 0) {
+ if (ret < 0)
lbs_deb_assoc("ASSOC: channel: error getting channel.");
- }
if (assoc_req->channel != priv->curbssparams.channel) {
lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
return 0;
}
-static int lbs_cmd_802_11_rf_channel(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- int option, void *pdata_buf)
+/**
+ * @brief Get the radio channel
+ *
+ * @param priv A pointer to struct lbs_private structure
+ *
+ * @return The channel on success, error on failure
+ */
+int lbs_get_channel(struct lbs_private *priv)
{
- struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
+ struct cmd_ds_802_11_rf_channel cmd;
+ int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
- S_DS_GEN);
- if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
- rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
- }
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
- rfchan->action = cpu_to_le16(option);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, cmd);
+ if (ret)
+ goto out;
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ lbs_deb_cmd("current radio channel is %d\n", cmd.channel);
+ ret = (int) cmd.channel;
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Set the radio channel
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param channel The desired channel, or 0 to clear a locked channel
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_channel(struct lbs_private *priv, u8 channel)
+{
+ struct cmd_ds_802_11_rf_channel cmd;
+ u8 old_channel = priv->curbssparams.channel;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
+ cmd.channel = cpu_to_le16(channel);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, cmd);
+ if (ret)
+ goto out;
+
+ priv->curbssparams.channel = cmd.channel;
+ lbs_deb_cmd("channel switch from %d to %d\n", old_channel, cmd.channel);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
break;
- case CMD_802_11_RF_CHANNEL:
- ret = lbs_cmd_802_11_rf_channel(priv, cmdptr,
- cmd_action, pdata_buf);
- break;
-
case CMD_802_11_RF_TX_POWER:
ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
cmd_action, pdata_buf);
int lbs_get_data_rate(struct lbs_private *priv);
int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
+int lbs_get_channel(struct lbs_private *priv);
+int lbs_set_channel(struct lbs_private *priv, u8 channel);
+
#endif /* _LBS_CMD_H */
return 0;
}
-static int lbs_ret_802_11_rf_channel(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
- u16 action = le16_to_cpu(rfchannel->action);
- u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (action == CMD_OPT_802_11_RF_CHANNEL_GET
- && priv->curbssparams.channel != newchannel) {
- lbs_deb_cmd("channel switch from %d to %d\n",
- priv->curbssparams.channel, newchannel);
-
- /* Update the channel again */
- priv->curbssparams.channel = newchannel;
- }
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
static int lbs_ret_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
break;
- case CMD_RET(CMD_802_11_RF_CHANNEL):
- ret = lbs_ret_802_11_rf_channel(priv, resp);
- break;
case CMD_RET(CMD_802_11_RSSI):
ret = lbs_ret_802_11_rssi(priv, resp);
};
struct cmd_ds_802_11_rf_channel {
+ struct cmd_header hdr;
+
__le16 action;
- __le16 currentchannel;
- __le16 rftype;
- __le16 reserved;
- u8 channellist[32];
+ __le16 channel;
+ __le16 rftype; /* unused */
+ __le16 reserved; /* unused */
+ u8 channellist[32]; /* unused */
};
struct cmd_ds_802_11_rssi {