]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/wpa/wpa_supplicant/wifi_display.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / wpa / wpa_supplicant / wifi_display.c
1 /*
2  * wpa_supplicant - Wi-Fi Display
3  * Copyright (c) 2011, Atheros Communications, Inc.
4  * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9
10 #include "includes.h"
11
12 #include "common.h"
13 #include "p2p/p2p.h"
14 #include "common/ieee802_11_defs.h"
15 #include "wpa_supplicant_i.h"
16 #include "wifi_display.h"
17
18
19 int wifi_display_init(struct wpa_global *global)
20 {
21         global->wifi_display = 1;
22         return 0;
23 }
24
25
26 void wifi_display_deinit(struct wpa_global *global)
27 {
28         int i;
29         for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
30                 wpabuf_free(global->wfd_subelem[i]);
31                 global->wfd_subelem[i] = NULL;
32         }
33 }
34
35
36 static int wifi_display_update_wfd_ie(struct wpa_global *global)
37 {
38         struct wpabuf *ie, *buf;
39         size_t len, plen;
40
41         wpa_printf(MSG_DEBUG, "WFD: Update WFD IE");
42
43         if (!global->wifi_display) {
44                 wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display disabled - do not "
45                            "include WFD IE");
46                 p2p_set_wfd_ie_beacon(global->p2p, NULL);
47                 p2p_set_wfd_ie_probe_req(global->p2p, NULL);
48                 p2p_set_wfd_ie_probe_resp(global->p2p, NULL);
49                 p2p_set_wfd_ie_assoc_req(global->p2p, NULL);
50                 p2p_set_wfd_ie_invitation(global->p2p, NULL);
51                 p2p_set_wfd_ie_prov_disc_req(global->p2p, NULL);
52                 p2p_set_wfd_ie_prov_disc_resp(global->p2p, NULL);
53                 p2p_set_wfd_ie_go_neg(global->p2p, NULL);
54                 p2p_set_wfd_dev_info(global->p2p, NULL);
55                 p2p_set_wfd_assoc_bssid(global->p2p, NULL);
56                 p2p_set_wfd_coupled_sink_info(global->p2p, NULL);
57                 return 0;
58         }
59
60         p2p_set_wfd_dev_info(global->p2p,
61                              global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
62         p2p_set_wfd_assoc_bssid(
63                 global->p2p,
64                 global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]);
65         p2p_set_wfd_coupled_sink_info(
66                 global->p2p, global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]);
67
68         /*
69          * WFD IE is included in number of management frames. Two different
70          * sets of subelements are included depending on the frame:
71          *
72          * Beacon, (Re)Association Request, GO Negotiation Req/Resp/Conf,
73          * Provision Discovery Req:
74          * WFD Device Info
75          * [Associated BSSID]
76          * [Coupled Sink Info]
77          *
78          * Probe Request:
79          * WFD Device Info
80          * [Associated BSSID]
81          * [Coupled Sink Info]
82          * [WFD Extended Capability]
83          *
84          * Probe Response:
85          * WFD Device Info
86          * [Associated BSSID]
87          * [Coupled Sink Info]
88          * [WFD Extended Capability]
89          * [WFD Session Info]
90          *
91          * (Re)Association Response, P2P Invitation Req/Resp,
92          * Provision Discovery Resp:
93          * WFD Device Info
94          * [Associated BSSID]
95          * [Coupled Sink Info]
96          * [WFD Session Info]
97          */
98         len = 0;
99         if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
100                 len += wpabuf_len(global->wfd_subelem[
101                                           WFD_SUBELEM_DEVICE_INFO]);
102         if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
103                 len += wpabuf_len(global->wfd_subelem[
104                                           WFD_SUBELEM_ASSOCIATED_BSSID]);
105         if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK])
106                 len += wpabuf_len(global->wfd_subelem[
107                                           WFD_SUBELEM_COUPLED_SINK]);
108         if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
109                 len += wpabuf_len(global->wfd_subelem[
110                                           WFD_SUBELEM_SESSION_INFO]);
111         if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB])
112                 len += wpabuf_len(global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]);
113         buf = wpabuf_alloc(len);
114         if (buf == NULL)
115                 return -1;
116
117         if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
118                 wpabuf_put_buf(buf,
119                                global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
120         if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
121                 wpabuf_put_buf(buf, global->wfd_subelem[
122                                        WFD_SUBELEM_ASSOCIATED_BSSID]);
123         if (global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK])
124                 wpabuf_put_buf(buf,
125                                global->wfd_subelem[WFD_SUBELEM_COUPLED_SINK]);
126
127         ie = wifi_display_encaps(buf);
128         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Beacon", ie);
129         p2p_set_wfd_ie_beacon(global->p2p, ie);
130
131         ie = wifi_display_encaps(buf);
132         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for (Re)Association Request",
133                         ie);
134         p2p_set_wfd_ie_assoc_req(global->p2p, ie);
135
136         ie = wifi_display_encaps(buf);
137         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for GO Negotiation", ie);
138         p2p_set_wfd_ie_go_neg(global->p2p, ie);
139
140         ie = wifi_display_encaps(buf);
141         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery "
142                         "Request", ie);
143         p2p_set_wfd_ie_prov_disc_req(global->p2p, ie);
144
145         plen = buf->used;
146         if (global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB])
147                 wpabuf_put_buf(buf,
148                                global->wfd_subelem[WFD_SUBELEM_EXT_CAPAB]);
149
150         ie = wifi_display_encaps(buf);
151         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Request", ie);
152         p2p_set_wfd_ie_probe_req(global->p2p, ie);
153
154         if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
155                 wpabuf_put_buf(buf,
156                                global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]);
157         ie = wifi_display_encaps(buf);
158         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Probe Response", ie);
159         p2p_set_wfd_ie_probe_resp(global->p2p, ie);
160
161         /* Remove WFD Extended Capability from buffer */
162         buf->used = plen;
163         if (global->wfd_subelem[WFD_SUBELEM_SESSION_INFO])
164                 wpabuf_put_buf(buf,
165                                global->wfd_subelem[WFD_SUBELEM_SESSION_INFO]);
166
167         ie = wifi_display_encaps(buf);
168         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for P2P Invitation", ie);
169         p2p_set_wfd_ie_invitation(global->p2p, ie);
170
171         ie = wifi_display_encaps(buf);
172         wpa_hexdump_buf(MSG_DEBUG, "WFD: WFD IE for Provision Discovery "
173                         "Response", ie);
174         p2p_set_wfd_ie_prov_disc_resp(global->p2p, ie);
175
176         wpabuf_free(buf);
177
178         return 0;
179 }
180
181
182 void wifi_display_enable(struct wpa_global *global, int enabled)
183 {
184         wpa_printf(MSG_DEBUG, "WFD: Wi-Fi Display %s",
185                    enabled ? "enabled" : "disabled");
186         global->wifi_display = enabled;
187         wifi_display_update_wfd_ie(global);
188 }
189
190
191 int wifi_display_subelem_set(struct wpa_global *global, char *cmd)
192 {
193         char *pos;
194         int subelem;
195         size_t len;
196         struct wpabuf *e;
197
198         pos = os_strchr(cmd, ' ');
199         if (pos == NULL)
200                 return -1;
201         *pos++ = '\0';
202         subelem = atoi(cmd);
203         if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS)
204                 return -1;
205
206         len = os_strlen(pos);
207         if (len & 1)
208                 return -1;
209         len /= 2;
210
211         if (len == 0) {
212                 /* Clear subelement */
213                 e = NULL;
214                 wpa_printf(MSG_DEBUG, "WFD: Clear subelement %d", subelem);
215         } else {
216                 e = wpabuf_alloc(1 + len);
217                 if (e == NULL)
218                         return -1;
219                 wpabuf_put_u8(e, subelem);
220                 if (hexstr2bin(pos, wpabuf_put(e, len), len) < 0) {
221                         wpabuf_free(e);
222                         return -1;
223                 }
224                 wpa_printf(MSG_DEBUG, "WFD: Set subelement %d", subelem);
225         }
226
227         wpabuf_free(global->wfd_subelem[subelem]);
228         global->wfd_subelem[subelem] = e;
229         wifi_display_update_wfd_ie(global);
230
231         return 0;
232 }
233
234
235 int wifi_display_subelem_get(struct wpa_global *global, char *cmd,
236                              char *buf, size_t buflen)
237 {
238         int subelem;
239
240         subelem = atoi(cmd);
241         if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS)
242                 return -1;
243
244         if (global->wfd_subelem[subelem] == NULL)
245                 return 0;
246
247         return wpa_snprintf_hex(buf, buflen,
248                                 wpabuf_head_u8(global->wfd_subelem[subelem]) +
249                                 1,
250                                 wpabuf_len(global->wfd_subelem[subelem]) - 1);
251 }