]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P2: Set P2P mode (R1 vs. R2) in the driver
authorShivani Baranwal <quic_shivbara@quicinc.com>
Sat, 31 Aug 2024 16:51:26 +0000 (22:21 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 25 Nov 2024 21:21:59 +0000 (23:21 +0200)
Add support to set P2P mode in which P2P interface should be brought up.
It has Wi-Fi Direct R1 only mode, Wi-Fi Direct R2 only mode, and P2P
connection compatibility mode which support both R1 and R2. PCC mode is
applicable only for the Group Owner.

For now, this can be configured only with a QCA vendor command.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
src/drivers/driver.h
src/drivers/driver_bsd.c
src/drivers/driver_nl80211.c
wpa_supplicant/driver_i.h

index 3f650c5578ad00c2d8f6b10bbb31ec0a785a7695..a612f8cd2631d3c691593097e99034ac1ee92c1a 100644 (file)
@@ -3493,12 +3493,15 @@ struct wpa_driver_ops {
         * e.g., wpa_supplicant_event()
         * @ifname: interface name, e.g., wlan0
         * @global_priv: private driver global data from global_init()
+        * @p2p_mode: P2P mode for a GO (not applicable for other interface
+        *      types)
         * Returns: Pointer to private data, %NULL on failure
         *
         * This function can be used instead of init() if the driver wrapper
         * uses global data.
         */
-       void * (*init2)(void *ctx, const char *ifname, void *global_priv);
+       void * (*init2)(void *ctx, const char *ifname, void *global_priv,
+                       enum wpa_p2p_mode p2p_mode);
 
        /**
         * get_interfaces - Get information about available interfaces
index 82d8a0186c57615b5f460fd31f690523542a182f..0979fc5dddc531f9ed3f6d0ffdf2f139ed77710d 100644 (file)
@@ -998,7 +998,8 @@ handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
 }
 
 static void *
-bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
+bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params,
+        enum wpa_p2p_mode p2p_mode)
 {
        struct bsd_driver_data *drv;
 
index 3f9789df3745f84df8decfadb341068a390f89b1..b26d1c12156de7f5e9517f5f92d1abdd5445bac8 100644 (file)
@@ -165,7 +165,8 @@ static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
 static int
 wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
                                   const u8 *set_addr, int first,
-                                  const char *driver_params);
+                                  const char *driver_params,
+                                  enum wpa_p2p_mode p2p_mode);
 static int nl80211_send_frame_cmd(struct i802_bss *bss,
                                  unsigned int freq, unsigned int wait,
                                  const u8 *buf, size_t buf_len,
@@ -1216,7 +1217,8 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
                nl80211_check_global(drv->global);
                wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
                           "interface");
-               if (wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL) < 0)
+               if (wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL,
+                                                      WPA_P2P_MODE_WFD_R1) < 0)
                        return -1;
                return 1;
        }
@@ -2284,7 +2286,8 @@ wpa_driver_nl80211_drv_init_rfkill(struct wpa_driver_nl80211_data *drv)
 static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
                                          void *global_priv, int hostapd,
                                          const u8 *set_addr,
-                                         const char *driver_params)
+                                         const char *driver_params,
+                                         enum wpa_p2p_mode p2p_mode)
 {
        struct wpa_driver_nl80211_data *drv;
        struct i802_bss *bss;
@@ -2347,7 +2350,8 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
        if (nl80211_init_bss(bss))
                goto failed;
 
-       if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
+       if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params,
+                                              p2p_mode))
                goto failed;
 
        if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS) {
@@ -2410,10 +2414,11 @@ failed:
  * Returns: Pointer to private data, %NULL on failure
  */
 static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
-                                     void *global_priv)
+                                     void *global_priv,
+                                     enum wpa_p2p_mode p2p_mode)
 {
        return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL,
-                                          NULL);
+                                          NULL, p2p_mode);
 }
 
 
@@ -2973,10 +2978,67 @@ static void qca_vendor_test(struct wpa_driver_nl80211_data *drv)
 }
 
 
+#ifdef CONFIG_DRIVER_NL80211_QCA
+static int nl80211_set_p2p_mode(void *priv, enum wpa_p2p_mode mode)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       struct nl_msg *msg;
+       struct nlattr *container;
+       int ret;
+       enum qca_wlan_vendor_p2p_mode drv_mode;
+
+       wpa_printf(MSG_DEBUG, "nl80211: Set P2P mode: %d", mode);
+
+       switch (mode) {
+       case WPA_P2P_MODE_WFD_R1:
+               drv_mode = QCA_P2P_MODE_WFD_R1;
+               break;
+       case WPA_P2P_MODE_WFD_R2:
+               drv_mode = QCA_P2P_MODE_WFD_R2;
+               break;
+       case WPA_P2P_MODE_WFD_PCC:
+               drv_mode = QCA_P2P_MODE_WFD_PCC;
+               break;
+       default:
+               return -1;
+       }
+
+       msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+       if (!msg ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+                       QCA_NL80211_VENDOR_SUBCMD_SET_P2P_MODE))
+               goto fail;
+
+       container = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+       if (!container)
+               goto fail;
+
+       if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_CONFIG, drv_mode))
+               goto fail;
+
+       nla_nest_end(msg, container);
+
+       ret = send_and_recv_cmd(drv, msg);
+       if (ret)
+               wpa_printf(MSG_ERROR,
+                          "nl80211: Failed to set P2P Mode: ret=%d (%s)",
+                          ret, strerror(-ret));
+       return ret;
+
+fail:
+       nlmsg_free(msg);
+       return -1;
+}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
+
 static int
 wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
                                   const u8 *set_addr, int first,
-                                  const char *driver_params)
+                                  const char *driver_params,
+                                  enum wpa_p2p_mode p2p_mode)
 {
        struct i802_bss *bss = drv->first_bss;
        int send_rfkill_event = 0;
@@ -3035,6 +3097,11 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 
        wpa_driver_nl80211_drv_init_rfkill(drv);
 
+#ifdef CONFIG_DRIVER_NL80211_QCA
+       if (nlmode == NL80211_IFTYPE_P2P_GO)
+               nl80211_set_p2p_mode(bss, p2p_mode);
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
        if (!rfkill_is_blocked(drv->rfkill)) {
                int ret = i802_set_iface_flags(bss, 1);
                if (ret) {
@@ -8713,7 +8780,8 @@ static void *i802_init(struct hostapd_data *hapd,
 
        bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
                                          params->global_priv, 1,
-                                         params->bssid, params->driver_params);
+                                         params->bssid, params->driver_params,
+                                         WPA_P2P_MODE_WFD_R1);
        if (bss == NULL)
                return NULL;
 
index cd74e31d34abf5747533538a3ae9b95b75755b7f..43847cf4ab2ee2e4d75551dd1793b16431d3ce77 100644 (file)
 static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,
                                  const char *ifname)
 {
-       if (wpa_s->driver->init2)
+       if (wpa_s->driver->init2) {
+               enum wpa_p2p_mode p2p_mode = WPA_P2P_MODE_WFD_R1;
+
+#ifdef CONFIG_P2P
+               p2p_mode = wpa_s->p2p_mode;
+#endif /* CONFIG_P2P */
+
                return wpa_s->driver->init2(wpa_s, ifname,
-                                           wpa_s->global_drv_priv);
+                                           wpa_s->global_drv_priv,
+                                           p2p_mode);
+       }
        if (wpa_s->driver->init) {
                return wpa_s->driver->init(wpa_s, ifname);
        }