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 1904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt#define WIFI_DISPLAY_SUBELEM_HEADER_LEN 3 2004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 2104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wifi_display_init(struct wpa_global *global) 2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wifi_display = 1; 2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wifi_display_deinit(struct wpa_global *global) 3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int i; 3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < MAX_WFD_SUBELEMS; i++) { 3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(global->wfd_subelem[i]); 3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[i] = NULL; 3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 3761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 3861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 39661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtstruct wpabuf * wifi_display_get_wfd_ie(struct wpa_global *global) 40661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{ 41661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct wpabuf *ie; 42661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt size_t len; 43661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt int i; 44661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 45661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (global->p2p == NULL) 46661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return NULL; 47661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 48661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt len = 0; 49661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt for (i = 0; i < MAX_WFD_SUBELEMS; i++) { 50661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (global->wfd_subelem[i]) 51661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt len += wpabuf_len(global->wfd_subelem[i]); 52661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 53661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 54661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ie = wpabuf_alloc(len); 55661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (ie == NULL) 56661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return NULL; 57661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 58661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt for (i = 0; i < MAX_WFD_SUBELEMS; i++) { 59661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (global->wfd_subelem[i]) 60661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpabuf_put_buf(ie, global->wfd_subelem[i]); 61661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 62661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 63661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return ie; 64661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt} 65661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 66661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wifi_display_update_wfd_ie(struct wpa_global *global) 6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *ie, *buf; 7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t len, plen; 7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 72ed003d2a93648e6201272d2fb8212cbc01085928Dmitry Shmidt if (global->p2p == NULL) 73ed003d2a93648e6201272d2fb8212cbc01085928Dmitry Shmidt return 0; 74ed003d2a93648e6201272d2fb8212cbc01085928Dmitry Shmidt 7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD: Update WFD IE"); 7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!global->wifi_display) { 7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display disabled - do not " 7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "include WFD IE"); 8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_beacon(global->p2p, NULL); 8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_probe_req(global->p2p, NULL); 8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_probe_resp(global->p2p, NULL); 8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_assoc_req(global->p2p, NULL); 8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_invitation(global->p2p, NULL); 8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_prov_disc_req(global->p2p, NULL); 8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_prov_disc_resp(global->p2p, NULL); 8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_go_neg(global->p2p, NULL); 8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_dev_info(global->p2p, NULL); 8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_assoc_bssid(global->p2p, NULL); 9061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_coupled_sink_info(global->p2p, NULL); 9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_dev_info(global->p2p, 9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]); 9661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_assoc_bssid( 9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->p2p, 9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]); 9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_coupled_sink_info( 10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->p2p, global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]); 10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * WFD IE is included in number of management frames. Two different 10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * sets of subelements are included depending on the frame: 10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * 10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Beacon, (Re)Association Request, GO Negotiation Req/Resp/Conf, 10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provision Discovery Req: 10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * WFD Device Info 10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Associated BSSID] 11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Coupled Sink Info] 11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * 11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Probe Request: 11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * WFD Device Info 11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Associated BSSID] 11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Coupled Sink Info] 11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [WFD Extended Capability] 11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * 11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Probe Response: 11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * WFD Device Info 12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Associated BSSID] 12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Coupled Sink Info] 12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [WFD Extended Capability] 12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [WFD Session Info] 12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * 12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * (Re)Association Response, P2P Invitation Req/Resp, 12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provision Discovery Resp: 12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * WFD Device Info 12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Associated BSSID] 12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [Coupled Sink Info] 13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * [WFD Session Info] 13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = 0; 13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]) 13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(global->wfd_subelem[ 13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WFD_SUBELEM_DEVICE_INFO]); 13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]) 13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(global->wfd_subelem[ 13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WFD_SUBELEM_ASSOCIATED_BSSID]); 13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]) 14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(global->wfd_subelem[ 14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WFD_SUBELEM_COUPLED_SINK]); 14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]) 14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(global->wfd_subelem[ 14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WFD_SUBELEM_SESSION_INFO]); 14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]) 14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]); 14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf = wpabuf_alloc(len); 14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (buf == NULL) 14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]) 15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, 15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]); 15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]) 15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, global->wfd_subelem[ 15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WFD_SUBELEM_ASSOCIATED_BSSID]); 15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]) 15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, 15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]); 16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Beacon", ie); 16361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_beacon(global->p2p, ie); 16461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for (Re)Association Request", 16761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie); 16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_assoc_req(global->p2p, ie); 16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 17061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for GO Negotiation", ie); 17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_go_neg(global->p2p, ie); 17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 17461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery " 17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Request", ie); 17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_prov_disc_req(global->p2p, ie); 17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plen = buf->used; 18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]) 18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, 18261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]); 18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Request", ie); 18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_probe_req(global->p2p, ie); 18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]) 18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, 19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]); 19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Response", ie); 19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_probe_resp(global->p2p, ie); 19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Remove WFD Extended Capability from buffer */ 19661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf->used = plen; 19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]) 19861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, 19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]); 20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for P2P Invitation", ie); 20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_invitation(global->p2p, ie); 20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wifi_display_encaps(buf); 20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery " 20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Response", ie); 20861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt p2p_set_wfd_ie_prov_disc_resp(global->p2p, ie); 20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(buf); 21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wifi_display_enable(struct wpa_global *global, int enabled) 21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display %s", 21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt enabled ? "enabled" : "disabled"); 22061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wifi_display = enabled; 22161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wifi_display_update_wfd_ie(global); 22261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wifi_display_subelem_set(struct wpa_global *global, char *cmd) 22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *pos; 22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int subelem; 22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t len; 23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *e; 23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = os_strchr(cmd, ' '); 23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos == NULL) 23461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 23561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *pos++ = '\0'; 23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem = atoi(cmd); 23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS) 23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = os_strlen(pos); 24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len & 1) 24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len /= 2; 24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len == 0) { 24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Clear subelement */ 24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt e = NULL; 24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD: Clear subelement %d", subelem); 24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt e = wpabuf_alloc(1 + len); 25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (e == NULL) 25261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(e, subelem); 25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hexstr2bin(pos, wpabuf_put(e, len), len) < 0) { 25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(e); 25661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 25761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 25861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD: Set subelement %d", subelem); 25961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 26061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(global->wfd_subelem[subelem]); 26261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt global->wfd_subelem[subelem] = e; 26361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wifi_display_update_wfd_ie(global); 26461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 269661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtint wifi_display_subelem_set_from_ies(struct wpa_global *global, 270661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct wpabuf *ie) 271661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{ 272661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt int subelements[MAX_WFD_SUBELEMS] = {}; 273661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt const u8 *pos, *end; 274661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt int len, subelem; 275661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct wpabuf *e; 276661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 277661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD IEs set: %p - %lu", 278661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ie, ie ? (unsigned long) wpabuf_len(ie) : 0); 279661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 280661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (ie == NULL || wpabuf_len(ie) < 6) 281661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return -1; 282661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 283661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos = wpabuf_head(ie); 284661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt end = pos + wpabuf_len(ie); 285661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 286661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt while (end > pos) { 287661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (pos + 3 > end) 288661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt break; 289661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 290661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt len = WPA_GET_BE16(pos + 1) + 3; 291661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 292661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD Sub-Element ID %d - len %d", 293661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt *pos, len - 3); 294661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 295661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (pos + len > end) 296661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt break; 297661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 298661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt subelem = *pos; 299661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (subelem < MAX_WFD_SUBELEMS && subelements[subelem] == 0) { 300661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt e = wpabuf_alloc_copy(pos, len); 301661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (e == NULL) 302661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return -1; 303661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 304661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpabuf_free(global->wfd_subelem[subelem]); 305661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt global->wfd_subelem[subelem] = e; 306661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt subelements[subelem] = 1; 307661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 308661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 309661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += len; 310661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 311661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 312661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt for (subelem = 0; subelem < MAX_WFD_SUBELEMS; subelem++) { 313661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (subelements[subelem] == 0) { 314661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpabuf_free(global->wfd_subelem[subelem]); 315661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt global->wfd_subelem[subelem] = NULL; 316661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 317661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 318661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 319661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return wifi_display_update_wfd_ie(global); 320661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt} 321661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 322661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 32361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wifi_display_subelem_get(struct wpa_global *global, char *cmd, 32461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *buf, size_t buflen) 32561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 32661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int subelem; 32761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 32861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem = atoi(cmd); 32961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS) 33061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 33161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 33261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (global->wfd_subelem[subelem] == NULL) 33361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 33461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 33561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return wpa_snprintf_hex(buf, buflen, 33661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_head_u8(global->wfd_subelem[subelem]) + 33761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1, 33861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_len(global->wfd_subelem[subelem]) - 1); 33961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 34004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 34104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 34204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidtchar * wifi_display_subelem_hex(const struct wpabuf *wfd_subelems, u8 id) 34304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt{ 34404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt char *subelem = NULL; 34504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt const u8 *buf; 34604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt size_t buflen; 34704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt size_t i = 0; 34804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt u16 elen; 34904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 35004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!wfd_subelems) 35104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return NULL; 35204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 35304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt buf = wpabuf_head_u8(wfd_subelems); 35404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!buf) 35504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return NULL; 35604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 35704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt buflen = wpabuf_len(wfd_subelems); 35804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 35904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt while (i + WIFI_DISPLAY_SUBELEM_HEADER_LEN < buflen) { 36004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt elen = WPA_GET_BE16(buf + i + 1); 361623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt if (i + WIFI_DISPLAY_SUBELEM_HEADER_LEN + elen > buflen) 362623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt break; /* truncated subelement */ 36304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 36404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (buf[i] == id) { 365c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt /* 366c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt * Limit explicitly to an arbitrary length to avoid 367c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt * unnecessarily large allocations. In practice, this 368c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt * is limited to maximum frame length anyway, so the 369c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt * maximum memory allocation here is not really that 370c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt * large. Anyway, the Wi-Fi Display subelements that 371c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt * are fetched with this function are even shorter. 372c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt */ 373c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (elen > 1000) 374c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt break; 37504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt subelem = os_zalloc(2 * elen + 1); 37604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!subelem) 37704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return NULL; 37804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_snprintf_hex(subelem, 2 * elen + 1, 37904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt buf + i + 38004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt WIFI_DISPLAY_SUBELEM_HEADER_LEN, 38104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt elen); 38204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt break; 38304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt } 38404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 38504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt i += elen + WIFI_DISPLAY_SUBELEM_HEADER_LEN; 38604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt } 38704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 38804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return subelem; 38904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt} 390