161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/*
261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * wpa_supplicant - Wi-Fi Display
361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2011, Atheros Communications, Inc.
461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * See README for more details.
861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */
961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "includes.h"
1161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "common.h"
1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "p2p/p2p.h"
1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "common/ieee802_11_defs.h"
1561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "wpa_supplicant_i.h"
1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "wifi_display.h"
1761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wifi_display_init(struct wpa_global *global)
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global->wifi_display = 1;
2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wifi_display_deinit(struct wpa_global *global)
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int i;
2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(global->wfd_subelem[i]);
3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		global->wfd_subelem[i] = NULL;
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wifi_display_update_wfd_ie(struct wpa_global *global)
3761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
3861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *ie, *buf;
3961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len, plen;
4061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WFD: Update WFD IE");
4261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!global->wifi_display) {
4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display disabled - do not "
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   "include WFD IE");
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_beacon(global->p2p, NULL);
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_probe_req(global->p2p, NULL);
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_probe_resp(global->p2p, NULL);
4961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_assoc_req(global->p2p, NULL);
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_invitation(global->p2p, NULL);
5161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_prov_disc_req(global->p2p, NULL);
5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_prov_disc_resp(global->p2p, NULL);
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_ie_go_neg(global->p2p, NULL);
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_dev_info(global->p2p, NULL);
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_assoc_bssid(global->p2p, NULL);
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_wfd_coupled_sink_info(global->p2p, NULL);
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_dev_info(global->p2p,
6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			     global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_assoc_bssid(
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		global->p2p,
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]);
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_coupled_sink_info(
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		global->p2p, global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]);
6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/*
6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * WFD IE is included in number of management frames. Two different
7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * sets of subelements are included depending on the frame:
7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 *
7261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * Beacon, (Re)Association Request, GO Negotiation Req/Resp/Conf,
7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * Provision Discovery Req:
7461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * WFD Device Info
7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Associated BSSID]
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Coupled Sink Info]
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 *
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * Probe Request:
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * WFD Device Info
8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Associated BSSID]
8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Coupled Sink Info]
8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [WFD Extended Capability]
8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 *
8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * Probe Response:
8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * WFD Device Info
8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Associated BSSID]
8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Coupled Sink Info]
8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [WFD Extended Capability]
8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [WFD Session Info]
9061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 *
9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * (Re)Association Response, P2P Invitation Req/Resp,
9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * Provision Discovery Resp:
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * WFD Device Info
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Associated BSSID]
9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [Coupled Sink Info]
9661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * [WFD Session Info]
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 */
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = 0;
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(global->wfd_subelem[
10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  WFD_SUBELEM_DEVICE_INFO]);
10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(global->wfd_subelem[
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  WFD_SUBELEM_ASSOCIATED_BSSID]);
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK])
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(global->wfd_subelem[
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  WFD_SUBELEM_COUPLED_SINK]);
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(global->wfd_subelem[
11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  WFD_SUBELEM_SESSION_INFO]);
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB])
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]);
11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(len);
11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (buf == NULL)
11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf,
11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, global->wfd_subelem[
12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				       WFD_SUBELEM_ASSOCIATED_BSSID]);
12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK])
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf,
12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]);
12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Beacon", ie);
12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_beacon(global->p2p, ie);
13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for (Re)Association Request",
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			ie);
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_assoc_req(global->p2p, ie);
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for GO Negotiation", ie);
13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_go_neg(global->p2p, ie);
13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery "
14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"Request", ie);
14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_prov_disc_req(global->p2p, ie);
14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	plen = buf->used;
14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB])
14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf,
14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]);
14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Request", ie);
15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_probe_req(global->p2p, ie);
15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf,
15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]);
15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Response", ie);
15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_probe_resp(global->p2p, ie);
16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* Remove WFD Extended Capability from buffer */
16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf->used = plen;
16361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
16461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf,
16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]);
16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
16761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for P2P Invitation", ie);
16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_invitation(global->p2p, ie);
17061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wifi_display_encaps(buf);
17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery "
17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"Response", ie);
17461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_wfd_ie_prov_disc_resp(global->p2p, ie);
17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(buf);
17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wifi_display_enable(struct wpa_global *global, int enabled)
18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display %s",
18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		   enabled ? "enabled" : "disabled");
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global->wifi_display = enabled;
18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wifi_display_update_wfd_ie(global);
18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wifi_display_subelem_set(struct wpa_global *global, char *cmd)
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *pos;
19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int subelem;
19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len;
19661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *e;
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = os_strchr(cmd, ' ');
19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (pos == NULL)
20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	*pos++ = '\0';
20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	subelem = atoi(cmd);
20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS)
20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = os_strlen(pos);
20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (len & 1)
20861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len /= 2;
21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (len == 0) {
21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		/* Clear subelement */
21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		e = NULL;
21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WFD: Clear subelement %d", subelem);
21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
21661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		e = wpabuf_alloc(1 + len);
21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (e == NULL)
21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_u8(e, subelem);
22061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (hexstr2bin(pos, wpabuf_put(e, len), len) < 0) {
22161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpabuf_free(e);
22261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WFD: Set subelement %d", subelem);
22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(global->wfd_subelem[subelem]);
22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global->wfd_subelem[subelem] = e;
22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wifi_display_update_wfd_ie(global);
23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wifi_display_subelem_get(struct wpa_global *global, char *cmd,
23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			     char *buf, size_t buflen)
23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int subelem;
23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	subelem = atoi(cmd);
24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS)
24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (global->wfd_subelem[subelem] == NULL)
24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return wpa_snprintf_hex(buf, buflen,
24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wpabuf_head_u8(global->wfd_subelem[subelem]) +
24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				1,
25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wpabuf_len(global->wfd_subelem[subelem]) - 1);
25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
252