123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /*
- * wpa_supplicant - Wi-Fi Display
- * Copyright (c) 2011, Atheros Communications, Inc.
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
- #include "includes.h"
- #include "common.h"
- #include "p2p/p2p.h"
- #include "common/ieee802_11_defs.h"
- #include "wpa_supplicant_i.h"
- #include "wifi_display.h"
- int wifi_display_init(struct wpa_global *global)
- {
- global->wifi_display = 1;
- return 0;
- }
- void wifi_display_deinit(struct wpa_global *global)
- {
- int i;
- for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
- wpabuf_free(global->wfd_subelem[i]);
- global->wfd_subelem[i] = NULL;
- }
- }
- static int wifi_display_update_wfd_ie(struct wpa_global *global)
- {
- struct wpabuf *ie, *buf;
- size_t len, plen;
- wpa_printf(MSG_DEBUG, "WFD: Update WFD IE");
- if (!global->wifi_display) {
- wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display disabled - do not "
- "include WFD IE");
- p2p_set_wfd_ie_beacon(global->p2p, NULL);
- p2p_set_wfd_ie_probe_req(global->p2p, NULL);
- p2p_set_wfd_ie_probe_resp(global->p2p, NULL);
- p2p_set_wfd_ie_assoc_req(global->p2p, NULL);
- p2p_set_wfd_ie_invitation(global->p2p, NULL);
- p2p_set_wfd_ie_prov_disc_req(global->p2p, NULL);
- p2p_set_wfd_ie_prov_disc_resp(global->p2p, NULL);
- p2p_set_wfd_ie_go_neg(global->p2p, NULL);
- p2p_set_wfd_dev_info(global->p2p, NULL);
- p2p_set_wfd_assoc_bssid(global->p2p, NULL);
- p2p_set_wfd_coupled_sink_info(global->p2p, NULL);
- return 0;
- }
- p2p_set_wfd_dev_info(global->p2p,
- global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
- p2p_set_wfd_assoc_bssid(
- global->p2p,
- global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]);
- p2p_set_wfd_coupled_sink_info(
- global->p2p, global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]);
- /*
- * WFD IE is included in number of management frames. Two different
- * sets of subelements are included depending on the frame:
- *
- * Beacon, (Re)Association Request, GO Negotiation Req/Resp/Conf,
- * Provision Discovery Req:
- * WFD Device Info
- * [Associated BSSID]
- * [Coupled Sink Info]
- *
- * Probe Request:
- * WFD Device Info
- * [Associated BSSID]
- * [Coupled Sink Info]
- * [WFD Extended Capability]
- *
- * Probe Response:
- * WFD Device Info
- * [Associated BSSID]
- * [Coupled Sink Info]
- * [WFD Extended Capability]
- * [WFD Session Info]
- *
- * (Re)Association Response, P2P Invitation Req/Resp,
- * Provision Discovery Resp:
- * WFD Device Info
- * [Associated BSSID]
- * [Coupled Sink Info]
- * [WFD Session Info]
- */
- len = 0;
- if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
- len += wpabuf_len(global->wfd_subelem[
- WFD_SUBELEM_DEVICE_INFO]);
- if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
- len += wpabuf_len(global->wfd_subelem[
- WFD_SUBELEM_ASSOCIATED_BSSID]);
- if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK])
- len += wpabuf_len(global->wfd_subelem[
- WFD_SUBELEM_COUPLED_SINK]);
- if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
- len += wpabuf_len(global->wfd_subelem[
- WFD_SUBELEM_SESSION_INFO]);
- if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB])
- len += wpabuf_len(global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]);
- buf = wpabuf_alloc(len);
- if (buf == NULL)
- return -1;
- if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
- wpabuf_put_buf(buf,
- global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
- if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
- wpabuf_put_buf(buf, global->wfd_subelem[
- WFD_SUBELEM_ASSOCIATED_BSSID]);
- if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK])
- wpabuf_put_buf(buf,
- global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Beacon", ie);
- p2p_set_wfd_ie_beacon(global->p2p, ie);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for (Re)Association Request",
- ie);
- p2p_set_wfd_ie_assoc_req(global->p2p, ie);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for GO Negotiation", ie);
- p2p_set_wfd_ie_go_neg(global->p2p, ie);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery "
- "Request", ie);
- p2p_set_wfd_ie_prov_disc_req(global->p2p, ie);
- plen = buf->used;
- if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB])
- wpabuf_put_buf(buf,
- global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Request", ie);
- p2p_set_wfd_ie_probe_req(global->p2p, ie);
- if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
- wpabuf_put_buf(buf,
- global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Response", ie);
- p2p_set_wfd_ie_probe_resp(global->p2p, ie);
- /* Remove WFD Extended Capability from buffer */
- buf->used = plen;
- if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
- wpabuf_put_buf(buf,
- global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for P2P Invitation", ie);
- p2p_set_wfd_ie_invitation(global->p2p, ie);
- ie = wifi_display_encaps(buf);
- wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery "
- "Response", ie);
- p2p_set_wfd_ie_prov_disc_resp(global->p2p, ie);
- wpabuf_free(buf);
- return 0;
- }
- void wifi_display_enable(struct wpa_global *global, int enabled)
- {
- wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display %s",
- enabled ? "enabled" : "disabled");
- global->wifi_display = enabled;
- wifi_display_update_wfd_ie(global);
- }
- int wifi_display_subelem_set(struct wpa_global *global, char *cmd)
- {
- char *pos;
- int subelem;
- size_t len;
- struct wpabuf *e;
- pos = os_strchr(cmd, ' ');
- if (pos == NULL)
- return -1;
- *pos++ = '\0';
- subelem = atoi(cmd);
- if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS)
- return -1;
- len = os_strlen(pos);
- if (len & 1)
- return -1;
- len /= 2;
- if (len == 0) {
- /* Clear subelement */
- e = NULL;
- wpa_printf(MSG_DEBUG, "WFD: Clear subelement %d", subelem);
- } else {
- e = wpabuf_alloc(1 + len);
- if (e == NULL)
- return -1;
- wpabuf_put_u8(e, subelem);
- if (hexstr2bin(pos, wpabuf_put(e, len), len) < 0) {
- wpabuf_free(e);
- return -1;
- }
- wpa_printf(MSG_DEBUG, "WFD: Set subelement %d", subelem);
- }
- wpabuf_free(global->wfd_subelem[subelem]);
- global->wfd_subelem[subelem] = e;
- wifi_display_update_wfd_ie(global);
- return 0;
- }
- int wifi_display_subelem_get(struct wpa_global *global, char *cmd,
- char *buf, size_t buflen)
- {
- int subelem;
- subelem = atoi(cmd);
- if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS)
- return -1;
- if (global->wfd_subelem[subelem] == NULL)
- return 0;
- return wpa_snprintf_hex(buf, buflen,
- wpabuf_head_u8(global->wfd_subelem[subelem]) +
- 1,
- wpabuf_len(global->wfd_subelem[subelem]) - 1);
- }
|