Skip to content
Browse files

nl80211/cfg80211: add intermediate scan result event (INTERNAL)

Adding intermediate scan result event by exposing new
NL80211_CMD_IM_SCAN_RESULT event, which will contain
NL80211_BSS_BSSID to specify the BSSID of received scan result and
NL80211_BSS_SIGNAL_MBM to indicate signal strength.

This event might be optionally enabled during
NL80211_CMD_TRIGGER_SCAN, with NL80211_ATTR_IM_SCAN_RESULT
flag attribute.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
  • Loading branch information...
1 parent 0d4f0e0 commit 539096f5607b3c41e7f18b1b7368e553254fa824 @victorgld victorgld committed with ariknem May 16, 2012
Showing with 140 additions and 0 deletions.
  1. +17 −0 include/linux/nl80211.h
  2. +10 −0 include/net/cfg80211.h
  3. +10 −0 net/wireless/core.h
  4. +54 −0 net/wireless/nl80211.c
  5. +3 −0 net/wireless/nl80211.h
  6. +43 −0 net/wireless/scan.c
  7. +3 −0 net/wireless/util.c
View
17 include/linux/nl80211.h
@@ -570,6 +570,14 @@
* event, partial scan results will be available. Returns -ENOENT
* if scan is not running.
*
+ * @NL80211_CMD_IM_SCAN_RESULT: Intermediate scan result notification event,
+ * this event could be enabled with @NL80211_ATTR_IM_SCAN_RESULT
+ * flag during @NL80211_CMD_TRIGGER_SCAN. This event contains
+ * %NL80211_BSS_BSSID which is used to specify the BSSID of received
+ * scan result and %NL80211_BSS_SIGNAL_MBM to indicate signal strength.
+ * On reception of this notification, userspace may decide to stop earlier
+ * currently running scan with (@NL80211_CMD_SCAN_CANCEL).
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -715,6 +723,8 @@ enum nl80211_commands {
NL80211_CMD_SCAN_CANCEL,
+ NL80211_CMD_IM_SCAN_RESULT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1249,6 +1259,11 @@ enum nl80211_commands {
* @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
* or 0 to disable background scan.
*
+ * @%NL80211_ATTR_IM_SCAN_RESULT: Flag attribute to enable intermediate
+ * scan result notification event (%NL80211_CMD_IM_SCAN_RESULT)
+ * for the %NL80211_CMD_TRIGGER_SCAN command.
+ * When set: will notify on each new scan result in the cache.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1500,6 +1515,8 @@ enum nl80211_attrs {
NL80211_ATTR_BG_SCAN_PERIOD,
+ NL80211_ATTR_IM_SCAN_RESULT,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
View
10 include/net/cfg80211.h
@@ -2803,6 +2803,16 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy);
void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
/**
+ * cfg80211_send_intermediate_result - inform userspace about new
+ * scan result.
+ *
+ * @dev: network device
+ * @cbss: bss info to report.
+ */
+void cfg80211_send_intermediate_result(struct net_device *dev,
+ struct cfg80211_bss *cbss);
+
+/**
* cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame
*
* @wiphy: the wiphy reporting the BSS
View
10 net/wireless/core.h
@@ -86,6 +86,9 @@ struct cfg80211_registered_device {
struct cfg80211_wowlan *wowlan;
+ /* intermediate scan result pid of sender */
+ u32 im_scan_result_snd_pid;
+
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -218,6 +221,7 @@ enum cfg80211_event_type {
EVENT_ROAMED,
EVENT_DISCONNECTED,
EVENT_IBSS_JOINED,
+ EVENT_IM_SCAN_RESULT,
};
struct cfg80211_event {
@@ -248,6 +252,10 @@ struct cfg80211_event {
struct {
u8 bssid[ETH_ALEN];
} ij;
+ struct {
+ u8 bssid[ETH_ALEN];
+ s32 signal;
+ } im;
};
};
@@ -424,6 +432,8 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak);
void __cfg80211_sched_scan_results(struct work_struct *wk);
int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
bool driver_initiated);
+void __cfg80211_send_intermediate_result(struct net_device *dev,
+ struct cfg80211_event *ev);
int cfg80211_scan_cancel(struct cfg80211_registered_device *rdev);
void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
View
54 net/wireless/nl80211.c
@@ -294,6 +294,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [NL80211_ATTR_IM_SCAN_RESULT] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -4172,6 +4173,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->ie_len);
}
+ if (info->attrs[NL80211_ATTR_IM_SCAN_RESULT])
+ rdev->im_scan_result_snd_pid = info->snd_pid;
+ else
+ rdev->im_scan_result_snd_pid = 0;
+
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
if (wiphy->bands[i])
request->rates[i] =
@@ -7377,6 +7383,34 @@ nl80211_send_sched_scan_msg(struct sk_buff *msg,
return -EMSGSIZE;
}
+static int nl80211_send_intermediate_msg(struct sk_buff *msg,
+ struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ u32 pid, u32 seq, int flags,
+ struct cfg80211_event *ev, u32 cmd)
+{
+ void *hdr;
+
+ hdr = nl80211hdr_put(msg, pid, seq, flags, cmd);
+ if (!hdr)
+ return -1;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+ nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, ev->im.signal))
+ goto nla_put_failure;
+
+ if (!is_zero_ether_addr(ev->im.bssid))
+ if (nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, ev->im.bssid))
+ goto nla_put_failure;
+
+ return genlmsg_end(msg, hdr);
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return -EMSGSIZE;
+}
+
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
struct net_device *netdev)
{
@@ -7434,6 +7468,26 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
+void nl80211_send_intermediate_result(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ struct cfg80211_event *ev)
+{
+ struct sk_buff *msg;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ if (nl80211_send_intermediate_msg(msg, rdev, netdev, 0, 0, 0, ev,
+ NL80211_CMD_IM_SCAN_RESULT) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
+ rdev->im_scan_result_snd_pid);
+}
+
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
struct net_device *netdev)
{
View
3 net/wireless/nl80211.h
@@ -12,6 +12,9 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
+void nl80211_send_intermediate_result(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ struct cfg80211_event *ev);
void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
struct net_device *netdev, u32 cmd);
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
View
43 net/wireless/scan.c
@@ -155,6 +155,49 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
return err;
}
+void __cfg80211_send_intermediate_result(struct net_device *dev,
+ struct cfg80211_event *ev)
+{
+ struct wireless_dev *wdev;
+ struct cfg80211_registered_device *rdev;
+
+ if (!dev)
+ return;
+
+ wdev = dev->ieee80211_ptr;
+ rdev = wiphy_to_dev(wdev->wiphy);
+
+ if (rdev->scan_req)
+ nl80211_send_intermediate_result(rdev, dev, ev);
+}
+
+void cfg80211_send_intermediate_result(struct net_device *dev,
+ struct cfg80211_bss *cbss)
+{
+ struct cfg80211_event *ev;
+ unsigned long flags;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+
+ if (!rdev->im_scan_result_snd_pid || !rdev->scan_req || !cbss)
+ return;
+
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev)
+ return;
+
+ ev->type = EVENT_IM_SCAN_RESULT;
+ ev->im.signal = cbss->signal;
+ if (cbss->bssid)
+ memcpy(ev->im.bssid, cbss->bssid, ETH_ALEN);
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ list_add_tail(&ev->list, &wdev->event_list);
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+ queue_work(cfg80211_wq, &rdev->event_work);
+}
+EXPORT_SYMBOL(cfg80211_send_intermediate_result);
+
int cfg80211_scan_cancel(struct cfg80211_registered_device *rdev)
{
struct net_device *dev;
View
3 net/wireless/util.c
@@ -774,6 +774,9 @@ static void cfg80211_process_wdev_events(struct wireless_dev *wdev)
case EVENT_IBSS_JOINED:
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
break;
+ case EVENT_IM_SCAN_RESULT:
+ __cfg80211_send_intermediate_result(wdev->netdev, ev);
+ break;
}
wdev_unlock(wdev);

0 comments on commit 539096f

Please sign in to comment.
Something went wrong with that request. Please try again.