Patchwork [07/20] driver: nl80211: allow Android P2P functionality

login
register
mail settings
Submitter Arend van Spriel
Date May 16, 2013, 1:28 p.m.
Message ID <1368710915-32176-8-git-send-email-arend@broadcom.com>
Download mbox | patch
Permalink /patch/244316/
State Changes Requested
Headers show

Comments

Arend van Spriel - May 16, 2013, 1:28 p.m.
From: Johannes Berg <johannes.berg@intel.com>

To support Android the kernel may have a "p2p0" netdev for a
P2P-Device even though this isn't very useful, but Android
requires a netdev. To support this in the supplicant, if the
interface mode is P2P_DEVICE, re-set it to the same instead
of STATION mode.

Note that this is only possible with a kernel that creates a
netdev for the P2P-Device wdev.

Signed-hostap: Johannes Berg <johannes.berg@intel.com>
---
 src/drivers/driver_nl80211.c |   50 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 247ba81..f185f71 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -543,6 +543,7 @@  static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
 
 struct wiphy_idx_data {
 	int wiphy_idx;
+	enum nl80211_iftype nlmode;
 };
 
 
@@ -558,6 +559,9 @@  static int netdev_info_handler(struct nl_msg *msg, void *arg)
 	if (tb[NL80211_ATTR_WIPHY])
 		info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
 
+	if (tb[NL80211_ATTR_IFTYPE])
+		info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
+
 	return NL_SKIP;
 }
 
@@ -586,6 +590,30 @@  nla_put_failure:
 }
 
 
+static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
+{
+	struct nl_msg *msg;
+	struct wiphy_idx_data data = {
+		.wiphy_idx = -1,
+	};
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
+		return data.nlmode;
+	msg = NULL;
+nla_put_failure:
+	nlmsg_free(msg);
+	return NL80211_IFTYPE_UNSPECIFIED;
+}
+
+
 static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
 				    struct nl80211_wiphy_data *w)
 {
@@ -3720,11 +3748,23 @@  wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
 	 * dynamically added interface (e.g., P2P) that was already configured
 	 * with proper iftype.
 	 */
-	if (drv->ifindex != drv->global->if_add_ifindex &&
-	    wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
-		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
-			   "use managed mode");
-		return -1;
+	if (drv->ifindex != drv->global->if_add_ifindex) {
+		enum nl80211_iftype nlmode;
+
+		nlmode = nl80211_get_ifmode(bss);
+		if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
+			nlmode = NL80211_IFTYPE_STATION;
+
+		if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
+			wpa_printf(MSG_ERROR, "nl80211: Could not configure "
+				   "driver to use %s mode",
+				   nlmode == NL80211_IFTYPE_STATION ?
+					"managed" : "P2P-Device");
+			return -1;
+		}
+
+		/* always use managed mode internally, even for P2P-Device */
+		drv->nlmode = NL80211_IFTYPE_STATION;
 	}
 
 	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {