QCA vendor command support to set band to driver
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
index 07b7038..41f9090 100644 (file)
@@ -286,6 +286,30 @@ static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
 }
 
 
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+{
+       union wpa_event_data event;
+
+       if (os_strcmp(band, "AUTO") == 0)
+               wpa_s->setband = WPA_SETBAND_AUTO;
+       else if (os_strcmp(band, "5G") == 0)
+               wpa_s->setband = WPA_SETBAND_5G;
+       else if (os_strcmp(band, "2G") == 0)
+               wpa_s->setband = WPA_SETBAND_2G;
+       else
+               return -1;
+
+       if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+               os_memset(&event, 0, sizeof(event));
+               event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+               event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+               wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
+       }
+
+       return 0;
+}
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                                         char *cmd)
 {
@@ -449,14 +473,7 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                ret = wpas_ctrl_set_blob(wpa_s, value);
 #endif /* CONFIG_NO_CONFIG_BLOBS */
        } else if (os_strcasecmp(cmd, "setband") == 0) {
-               if (os_strcmp(value, "AUTO") == 0)
-                       wpa_s->setband = WPA_SETBAND_AUTO;
-               else if (os_strcmp(value, "5G") == 0)
-                       wpa_s->setband = WPA_SETBAND_5G;
-               else if (os_strcmp(value, "2G") == 0)
-                       wpa_s->setband = WPA_SETBAND_2G;
-               else
-                       ret = -1;
+               ret = wpas_ctrl_set_band(wpa_s, value);
        } else {
                value[-1] = '=';
                ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -4652,6 +4669,48 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
 }
 
 
+static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
+{
+       const char *last = NULL;
+       const char *token;
+       long int token_len;
+       unsigned int i;
+
+       /* Expected predefined CPT names delimited by ':' */
+       for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
+               if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
+                       wpa_printf(MSG_ERROR,
+                                  "P2PS: CPT name list is too long, expected up to %d names",
+                                  P2PS_FEATURE_CAPAB_CPT_MAX);
+                       cpt[0] = 0;
+                       return -1;
+               }
+
+               token_len = last - token;
+
+               if (token_len  == 3 &&
+                   os_memcmp(token, "UDP", token_len) == 0) {
+                       cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+               } else if (token_len == 3 &&
+                          os_memcmp(token, "MAC", token_len) == 0) {
+                       cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
+               } else {
+                       wpa_printf(MSG_ERROR,
+                                  "P2PS: Unsupported CPT name '%s'", token);
+                       cpt[0] = 0;
+                       return -1;
+               }
+
+               if (isblank(*last)) {
+                       i++;
+                       break;
+               }
+       }
+       cpt[i] = 0;
+       return 0;
+}
+
+
 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
 {
        struct p2ps_provision *p2ps_prov;
@@ -4660,6 +4719,7 @@ static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
        char *info = NULL;
        u8 role = P2PS_SETUP_NONE;
        long long unsigned val;
+       int i;
 
        pos = os_strstr(cmd, "info=");
        if (pos) {
@@ -4718,6 +4778,18 @@ static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
        if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
                goto invalid_args;
 
+       pos = os_strstr(cmd, "cpt=");
+       if (pos) {
+               if (p2ps_ctrl_parse_cpt_priority(pos + 4,
+                                                p2ps_prov->cpt_priority))
+                       goto invalid_args;
+       } else {
+               p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+       }
+
+       for (i = 0; p2ps_prov->cpt_priority[i]; i++)
+               p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
+
        /* force conncap with tstCap (no sanity checks) */
        pos = os_strstr(cmd, "tstCap=");
        if (pos) {
@@ -5213,6 +5285,8 @@ static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
        char *adv_str;
        u32 auto_accept, adv_id, svc_state, config_methods;
        char *svc_info = NULL;
+       char *cpt_prio_str;
+       u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
 
        pos = os_strchr(cmd, ' ');
        if (pos == NULL)
@@ -5285,6 +5359,19 @@ static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
        if (pos != NULL)
                *pos++ = '\0';
 
+       cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
+       if (cpt_prio_str) {
+               pos = os_strchr(pos, ' ');
+               if (pos != NULL)
+                       *pos++ = '\0';
+
+               if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
+                       return -1;
+       } else {
+               cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+               cpt_prio[1] = 0;
+       }
+
        /* Service and Response Information are optional */
        if (pos && pos[0]) {
                size_t len;
@@ -5302,7 +5389,7 @@ static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
 
        return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
                                        (u8) svc_state, (u16) config_methods,
-                                       svc_info);
+                                       svc_info, cpt_prio);
 }
 
 
@@ -9194,6 +9281,10 @@ static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global,
        if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
                wpa_s = wpa_supplicant_get_iface(global, ifname);
                if (wpa_s) {
+                       if (wpa_s->fst) {
+                               wpa_printf(MSG_INFO, "FST: Already attached");
+                               return -1;
+                       }
                        fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
                        wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
                                                &iface_obj, &cfg);