diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 27e883126..7f1f526c2 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -481,6 +481,14 @@ struct wpa_driver_associate_params { * p2p - Whether this connection is a P2P group */ int p2p; + + /** + * uapsd - UAPSD parameters for the network + * -1 = do not change defaults + * AP mode: 1 = enabled, 0 = disabled + * STA mode: bits 0..3 UAPSD enabled for VO,VI,BK,BE + */ + int uapsd; }; /** diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 8d173ffac..dd41c205a 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -296,6 +296,11 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, params.p2p = 1; #endif /* CONFIG_P2P */ + if (wpa_s->parent->set_ap_uapsd) + params.uapsd = wpa_s->parent->ap_uapsd; + else + params.uapsd = -1; + if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); return -1; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 739b9e903..4357adada 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2479,6 +2479,55 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) if (os_strcmp(cmd, "cross_connect") == 0) return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); + if (os_strcmp(cmd, "go_apsd") == 0) { + if (os_strcmp(param, "disable") == 0) + wpa_s->set_ap_uapsd = 0; + else { + wpa_s->set_ap_uapsd = 1; + wpa_s->ap_uapsd = atoi(param); + } + return 0; + } + + if (os_strcmp(cmd, "client_apsd") == 0) { + if (os_strcmp(param, "disable") == 0) + wpa_s->set_sta_uapsd = 0; + else { + int be, bk, vi, vo; + char *pos; + /* format: BE,BK,VI,VO;max SP Length */ + be = atoi(param); + pos = os_strchr(param, ','); + if (pos == NULL) + return -1; + pos++; + bk = atoi(pos); + pos = os_strchr(pos, ','); + if (pos == NULL) + return -1; + pos++; + vi = atoi(pos); + pos = os_strchr(pos, ','); + if (pos == NULL) + return -1; + pos++; + vo = atoi(pos); + /* ignore max SP Length for now */ + + wpa_s->set_sta_uapsd = 1; + wpa_s->sta_uapsd = 0; + if (be) + wpa_s->sta_uapsd |= BIT(0); + if (bk) + wpa_s->sta_uapsd |= BIT(1); + if (vi) + wpa_s->sta_uapsd |= BIT(2); + if (vo) + wpa_s->sta_uapsd |= BIT(3); + } + return 0; + } + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", cmd); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 23ffe800c..985c9001c 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -386,6 +386,11 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)) params.p2p = 1; + if (wpa_s->parent->set_sta_uapsd) + params.uapsd = wpa_s->parent->sta_uapsd; + else + params.uapsd = -1; + if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " "failed"); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 8536b4558..bbfa29166 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1283,6 +1283,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, params.p2p = 1; #endif /* CONFIG_P2P */ + if (wpa_s->parent->set_sta_uapsd) + params.uapsd = wpa_s->parent->sta_uapsd; + else + params.uapsd = -1; + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) ret = ieee80211_sta_associate(wpa_s, ¶ms); else diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index fb1b955ff..ca3a27334 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -424,6 +424,11 @@ struct wpa_supplicant { struct ibss_rsn *ibss_rsn; + int set_sta_uapsd; + int sta_uapsd; + int set_ap_uapsd; + int ap_uapsd; + #ifdef CONFIG_SME struct { u8 ssid[32];