2 * wpa_supplicant - Wi-Fi Display
3 * Copyright (c) 2011, Atheros Communications, Inc.
4 * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
14 #include "common/ieee802_11_defs.h"
15 #include "wpa_supplicant_i.h"
16 #include "wifi_display.h"
19 #define WIFI_DISPLAY_SUBELEM_HEADER_LEN 3
22 int wifi_display_init(struct wpa_global
*global
)
24 global
->wifi_display
= 1;
29 void wifi_display_deinit(struct wpa_global
*global
)
32 for (i
= 0; i
< MAX_WFD_SUBELEMS
; i
++) {
33 wpabuf_free(global
->wfd_subelem
[i
]);
34 global
->wfd_subelem
[i
] = NULL
;
39 static int wifi_display_update_wfd_ie(struct wpa_global
*global
)
41 struct wpabuf
*ie
, *buf
;
44 wpa_printf(MSG_DEBUG
, "WFD: Update WFD IE");
46 if (!global
->wifi_display
) {
47 wpa_printf(MSG_DEBUG
, "WFD: Wi-Fi Display disabled - do not "
49 p2p_set_wfd_ie_beacon(global
->p2p
, NULL
);
50 p2p_set_wfd_ie_probe_req(global
->p2p
, NULL
);
51 p2p_set_wfd_ie_probe_resp(global
->p2p
, NULL
);
52 p2p_set_wfd_ie_assoc_req(global
->p2p
, NULL
);
53 p2p_set_wfd_ie_invitation(global
->p2p
, NULL
);
54 p2p_set_wfd_ie_prov_disc_req(global
->p2p
, NULL
);
55 p2p_set_wfd_ie_prov_disc_resp(global
->p2p
, NULL
);
56 p2p_set_wfd_ie_go_neg(global
->p2p
, NULL
);
57 p2p_set_wfd_dev_info(global
->p2p
, NULL
);
58 p2p_set_wfd_assoc_bssid(global
->p2p
, NULL
);
59 p2p_set_wfd_coupled_sink_info(global
->p2p
, NULL
);
63 p2p_set_wfd_dev_info(global
->p2p
,
64 global
->wfd_subelem
[WFD_SUBELEM_DEVICE_INFO
]);
65 p2p_set_wfd_assoc_bssid(
67 global
->wfd_subelem
[WFD_SUBELEM_ASSOCIATED_BSSID
]);
68 p2p_set_wfd_coupled_sink_info(
69 global
->p2p
, global
->wfd_subelem
[WFD_SUBELEM_COUPLED_SINK
]);
72 * WFD IE is included in number of management frames. Two different
73 * sets of subelements are included depending on the frame:
75 * Beacon, (Re)Association Request, GO Negotiation Req/Resp/Conf,
76 * Provision Discovery Req:
85 * [WFD Extended Capability]
91 * [WFD Extended Capability]
94 * (Re)Association Response, P2P Invitation Req/Resp,
95 * Provision Discovery Resp:
102 if (global
->wfd_subelem
[WFD_SUBELEM_DEVICE_INFO
])
103 len
+= wpabuf_len(global
->wfd_subelem
[
104 WFD_SUBELEM_DEVICE_INFO
]);
105 if (global
->wfd_subelem
[WFD_SUBELEM_ASSOCIATED_BSSID
])
106 len
+= wpabuf_len(global
->wfd_subelem
[
107 WFD_SUBELEM_ASSOCIATED_BSSID
]);
108 if (global
->wfd_subelem
[WFD_SUBELEM_COUPLED_SINK
])
109 len
+= wpabuf_len(global
->wfd_subelem
[
110 WFD_SUBELEM_COUPLED_SINK
]);
111 if (global
->wfd_subelem
[WFD_SUBELEM_SESSION_INFO
])
112 len
+= wpabuf_len(global
->wfd_subelem
[
113 WFD_SUBELEM_SESSION_INFO
]);
114 if (global
->wfd_subelem
[WFD_SUBELEM_EXT_CAPAB
])
115 len
+= wpabuf_len(global
->wfd_subelem
[WFD_SUBELEM_EXT_CAPAB
]);
116 buf
= wpabuf_alloc(len
);
120 if (global
->wfd_subelem
[WFD_SUBELEM_DEVICE_INFO
])
122 global
->wfd_subelem
[WFD_SUBELEM_DEVICE_INFO
]);
123 if (global
->wfd_subelem
[WFD_SUBELEM_ASSOCIATED_BSSID
])
124 wpabuf_put_buf(buf
, global
->wfd_subelem
[
125 WFD_SUBELEM_ASSOCIATED_BSSID
]);
126 if (global
->wfd_subelem
[WFD_SUBELEM_COUPLED_SINK
])
128 global
->wfd_subelem
[WFD_SUBELEM_COUPLED_SINK
]);
130 ie
= wifi_display_encaps(buf
);
131 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for Beacon", ie
);
132 p2p_set_wfd_ie_beacon(global
->p2p
, ie
);
134 ie
= wifi_display_encaps(buf
);
135 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for (Re)Association Request",
137 p2p_set_wfd_ie_assoc_req(global
->p2p
, ie
);
139 ie
= wifi_display_encaps(buf
);
140 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for GO Negotiation", ie
);
141 p2p_set_wfd_ie_go_neg(global
->p2p
, ie
);
143 ie
= wifi_display_encaps(buf
);
144 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for Provision Discovery "
146 p2p_set_wfd_ie_prov_disc_req(global
->p2p
, ie
);
149 if (global
->wfd_subelem
[WFD_SUBELEM_EXT_CAPAB
])
151 global
->wfd_subelem
[WFD_SUBELEM_EXT_CAPAB
]);
153 ie
= wifi_display_encaps(buf
);
154 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for Probe Request", ie
);
155 p2p_set_wfd_ie_probe_req(global
->p2p
, ie
);
157 if (global
->wfd_subelem
[WFD_SUBELEM_SESSION_INFO
])
159 global
->wfd_subelem
[WFD_SUBELEM_SESSION_INFO
]);
160 ie
= wifi_display_encaps(buf
);
161 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for Probe Response", ie
);
162 p2p_set_wfd_ie_probe_resp(global
->p2p
, ie
);
164 /* Remove WFD Extended Capability from buffer */
166 if (global
->wfd_subelem
[WFD_SUBELEM_SESSION_INFO
])
168 global
->wfd_subelem
[WFD_SUBELEM_SESSION_INFO
]);
170 ie
= wifi_display_encaps(buf
);
171 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for P2P Invitation", ie
);
172 p2p_set_wfd_ie_invitation(global
->p2p
, ie
);
174 ie
= wifi_display_encaps(buf
);
175 wpa_hexdump_buf(MSG_DEBUG
, "WFD: WFD IE for Provision Discovery "
177 p2p_set_wfd_ie_prov_disc_resp(global
->p2p
, ie
);
185 void wifi_display_enable(struct wpa_global
*global
, int enabled
)
187 wpa_printf(MSG_DEBUG
, "WFD: Wi-Fi Display %s",
188 enabled
? "enabled" : "disabled");
189 global
->wifi_display
= enabled
;
190 wifi_display_update_wfd_ie(global
);
194 int wifi_display_subelem_set(struct wpa_global
*global
, char *cmd
)
201 pos
= os_strchr(cmd
, ' ');
206 if (subelem
< 0 || subelem
>= MAX_WFD_SUBELEMS
)
209 len
= os_strlen(pos
);
215 /* Clear subelement */
217 wpa_printf(MSG_DEBUG
, "WFD: Clear subelement %d", subelem
);
219 e
= wpabuf_alloc(1 + len
);
222 wpabuf_put_u8(e
, subelem
);
223 if (hexstr2bin(pos
, wpabuf_put(e
, len
), len
) < 0) {
227 wpa_printf(MSG_DEBUG
, "WFD: Set subelement %d", subelem
);
230 wpabuf_free(global
->wfd_subelem
[subelem
]);
231 global
->wfd_subelem
[subelem
] = e
;
232 wifi_display_update_wfd_ie(global
);
238 int wifi_display_subelem_get(struct wpa_global
*global
, char *cmd
,
239 char *buf
, size_t buflen
)
244 if (subelem
< 0 || subelem
>= MAX_WFD_SUBELEMS
)
247 if (global
->wfd_subelem
[subelem
] == NULL
)
250 return wpa_snprintf_hex(buf
, buflen
,
251 wpabuf_head_u8(global
->wfd_subelem
[subelem
]) +
253 wpabuf_len(global
->wfd_subelem
[subelem
]) - 1);
257 char * wifi_display_subelem_hex(const struct wpabuf
*wfd_subelems
, u8 id
)
259 char *subelem
= NULL
;
268 buf
= wpabuf_head_u8(wfd_subelems
);
272 buflen
= wpabuf_len(wfd_subelems
);
274 while (i
+ WIFI_DISPLAY_SUBELEM_HEADER_LEN
< buflen
) {
275 elen
= WPA_GET_BE16(buf
+ i
+ 1);
278 subelem
= os_zalloc(2 * elen
+ 1);
281 wpa_snprintf_hex(subelem
, 2 * elen
+ 1,
283 WIFI_DISPLAY_SUBELEM_HEADER_LEN
,
288 i
+= elen
+ WIFI_DISPLAY_SUBELEM_HEADER_LEN
;