P2P: Enable 40 MHz support for autonomous P2P group addition
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>
Wed, 15 Aug 2012 19:53:01 +0000 (22:53 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 15 Aug 2012 19:53:01 +0000 (22:53 +0300)
Add optional "ht40" argument for p2p_group_add command to enable 40 MHz
in 5GHz band. This configures the secondary channel, when HT support is
enabled and if the HW supports 40 MHz channel width.

Signed-hostap: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>

src/p2p/p2p.h
wpa_supplicant/ap.c
wpa_supplicant/config_ssid.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers_p2p.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h
wpa_supplicant/wpa_cli.c

index 7e47270..90152b8 100644 (file)
@@ -75,6 +75,8 @@ struct p2p_go_neg_results {
         */
        int freq;
 
+       int ht40;
+
        /**
         * ssid - SSID of the group
         */
index 948e2e4..19b1069 100644 (file)
@@ -99,6 +99,18 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 
                if (!no_ht && mode && mode->ht_capab) {
                        conf->ieee80211n = 1;
+#ifdef CONFIG_P2P
+                       if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
+                           (mode->ht_capab &
+                            HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
+                           ssid->ht40)
+                               conf->secondary_channel =
+                                       wpas_p2p_get_ht40_mode(wpa_s, mode,
+                                                              conf->channel);
+                       if (conf->secondary_channel)
+                               conf->ht_capab |=
+                                       HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+#endif /* CONFIG_P2P */
 
                        /*
                         * white-list capabilities that won't cause issues
index f4d551d..476a984 100644 (file)
@@ -364,6 +364,8 @@ struct wpa_ssid {
         */
        int frequency;
 
+       int ht40;
+
        /**
         * wpa_ptk_rekey - Maximum lifetime for PTK in seconds
         *
index 8d9b447..08cf813 100644 (file)
@@ -3482,7 +3482,7 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
 
 
 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
-                                        char *cmd, int freq)
+                                        char *cmd, int freq, int ht40)
 {
        int id;
        struct wpa_ssid *ssid;
@@ -3496,26 +3496,31 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
-       return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
+       return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40);
 }
 
 
 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
 {
-       int freq = 0;
+       int freq = 0, ht40;
        char *pos;
 
        pos = os_strstr(cmd, "freq=");
        if (pos)
                freq = atoi(pos + 5);
 
+       ht40 = os_strstr(cmd, "ht40") != NULL;
+
        if (os_strncmp(cmd, "persistent=", 11) == 0)
-               return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
+               return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
+                                                    ht40);
        if (os_strcmp(cmd, "persistent") == 0 ||
            os_strncmp(cmd, "persistent ", 11) == 0)
-               return wpas_p2p_group_add(wpa_s, 1, freq);
+               return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
        if (os_strncmp(cmd, "freq=", 5) == 0)
-               return wpas_p2p_group_add(wpa_s, 0, freq);
+               return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
+       if (ht40)
+               return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
 
        wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
                   cmd);
@@ -4313,7 +4318,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpas_p2p_group_remove(wpa_s, buf + 17))
                        reply_len = -1;
        } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
-               if (wpas_p2p_group_add(wpa_s, 0, 0))
+               if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
                        reply_len = -1;
        } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
                if (p2p_ctrl_group_add(wpa_s, buf + 14))
index 3d31c89..f19e0b6 100644 (file)
@@ -346,13 +346,13 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
                if (ssid == NULL || ssid->disabled != 2)
                        goto inv_args;
 
-               if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq)) {
+               if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0)) {
                        reply = wpas_dbus_error_unknown_error(
                                message,
                                "Failed to reinvoke a persistent group");
                        goto out;
                }
-       } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq))
+       } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0))
                goto inv_args;
 
 out:
index 42d758e..e2fc9fb 100644 (file)
@@ -819,6 +819,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
        ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION :
                WPAS_MODE_P2P_GO;
        ssid->frequency = params->freq;
+       ssid->ht40 = params->ht40;
        ssid->ssid = os_zalloc(params->ssid_len + 1);
        if (ssid->ssid) {
                os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
@@ -2042,7 +2043,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
                           MAC2STR(sa), op_freq);
                if (s) {
                        wpas_p2p_group_add_persistent(
-                               wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0);
+                               wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0, 0);
                } else if (bssid) {
                        wpas_p2p_join(wpa_s, bssid, go_dev_addr,
                                      wpa_s->p2p_wps_method, 0);
@@ -2109,7 +2110,7 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid)
        }
 
        wpas_p2p_group_add_persistent(wpa_s, ssid,
-                                     ssid->mode == WPAS_MODE_P2P_GO, 0);
+                                     ssid->mode == WPAS_MODE_P2P_GO, 0, 0);
 }
 
 
@@ -2331,6 +2332,32 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 }
 
 
+int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
+                          struct hostapd_hw_modes *mode, u8 channel)
+{
+       int op, ret;
+
+       for (op = 0; op_class[op].op_class; op++) {
+               struct p2p_oper_class_map *o = &op_class[op];
+               u8 ch;
+
+               for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
+                       if (o->mode != HOSTAPD_MODE_IEEE80211A ||
+                           o->bw == BW20 || ch != channel)
+                               continue;
+                       ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
+                       if (ret < 0)
+                               continue;
+                       else if (ret > 0)
+                               return (o->bw == BW40MINUS) ? -1 : 1;
+                       else
+                               return 0;
+               }
+       }
+       return 0;
+}
+
+
 static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
                        size_t buf_len)
 {
@@ -3400,13 +3427,14 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
 
 static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
                                   struct p2p_go_neg_results *params,
-                                  int freq)
+                                  int freq, int ht40)
 {
        u8 bssid[ETH_ALEN];
        int res;
 
        os_memset(params, 0, sizeof(*params));
        params->role_go = 1;
+       params->ht40 = ht40;
        if (freq) {
                wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
                           "frequency %d MHz", freq);
@@ -3518,7 +3546,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
  * i.e., without using Group Owner Negotiation.
  */
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
-                      int freq)
+                      int freq, int ht40)
 {
        struct p2p_go_neg_results params;
        unsigned int r;
@@ -3576,7 +3604,7 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
                return -1;
        }
 
-       if (wpas_p2p_init_go_params(wpa_s, &params, freq))
+       if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40))
                return -1;
        if (params.freq &&
            !p2p_supported_freq(wpa_s->global->p2p, params.freq)) {
@@ -3643,7 +3671,7 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
 
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                                  struct wpa_ssid *ssid, int addr_allocated,
-                                 int freq)
+                                 int freq, int ht40)
 {
        struct p2p_go_neg_results params;
        int go = 0;
@@ -3669,7 +3697,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
        if (ssid->mode != WPAS_MODE_P2P_GO)
                return -1;
 
-       if (wpas_p2p_init_go_params(wpa_s, &params, freq))
+       if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40))
                return -1;
 
        params.role_go = 1;
index e2fe259..744d538 100644 (file)
@@ -28,10 +28,10 @@ void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
                                          unsigned int freq);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
-                      int freq);
+                      int freq, int ht40);
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                                  struct wpa_ssid *ssid, int addr_allocated,
-                                 int freq);
+                                 int freq, int ht40);
 struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
                                       struct wpa_ssid *ssid);
 void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
@@ -141,5 +141,7 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
 void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
                                       const u8 *addr);
 int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
+int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
+                          struct hostapd_hw_modes *mode, u8 channel);
 
 #endif /* P2P_SUPPLICANT_H */
index e05dba5..85a7443 100644 (file)
@@ -2368,7 +2368,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
          "<ifname> = remove P2P group interface (terminate group if GO)" },
        { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
-         "= add a new P2P group (local end as GO)" },
+         "[ht40] = add a new P2P group (local end as GO)" },
        { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
          "<addr> <method> = request provisioning discovery" },
        { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,