From Jouni Malinen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8711 Wi...
[metze/wireshark/wip.git] / epan / dissectors / packet-wifi-display.c
1 /* packet-wifi-display.c
2  *
3  * Wi-Fi Display
4  *
5  * Copyright 2011-2013 Qualcomm Atheros, Inc.
6  *
7  * $Id$
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 # include "config.h"
25
26 #include <glib.h>
27 #include <epan/packet.h>
28 #include <epan/expert.h>
29
30 #include "packet-ieee80211.h"
31
32 static int proto_wifi_display = -1;
33
34 static int hf_wfd_subelem_id = -1;
35 static int hf_wfd_subelem_len = -1;
36
37 static int hf_wfd_subelem_dev_info_type = -1;
38 static int hf_wfd_subelem_dev_info_coupled_sink_source = -1;
39 static int hf_wfd_subelem_dev_info_coupled_sink_sink = -1;
40 static int hf_wfd_subelem_dev_info_available = -1;
41 static int hf_wfd_subelem_dev_info_wsd = -1;
42 static int hf_wfd_subelem_dev_info_pc = -1;
43 static int hf_wfd_subelem_dev_info_content_protection = -1;
44 static int hf_wfd_subelem_dev_info_time_sync = -1;
45 static int hf_wfd_subelem_dev_info_control_port = -1;
46 static int hf_wfd_subelem_dev_info_max_throughput = -1;
47 static int hf_wfd_subelem_dev_info_audio_unsupp_pri_sink = -1;
48 static int hf_wfd_subelem_dev_info_audio_only_supp_source = -1;
49 static int hf_wfd_subelem_dev_info_tdls_persistent_group = -1;
50 static int hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke = -1;
51 static int hf_wfd_subelem_dev_info_reserved = -1;
52
53 static int hf_wfd_subelem_assoc_bssid = -1;
54
55 static int hf_wfd_subelem_coupled_sink_status_bitmap = -1;
56 static int hf_wfd_subelem_coupled_sink_reserved = -1;
57 static int hf_wfd_subelem_coupled_sink_mac_addr = -1;
58
59 static int hf_wfd_subelem_session_descr_len = -1;
60 static int hf_wfd_subelem_session_dev_addr = -1;
61 static int hf_wfd_subelem_session_assoc_bssid = -1;
62 static int hf_wfd_subelem_session_dev_info_type = -1;
63 static int hf_wfd_subelem_session_dev_info_coupled_sink_source = -1;
64 static int hf_wfd_subelem_session_dev_info_coupled_sink_sink = -1;
65 static int hf_wfd_subelem_session_dev_info_available = -1;
66 static int hf_wfd_subelem_session_dev_info_wsd = -1;
67 static int hf_wfd_subelem_session_dev_info_pc = -1;
68 static int hf_wfd_subelem_session_dev_info_content_protection = -1;
69 static int hf_wfd_subelem_session_dev_info_time_sync = -1;
70 static int hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink = -1;
71 static int hf_wfd_subelem_session_dev_info_audio_only_supp_source = -1;
72 static int hf_wfd_subelem_session_dev_info_tdls_persistent_group = -1;
73 static int hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke = -1;
74 static int hf_wfd_subelem_session_dev_info_reserved = -1;
75 static int hf_wfd_subelem_session_dev_info_max_throughput = -1;
76 static int hf_wfd_subelem_session_coupled_sink_status_bitmap = -1;
77 static int hf_wfd_subelem_session_coupled_sink_reserved = -1;
78 static int hf_wfd_subelem_session_coupled_sink_addr = -1;
79
80 static gint ett_wfd_subelem = -1;
81 static gint ett_wfd_dev_info_descr = -1;
82
83
84 enum wifi_display_subelem {
85   WFD_SUBELEM_DEVICE_INFO = 0,
86   WFD_SUBELEM_ASSOCIATED_BSSID = 1,
87   WFD_SUBELEM_AUDIO_FORMATS = 2,
88   WFD_SUBELEM_VIDEO_FORMATS = 3,
89   WFD_SUBELEM_3D_VIDEO_FORMATS = 4,
90   WFD_SUBELEM_CONTENT_PROTECTION = 5,
91   WFD_SUBELEM_COUPLED_SINK = 6,
92   WFD_SUBELEM_EXT_CAPAB = 7,
93   WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
94   WFD_SUBELEM_SESSION_INFO = 9,
95   WFD_SUBELEM_ALT_MAC_ADDR = 10
96 };
97
98 static const value_string wfd_subelem_ids[] = {
99   { WFD_SUBELEM_DEVICE_INFO, "WFD Device Information" },
100   { WFD_SUBELEM_ASSOCIATED_BSSID, "Associated BSSID" },
101   { WFD_SUBELEM_AUDIO_FORMATS, "WFD Audio Formats" },
102   { WFD_SUBELEM_VIDEO_FORMATS, "WFD Video Formats" },
103   { WFD_SUBELEM_3D_VIDEO_FORMATS, "WFD 3D Video Formats" },
104   { WFD_SUBELEM_CONTENT_PROTECTION, "WFD Content Protection" },
105   { WFD_SUBELEM_COUPLED_SINK, "Coupled Sink Information" },
106   { WFD_SUBELEM_EXT_CAPAB, "WFD Extended Capability" },
107   { WFD_SUBELEM_LOCAL_IP_ADDRESS, "Local IP Address" },
108   { WFD_SUBELEM_SESSION_INFO, "WFD Session Information" },
109   { WFD_SUBELEM_ALT_MAC_ADDR, "Alternative MAC Address" },
110   { 0, NULL }
111 };
112
113
114 static const value_string wfd_dev_info_types[] = {
115   { 0, "WFD source" },
116   { 1, "WFD primary sink" },
117   { 2, "WFD secondary sink" },
118   { 3, "WFD source/primary sink" },
119   { 0, NULL }
120 };
121
122 static const value_string wfd_dev_info_avail[] = {
123   { 0, "Not available for WFD Session" },
124   { 1, "Available for WFD Session" },
125   { 0, NULL }
126 };
127
128 static const value_string wfd_dev_info_pc[] = {
129   { 0, "P2P" },
130   { 1, "TDLS" },
131   { 0, NULL }
132 };
133
134 static const value_string wfd_coupled_sink_status_bitmap[] = {
135   { 0, "Not coupled/Available for Coupling" },
136   { 1, "Coupled" },
137   { 2, "Teardown Coupling" },
138   { 3, "Reserved" },
139   { 0, NULL }
140 };
141
142 static void
143 dissect_wfd_subelem_device_info(proto_tree *tree, tvbuff_t *tvb, int offset)
144 {
145   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_type,
146                       tvb, offset, 2, ENC_BIG_ENDIAN);
147   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_coupled_sink_source,
148                       tvb, offset, 2, ENC_BIG_ENDIAN);
149   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_coupled_sink_sink,
150                       tvb, offset, 2, ENC_BIG_ENDIAN);
151   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_available,
152                       tvb, offset, 2, ENC_BIG_ENDIAN);
153   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_wsd,
154                       tvb, offset, 2, ENC_BIG_ENDIAN);
155   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_pc,
156                       tvb, offset, 2, ENC_BIG_ENDIAN);
157   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_content_protection,
158                       tvb, offset, 2, ENC_BIG_ENDIAN);
159   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_time_sync,
160                       tvb, offset, 2, ENC_BIG_ENDIAN);
161   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_audio_unsupp_pri_sink,
162                       tvb, offset, 2, ENC_BIG_ENDIAN);
163   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_audio_only_supp_source,
164                       tvb, offset, 2, ENC_BIG_ENDIAN);
165   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_tdls_persistent_group,
166                       tvb, offset, 2, ENC_BIG_ENDIAN);
167   proto_tree_add_item(tree,
168                       hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke,
169                       tvb, offset, 2, ENC_BIG_ENDIAN);
170   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_reserved,
171                       tvb, offset, 2, ENC_BIG_ENDIAN);
172   offset += 2;
173
174   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_control_port,
175                       tvb, offset, 2, ENC_BIG_ENDIAN);
176   offset += 2;
177
178   proto_tree_add_item(tree, hf_wfd_subelem_dev_info_max_throughput,
179                       tvb, offset, 2, ENC_BIG_ENDIAN);
180 }
181
182 static void
183 dissect_wfd_subelem_associated_bssid(packet_info *pinfo, proto_tree *tree,
184                                      tvbuff_t *tvb, int offset, int len)
185 {
186   if (len < 6) {
187     expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
188                            "Too short Wi-Fi Display Associated BSSID");
189     return;
190   }
191   proto_tree_add_item(tree, hf_wfd_subelem_assoc_bssid, tvb, offset, 6, ENC_NA);
192 }
193
194 static void
195 dissect_wfd_subelem_coupled_sink(packet_info *pinfo, proto_tree *tree,
196                                  tvbuff_t *tvb, int offset, int len)
197 {
198   if (len < 1) {
199     expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
200                            "Too short Wi-Fi Display Coupled Sink");
201     return;
202   }
203   proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_status_bitmap,
204                       tvb, offset, 1, ENC_BIG_ENDIAN);
205   proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_reserved,
206                       tvb, offset, 1, ENC_BIG_ENDIAN);
207   if (len < 1 + 6) {
208     expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
209                            "Too short Wi-Fi Display Coupled Sink");
210     return;
211   }
212   proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_mac_addr, tvb,
213                       offset + 1, 6, ENC_NA);
214 }
215
216 static void
217 dissect_wfd_subelem_session_info(packet_info *pinfo, proto_tree *tree,
218                                  tvbuff_t *tvb, int offset, guint8 len)
219 {
220   int end = offset + len, next;
221   proto_item *item;
222   proto_tree *descr;
223
224   while (offset < end) {
225     guint8 dlen = tvb_get_guint8(tvb, offset);
226     if (offset + 1 + dlen > end || dlen < 23) {
227       expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
228                              "Invalid WFD Device Info Descriptor");
229       break;
230     }
231     next = offset + 1 + dlen;
232
233     item = proto_tree_add_text(tree, tvb, offset, 1 + dlen,
234                                "WFD Device Info Descriptor");
235     descr = proto_item_add_subtree(item, ett_wfd_dev_info_descr);
236
237     proto_tree_add_item(descr, hf_wfd_subelem_session_descr_len,
238                         tvb, offset, 1, ENC_BIG_ENDIAN);
239     offset++;
240
241     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_addr, tvb, offset, 6,
242                         ENC_NA);
243     proto_item_append_text(descr, ": %s", tvb_ether_to_str(tvb, offset));
244     offset += 6;
245
246     proto_tree_add_item(descr, hf_wfd_subelem_session_assoc_bssid,
247                         tvb, offset, 6, ENC_NA);
248     offset += 6;
249
250     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_type,
251                         tvb, offset, 2, ENC_BIG_ENDIAN);
252     proto_tree_add_item(descr,
253                         hf_wfd_subelem_session_dev_info_coupled_sink_source,
254                         tvb, offset, 2, ENC_BIG_ENDIAN);
255     proto_tree_add_item(descr,
256                         hf_wfd_subelem_session_dev_info_coupled_sink_sink,
257                         tvb, offset, 2, ENC_BIG_ENDIAN);
258     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_available,
259                         tvb, offset, 2, ENC_BIG_ENDIAN);
260     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_wsd,
261                         tvb, offset, 2, ENC_BIG_ENDIAN);
262     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_pc,
263                         tvb, offset, 2, ENC_BIG_ENDIAN);
264     proto_tree_add_item(descr,
265                         hf_wfd_subelem_session_dev_info_content_protection,
266                         tvb, offset, 2, ENC_BIG_ENDIAN);
267     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_time_sync,
268                         tvb, offset, 2, ENC_BIG_ENDIAN);
269     proto_tree_add_item(tree,
270                         hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink,
271                         tvb, offset, 2, ENC_BIG_ENDIAN);
272     proto_tree_add_item(tree,
273                         hf_wfd_subelem_session_dev_info_audio_only_supp_source,
274                         tvb, offset, 2, ENC_BIG_ENDIAN);
275     proto_tree_add_item(tree,
276                         hf_wfd_subelem_session_dev_info_tdls_persistent_group,
277                         tvb, offset, 2, ENC_BIG_ENDIAN);
278     proto_tree_add_item(tree,
279                         hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke,
280                         tvb, offset, 2, ENC_BIG_ENDIAN);
281     proto_tree_add_item(tree,
282                         hf_wfd_subelem_session_dev_info_reserved,
283                         tvb, offset, 2, ENC_BIG_ENDIAN);
284     offset += 2;
285
286     proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_max_throughput,
287                         tvb, offset, 2, ENC_BIG_ENDIAN);
288     offset += 2;
289
290     proto_tree_add_item(descr,
291                         hf_wfd_subelem_session_coupled_sink_status_bitmap,
292                         tvb, offset, 1, ENC_BIG_ENDIAN);
293     proto_tree_add_item(descr,
294                         hf_wfd_subelem_session_coupled_sink_reserved,
295                         tvb, offset, 1, ENC_BIG_ENDIAN);
296     offset++;
297
298     proto_tree_add_item(descr, hf_wfd_subelem_session_coupled_sink_addr,
299                         tvb, offset, 6, ENC_NA);
300     offset += 6;
301
302     if (offset < next) {
303       proto_tree_add_text(descr, tvb, offset, next - offset,
304                           "Extra info in the end of descriptor");
305     }
306
307     offset = next;
308   }
309 }
310
311 void dissect_wifi_display_ie(packet_info *pinfo, proto_tree *tree,
312                              tvbuff_t *tvb, int offset, gint size)
313 {
314   int end = offset + size;
315   guint8 id;
316   guint16 len;
317   proto_tree *wfd_tree;
318   proto_item *subelem;
319
320   while (offset < end) {
321     if (end - offset < 2) {
322       expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
323                              "Packet too short for Wi-Fi Display subelement");
324       break;
325     }
326
327     id = tvb_get_guint8(tvb, offset);
328     len = tvb_get_ntohs(tvb, offset + 1);
329     subelem = proto_tree_add_text(tree, tvb, offset, 3 + len, "%s",
330                                   val_to_str(id, wfd_subelem_ids,
331                                              "Unknown subelement ID (%u)"));
332     if (offset + 3 + len > end) {
333       expert_add_info_format(pinfo, subelem, PI_MALFORMED, PI_ERROR,
334                              "Packet too short for Wi-Fi Display subelement "
335                              "payload");
336     }
337
338     wfd_tree = proto_item_add_subtree(subelem, ett_wfd_subelem);
339
340     proto_tree_add_item(wfd_tree, hf_wfd_subelem_id, tvb, offset, 1,
341                         ENC_BIG_ENDIAN);
342     offset++;
343     proto_tree_add_item(wfd_tree, hf_wfd_subelem_len, tvb, offset, 2,
344                         ENC_BIG_ENDIAN);
345     offset += 2;
346
347     switch (id) {
348     case WFD_SUBELEM_DEVICE_INFO:
349       dissect_wfd_subelem_device_info(wfd_tree, tvb, offset);
350       break;
351     case WFD_SUBELEM_ASSOCIATED_BSSID:
352       dissect_wfd_subelem_associated_bssid(pinfo, wfd_tree, tvb, offset, len);
353       break;
354     case WFD_SUBELEM_COUPLED_SINK:
355       dissect_wfd_subelem_coupled_sink(pinfo, wfd_tree, tvb, offset, len);
356       break;
357     case WFD_SUBELEM_SESSION_INFO:
358       dissect_wfd_subelem_session_info(pinfo, wfd_tree, tvb, offset, len);
359       break;
360     default:
361       proto_tree_add_text(wfd_tree, tvb, offset, len,
362                           "Unknown subelement payload");
363       break;
364     }
365
366     offset += len;
367   }
368 }
369
370 void
371 proto_register_wifi_display(void)
372 {
373   static hf_register_info hf[] = {
374     { &hf_wfd_subelem_id,
375       { "Subelement ID", "wifi_display.subelem.id",
376         FT_UINT8, BASE_DEC, VALS(wfd_subelem_ids), 0, NULL, HFILL }},
377     { &hf_wfd_subelem_len,
378       { "Length", "wifi_display.subelem.length",
379         FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
380     { &hf_wfd_subelem_dev_info_type,
381       { "Device type", "wifi_display.subelem.dev_info.type",
382         FT_UINT16, BASE_DEC, VALS(wfd_dev_info_types), 0x0003, NULL, HFILL }},
383     { &hf_wfd_subelem_dev_info_coupled_sink_source,
384       { "Coupled sink operation supported by WFD source",
385         "wifi_display.subelem.dev_info.coupled_sink_by_source",
386         FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
387     { &hf_wfd_subelem_dev_info_coupled_sink_sink,
388       { "Coupled sink operation supported by WFD sink",
389         "wifi_display.subelem.dev_info.coupled_sink_by_sink",
390         FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
391     { &hf_wfd_subelem_dev_info_available,
392       { "Available for WFD Session", "wifi_display.subelem.dev_info.available",
393         FT_UINT16, BASE_DEC, VALS(wfd_dev_info_avail), 0x0030, NULL, HFILL }},
394     { &hf_wfd_subelem_dev_info_wsd,
395       { "WFD Service Discovery", "wifi_display.subelem.dev_info.wsd",
396         FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }},
397     { &hf_wfd_subelem_dev_info_pc,
398       { "Preferred Connectivity", "wifi_display.subelem.dev_info.pc",
399         FT_UINT16, BASE_DEC, VALS(wfd_dev_info_pc), 0x0080, NULL, HFILL }},
400     { &hf_wfd_subelem_dev_info_content_protection,
401       { "Content Protection using HDCP2.0",
402         "wifi_display.subelem.dev_info.content_protection",
403         FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
404     { &hf_wfd_subelem_dev_info_time_sync,
405       { "Time Synchronization using 802.1AS",
406         "wifi_display.subelem.dev_info.time_sync",
407         FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
408     { &hf_wfd_subelem_dev_info_audio_unsupp_pri_sink,
409       { "Audio un-supported at Primary sink",
410         "wifi_display.subelem.session.audio_unsupp_pri_sink",
411         FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
412     { &hf_wfd_subelem_dev_info_audio_only_supp_source,
413       { "Audio only support af WFD source",
414         "wifi_display.subelem.session.audio_only_supp_source",
415         FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }},
416     { &hf_wfd_subelem_dev_info_tdls_persistent_group,
417       { "TDLS Persistent Group",
418         "wifi_display.subelem.session.tdls_persistent_group",
419         FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }},
420     { &hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke,
421       { "TDLS Persistent Group Re-invoke",
422         "wifi_display.subelem.session.tdls_persistent_group_reinvoke",
423         FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
424     { &hf_wfd_subelem_dev_info_reserved,
425       { "Reserved", "wifi_display.subelem.session.reserved",
426         FT_UINT16, BASE_DEC, NULL, 0xc000, NULL, HFILL }},
427     { &hf_wfd_subelem_dev_info_control_port,
428       { "Session Management Control Port",
429         "wifi_display.subelem.dev_info.control_port",
430         FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
431     { &hf_wfd_subelem_dev_info_max_throughput,
432       { "WFD Device Maximum Throughput (Mbps)",
433         "wifi_display.subelem.dev_info.max_throughput",
434         FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
435     { &hf_wfd_subelem_assoc_bssid,
436       { "Associated BSSID", "wifi_display.subelem.assoc_bssid.bssid",
437         FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
438     { &hf_wfd_subelem_coupled_sink_status_bitmap,
439       { "Coupled Sink Status bitmap",
440         "wifi_display.subelem.coupled_sink.status",
441         FT_UINT8, BASE_DEC, VALS(wfd_coupled_sink_status_bitmap), 0x03,
442         NULL, HFILL }},
443     { &hf_wfd_subelem_coupled_sink_reserved,
444       { "Reserved", "wifi_display.subelem.coupled_sink.reserved",
445         FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL }},
446     { &hf_wfd_subelem_coupled_sink_mac_addr,
447       { "Coupled Sink MAC Address",
448         "wifi_display.subelem.coupled_sink.mac_addr",
449         FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
450     { &hf_wfd_subelem_session_descr_len,
451       { "Descriptor length",
452         "wifi_display.subelem.session.descr_len",
453         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
454     { &hf_wfd_subelem_session_dev_addr,
455       { "Device address",
456         "wifi_display.subelem.session.device_address",
457         FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
458     { &hf_wfd_subelem_session_assoc_bssid,
459       { "Associated BSSID",
460         "wifi_display.subelem.session.associated_bssid",
461         FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
462     { &hf_wfd_subelem_session_dev_info_type,
463       { "Device type", "wifi_display.subelem.session.type",
464         FT_UINT16, BASE_DEC, VALS(wfd_dev_info_types), 0x0003, NULL, HFILL }},
465     { &hf_wfd_subelem_session_dev_info_coupled_sink_source,
466       { "Coupled sink operation supported by WFD source",
467         "wifi_display.subelem.session.coupled_sink_by_source",
468         FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
469     { &hf_wfd_subelem_session_dev_info_coupled_sink_sink,
470       { "Coupled sink operation supported by WFD sink",
471         "wifi_display.subelem.session.coupled_sink_by_sink",
472         FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
473     { &hf_wfd_subelem_session_dev_info_available,
474       { "Available for WFD Session", "wifi_display.subelem.session.available",
475         FT_UINT16, BASE_DEC, VALS(wfd_dev_info_avail), 0x0030, NULL, HFILL }},
476     { &hf_wfd_subelem_session_dev_info_wsd,
477       { "WFD Service Discovery", "wifi_display.subelem.session.wsd",
478         FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }},
479     { &hf_wfd_subelem_session_dev_info_pc,
480       { "Preferred Connectivity", "wifi_display.subelem.session.pc",
481         FT_UINT16, BASE_DEC, VALS(wfd_dev_info_pc), 0x0080, NULL, HFILL }},
482     { &hf_wfd_subelem_session_dev_info_content_protection,
483       { "Content Protection using HDCP2.0",
484         "wifi_display.subelem.session.content_protection",
485         FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
486     { &hf_wfd_subelem_session_dev_info_time_sync,
487       { "Time Synchronization using 802.1AS",
488         "wifi_display.subelem.session.time_sync",
489         FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
490     { &hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink,
491       { "Audio un-supported at Primary sink",
492         "wifi_display.subelem.session.audio_unsupp_pri_sink",
493         FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
494     { &hf_wfd_subelem_session_dev_info_audio_only_supp_source,
495       { "Audio only support af WFD source",
496         "wifi_display.subelem.session.audio_only_supp_source",
497         FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }},
498     { &hf_wfd_subelem_session_dev_info_tdls_persistent_group,
499       { "TDLS Persistent Group",
500         "wifi_display.subelem.session.tdls_persistent_group",
501         FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }},
502     { &hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke,
503       { "TDLS Persistent Group Re-invoke",
504         "wifi_display.subelem.session.tdls_persistent_group_reinvoke",
505         FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
506     { &hf_wfd_subelem_session_dev_info_reserved,
507       { "Reserved", "wifi_display.subelem.session.reserved",
508         FT_UINT16, BASE_DEC, NULL, 0xc000, NULL, HFILL }},
509     { &hf_wfd_subelem_session_dev_info_max_throughput,
510       { "WFD Device Maximum Throughput (Mbps)",
511         "wifi_display.subelem.session.max_throughput",
512         FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
513     { &hf_wfd_subelem_session_coupled_sink_status_bitmap,
514       { "Coupled Sink Status bitmap",
515         "wifi_display.subelem.session.coupled_sink_status",
516         FT_UINT8, BASE_DEC, VALS(wfd_coupled_sink_status_bitmap), 0x03,
517         NULL, HFILL }},
518     { &hf_wfd_subelem_session_coupled_sink_reserved,
519       { "Reserved", "wifi_display.subelem.session.coupled_sink.reserved",
520         FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL }},
521     { &hf_wfd_subelem_session_coupled_sink_addr,
522       { "Coupled peer sink address",
523         "wifi_display.subelem.session.coupled_peer_sink_addr",
524         FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }}
525   };
526   static gint *ett[] = {
527     &ett_wfd_subelem,
528     &ett_wfd_dev_info_descr
529   };
530
531   proto_wifi_display = proto_register_protocol("Wi-Fi Display", "WFD",
532                                                "wifi_display");
533   proto_register_field_array(proto_wifi_display, hf, array_length(hf));
534   proto_register_subtree_array(ett, array_length(ett));
535 }
536
537 /*
538  * Editor modelines
539  *
540  * Local Variables:
541  * c-basic-offset: 2
542  * tab-width: 8
543  * indent-tabs-mode: nil
544  * End:
545  *
546  * ex: set shiftwidth=2 tabstop=8 expandtab:
547  * :indentSize=2:tabSize=8:noTabs=true:
548  */