return ret;
}
-static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- union iwreq_data wrqu;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
-
- lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
-
-out_unlock:
- free_page(addr);
- return count;
-}
-
-static void lbs_parse_bssid(char *buf, size_t count,
- struct lbs_ioctl_user_scan_cfg *scan_cfg)
-{
- char *hold;
- unsigned int mac[ETH_ALEN];
-
- hold = strstr(buf, "bssid=");
- if (!hold)
- return;
- hold += 6;
- sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
- mac, mac+1, mac+2, mac+3, mac+4, mac+5);
- memcpy(scan_cfg->bssid, mac, ETH_ALEN);
-}
-
-static void lbs_parse_ssid(char *buf, size_t count,
- struct lbs_ioctl_user_scan_cfg *scan_cfg)
-{
- char *hold, *end;
- ssize_t size;
-
- hold = strstr(buf, "ssid=");
- if (!hold)
- return;
- hold += 5;
- end = strchr(hold, ' ');
- if (!end)
- end = buf + count - 1;
-
- size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
- strncpy(scan_cfg->ssid, hold, size);
-
- return;
-}
-
-static int lbs_parse_clear(char *buf, size_t count, const char *tag)
-{
- char *hold;
- int val;
-
- hold = strstr(buf, tag);
- if (!hold)
- return 0;
- hold += strlen(tag);
- sscanf(hold, "%d", &val);
-
- if (val != 0)
- val = 1;
-
- return val;
-}
-
-static int lbs_parse_dur(char *buf, size_t count,
- struct lbs_ioctl_user_scan_cfg *scan_cfg)
-{
- char *hold;
- int val;
-
- hold = strstr(buf, "dur=");
- if (!hold)
- return 0;
- hold += 4;
- sscanf(hold, "%d", &val);
-
- return val;
-}
-
-static void lbs_parse_type(char *buf, size_t count,
- struct lbs_ioctl_user_scan_cfg *scan_cfg)
-{
- char *hold;
- int val;
-
- hold = strstr(buf, "type=");
- if (!hold)
- return;
- hold += 5;
- sscanf(hold, "%d", &val);
-
- /* type=1,2 or 3 */
- if (val < 1 || val > 3)
- return;
-
- scan_cfg->bsstype = val;
-
- return;
-}
-
-static ssize_t lbs_setuserscan(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- struct lbs_ioctl_user_scan_cfg *scan_cfg;
- union iwreq_data wrqu;
- int dur;
- char *buf = (char *)get_zeroed_page(GFP_KERNEL);
-
- if (!buf)
- return -ENOMEM;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_buf;
- }
-
- scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
- if (!scan_cfg) {
- res = -ENOMEM;
- goto out_buf;
- }
- res = count;
-
- scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
-
- dur = lbs_parse_dur(buf, count, scan_cfg);
- lbs_parse_bssid(buf, count, scan_cfg);
- scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
- lbs_parse_ssid(buf, count, scan_cfg);
- scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
- lbs_parse_type(buf, count, scan_cfg);
-
- lbs_scan_networks(priv, scan_cfg, 1);
- wait_event_interruptible(priv->cmd_pending,
- priv->surpriseremoved || !priv->scan_channel);
-
- if (priv->surpriseremoved)
- goto out_scan_cfg;
-
- memset(&wrqu, 0x00, sizeof(union iwreq_data));
- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
-
- out_scan_cfg:
- kfree(scan_cfg);
- out_buf:
- free_page((unsigned long)buf);
- return res;
-}
-
-
/*
* When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
* get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
write_file_dummy), },
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
lbs_sleepparams_write), },
- { "extscan", 0600, FOPS(NULL, lbs_extscan), },
- { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
};
static struct lbs_debugfs_files debugfs_events_files[] = {
-
/*********************************************************************/
/* */
/* Main scanning support */
/* */
/*********************************************************************/
-void lbs_scan_worker(struct work_struct *work)
-{
- struct lbs_private *priv =
- container_of(work, struct lbs_private, scan_work.work);
-
- lbs_deb_enter(LBS_DEB_SCAN);
- lbs_scan_networks(priv, NULL, 0);
- lbs_deb_leave(LBS_DEB_SCAN);
-}
-
-
/**
* @brief Create a channel list for the driver to scan based on region info
*
*
* @param priv A pointer to struct lbs_private structure
* @param scanchanlist Output parameter: resulting channel list to scan
- * @param filteredscan Flag indicating whether or not a BSSID or SSID filter
- * is being sent in the command to firmware. Used to
- * increase the number of channels sent in a scan
- * command and to disable the firmware channel scan
- * filter.
*
* @return void
*/
static int lbs_scan_create_channel_list(struct lbs_private *priv,
- struct chanscanparamset *scanchanlist,
- uint8_t filteredscan)
+ struct chanscanparamset *scanchanlist)
{
struct region_channel *scanregion;
struct chan_freq_power *cfp;
}
chan->channumber = cfp->channel;
-
- if (filteredscan)
- chan->chanscanmode.disablechanfilt = 1;
}
}
return chanidx;
* length 06 00
* ssid 4d 4e 54 45 53 54
*/
-static int lbs_scan_add_ssid_tlv(uint8_t *tlv,
- const struct lbs_ioctl_user_scan_cfg *user_cfg)
+static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
{
struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
- ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len);
- memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len);
- return sizeof(ssid_tlv->header) + user_cfg->ssid_len;
+ ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
+ memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
+ return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
}
* for a bunch of channels.
*/
static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
- struct chanscanparamset *chan_list, int chan_count,
- const struct lbs_ioctl_user_scan_cfg *user_cfg)
+ struct chanscanparamset *chan_list, int chan_count)
{
int ret = -ENOMEM;
struct cmd_ds_802_11_scan *scan_cmd;
goto out;
tlv = scan_cmd->tlvbuffer;
- if (user_cfg)
- memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN);
+ /* TODO: do we need to scan for a specific BSSID?
+ memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
scan_cmd->bsstype = bsstype;
/* add TLVs */
- if (user_cfg && user_cfg->ssid_len)
- tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg);
+ if (priv->scan_ssid_len)
+ tlv += lbs_scan_add_ssid_tlv(priv, tlv);
if (chan_list && chan_count)
tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
tlv += lbs_scan_add_rates_tlv(tlv);
* update the internal driver scan table
*
* @param priv A pointer to struct lbs_private structure
- * @param puserscanin Pointer to the input configuration for the requested
- * scan.
+ * @param full_scan Do a full-scan (blocking)
*
* @return 0 or < 0 if error
*/
-int lbs_scan_networks(struct lbs_private *priv,
- const struct lbs_ioctl_user_scan_cfg *user_cfg,
- int full_scan)
+static int lbs_scan_networks(struct lbs_private *priv, int full_scan)
{
int ret = -ENOMEM;
struct chanscanparamset *chan_list;
int chan_count;
uint8_t bsstype = CMD_BSS_TYPE_ANY;
int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
- int filteredscan = 0;
union iwreq_data wrqu;
#ifdef CONFIG_LIBERTAS_DEBUG
struct bss_descriptor *iter;
if (full_scan && delayed_work_pending(&priv->scan_work))
cancel_delayed_work(&priv->scan_work);
- /* Determine same scan parameters */
+ /* User-specified bsstype or channel list
+ TODO: this can be implemented if some user-space application
+ need the feature. Formerly, it was accessible from debugfs,
+ but then nowhere used.
if (user_cfg) {
if (user_cfg->bsstype)
- bsstype = user_cfg->bsstype;
- if (!is_zero_ether_addr(user_cfg->bssid)) {
- numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN;
- filteredscan = 1;
- }
- }
- lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n",
- numchannels, bsstype, filteredscan);
+ bsstype = user_cfg->bsstype;
+ } */
+
+ lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
/* Create list of channels to scan */
chan_list = kzalloc(sizeof(struct chanscanparamset) *
}
/* We want to scan all channels */
- chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan);
+ chan_count = lbs_scan_create_channel_list(priv, chan_list);
netif_stop_queue(priv->dev);
netif_carrier_off(priv->dev);
lbs_deb_scan("scanning %d of %d channels\n",
to_scan, chan_count);
ret = lbs_do_scan(priv, bsstype, curr_chans,
- to_scan, user_cfg);
+ to_scan);
if (ret) {
lbs_pr_err("SCAN_CMD failed\n");
goto out2;
+void lbs_scan_worker(struct work_struct *work)
+{
+ struct lbs_private *priv =
+ container_of(work, struct lbs_private, scan_work.work);
+
+ lbs_deb_enter(LBS_DEB_SCAN);
+ lbs_scan_networks(priv, 0);
+ lbs_deb_leave(LBS_DEB_SCAN);
+}
+
+
/*********************************************************************/
/* */
/* Result interpretation */
}
/**
- * @brief Find the AP with specific ssid in the scan list
+ * @brief Find the best AP
*
* Used from association worker.
*
lbs_deb_enter(LBS_DEB_SCAN);
- lbs_scan_networks(priv, NULL, 1);
+ priv->scan_ssid_len = 0;
+ lbs_scan_networks(priv, 1);
if (priv->surpriseremoved)
goto out;
* @param priv A pointer to struct lbs_private structure
* @param ssid A pointer to the SSID to scan for
* @param ssid_len Length of the SSID
- * @param clear_ssid Should existing scan results with this SSID
- * be cleared?
*
* @return 0-success, otherwise fail
*/
int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
- uint8_t ssid_len, uint8_t clear_ssid)
+ uint8_t ssid_len)
{
- struct lbs_ioctl_user_scan_cfg scancfg;
int ret = 0;
- lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d",
- escape_essid(ssid, ssid_len), clear_ssid);
+ lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
+ escape_essid(ssid, ssid_len));
if (!ssid_len)
goto out;
- memset(&scancfg, 0x00, sizeof(scancfg));
- memcpy(scancfg.ssid, ssid, ssid_len);
- scancfg.ssid_len = ssid_len;
- scancfg.clear_ssid = clear_ssid;
+ memcpy(priv->scan_ssid, ssid, ssid_len);
+ priv->scan_ssid_len = ssid_len;
- lbs_scan_networks(priv, &scancfg, 1);
+ lbs_scan_networks(priv, 1);
if (priv->surpriseremoved) {
ret = -1;
goto out;
* @return 0 --success, otherwise fail
*/
int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *wrqu, char *extra)
+ union iwreq_data *wrqu, char *extra)
{
struct lbs_private *priv = dev->priv;
+ int ret = 0;
- lbs_deb_enter(LBS_DEB_SCAN);
+ lbs_deb_enter(LBS_DEB_WEXT);
- if (!netif_running(dev))
- return -ENETDOWN;
+ if (!netif_running(dev)) {
+ ret = -ENETDOWN;
+ goto out;
+ }
/* mac80211 does this:
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->type != IEEE80211_IF_TYPE_xxx)
- return -EOPNOTSUPP;
+ if (sdata->type != IEEE80211_IF_TYPE_xxx) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+ */
if (wrqu->data.length == sizeof(struct iw_scan_req) &&
wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- req = (struct iw_scan_req *)extra;
- ssid = req->essid;
- ssid_len = req->essid_len;
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ priv->scan_ssid_len = req->essid_len;
+ memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
+ lbs_deb_wext("set_scan, essid '%s'\n",
+ escape_essid(priv->scan_ssid, priv->scan_ssid_len));
+ } else {
+ priv->scan_ssid_len = 0;
}
- */
if (!delayed_work_pending(&priv->scan_work))
queue_delayed_work(priv->work_thread, &priv->scan_work,
priv->scan_channel = -1;
if (priv->surpriseremoved)
- return -EIO;
+ ret = -EIO;
- lbs_deb_leave(LBS_DEB_SCAN);
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
struct bss_descriptor *iter_bss;
struct bss_descriptor *safe;
- lbs_deb_enter(LBS_DEB_SCAN);
+ lbs_deb_enter(LBS_DEB_WEXT);
/* iwlist should wait until the current scan is finished */
if (priv->scan_channel)
dwrq->length = (ev - extra);
dwrq->flags = 0;
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err);
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
return err;
}
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
- *
- * @sa lbs_ioctl_user_scan_cfg
*/
#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
//! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter
#define LBS_SCAN_BSS_TYPE_ANY 3
-/**
- * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
- *
- * Multiple instances of this structure are included in the IOCTL command
- * to configure a instance of a scan on the specific channel.
- */
-struct lbs_ioctl_user_scan_chan {
- u8 channumber; //!< channel Number to scan
- u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
- u8 scantype; //!< Scan type: Active = 0, Passive = 1
- u16 scantime; //!< Scan duration in milliseconds; if 0 default used
-};
-
-/**
- * @brief IOCTL input structure to configure an immediate scan cmd to firmware
- *
- * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
- * a number of parameters to be used in general for the scan as well
- * as a channel list (lbs_ioctl_user_scan_chan) for each scan period
- * desired.
- *
- * @sa lbs_set_user_scan_ioctl
- */
-struct lbs_ioctl_user_scan_cfg {
- /**
- * @brief BSS type to be sent in the firmware command
- *
- * Field can be used to restrict the types of networks returned in the
- * scan. valid settings are:
- *
- * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
- * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
- * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
- */
- u8 bsstype;
-
- /**
- * @brief BSSID filter sent in the firmware command to limit the results
- */
- u8 bssid[ETH_ALEN];
-
- /* Clear existing scan results matching this BSSID */
- u8 clear_bssid;
-
- /**
- * @brief SSID filter sent in the firmware command to limit the results
- */
- char ssid[IW_ESSID_MAX_SIZE];
- u8 ssid_len;
-
- /* Clear existing scan results matching this SSID */
- u8 clear_ssid;
-};
-
/**
* @brief Structure used to store information for each beacon/probe response
*/
u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
- u8 ssid_len, u8 clear_ssid);
-
-int lbs_scan_networks(struct lbs_private *priv,
- const struct lbs_ioctl_user_scan_cfg *puserscanin,
- int full_scan);
-
-struct ifreq;
+ u8 ssid_len);
-struct iw_point;
-struct iw_param;
-struct iw_request_info;
int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra);
+ union iwreq_data *wrqu, char *extra);
void lbs_scan_worker(struct work_struct *work);