Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-wifi-display.c
Line
Count
Source
1
/* packet-wifi-display.c
2
 *
3
 * Wi-Fi Display
4
 *
5
 * Copyright 2011-2013 Qualcomm Atheros, Inc.
6
 *
7
 * SPDX-License-Identifier: GPL-2.0-or-later
8
 */
9
10
# include "config.h"
11
12
#include <epan/packet.h>
13
#include <epan/to_str.h>
14
#include <epan/expert.h>
15
#include <epan/tfs.h>
16
#include <wsutil/array.h>
17
18
#include "packet-ieee80211.h"
19
20
void proto_register_wifi_display(void);
21
void proto_reg_handoff_wifi_display(void);
22
23
static int proto_wifi_display;
24
25
static int hf_wfd_subelem_id;
26
static int hf_wfd_subelem_len;
27
28
static int hf_wfd_subelem_dev_info_type;
29
static int hf_wfd_subelem_dev_info_coupled_sink_source;
30
static int hf_wfd_subelem_dev_info_coupled_sink_sink;
31
static int hf_wfd_subelem_dev_info_available;
32
static int hf_wfd_subelem_dev_info_wsd;
33
static int hf_wfd_subelem_dev_info_pc;
34
static int hf_wfd_subelem_dev_info_content_protection;
35
static int hf_wfd_subelem_dev_info_time_sync;
36
static int hf_wfd_subelem_dev_info_control_port;
37
static int hf_wfd_subelem_dev_info_max_throughput;
38
static int hf_wfd_subelem_dev_info_audio_unsupp_pri_sink;
39
static int hf_wfd_subelem_dev_info_audio_only_supp_source;
40
static int hf_wfd_subelem_dev_info_tdls_persistent_group;
41
static int hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke;
42
static int hf_wfd_subelem_dev_info_reserved;
43
44
static int hf_wfd_subelem_assoc_bssid;
45
46
static int hf_wfd_subelem_coupled_sink_status_bitmap;
47
static int hf_wfd_subelem_coupled_sink_reserved;
48
static int hf_wfd_subelem_coupled_sink_mac_addr;
49
50
static int hf_wfd_subelem_session_descr_len;
51
static int hf_wfd_subelem_session_dev_addr;
52
static int hf_wfd_subelem_session_assoc_bssid;
53
static int hf_wfd_subelem_session_dev_info_type;
54
static int hf_wfd_subelem_session_dev_info_coupled_sink_source;
55
static int hf_wfd_subelem_session_dev_info_coupled_sink_sink;
56
static int hf_wfd_subelem_session_dev_info_available;
57
static int hf_wfd_subelem_session_dev_info_wsd;
58
static int hf_wfd_subelem_session_dev_info_pc;
59
static int hf_wfd_subelem_session_dev_info_content_protection;
60
static int hf_wfd_subelem_session_dev_info_time_sync;
61
static int hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink;
62
static int hf_wfd_subelem_session_dev_info_audio_only_supp_source;
63
static int hf_wfd_subelem_session_dev_info_tdls_persistent_group;
64
static int hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke;
65
static int hf_wfd_subelem_session_dev_info_reserved;
66
static int hf_wfd_subelem_session_dev_info_max_throughput;
67
static int hf_wfd_subelem_session_coupled_sink_status_bitmap;
68
static int hf_wfd_subelem_session_coupled_sink_reserved;
69
static int hf_wfd_subelem_session_coupled_sink_addr;
70
static int hf_wfd_subelem_session_extra_info;
71
72
static int hf_wfd_subelem_ext_capab;
73
static int hf_wfd_subelem_ext_capab_uibc;
74
static int hf_wfd_subelem_ext_capab_i2c_read_write;
75
static int hf_wfd_subelem_ext_capab_preferred_display_mode;
76
static int hf_wfd_subelem_ext_capab_standby_resume_control;
77
static int hf_wfd_subelem_ext_capab_tdls_persistent;
78
static int hf_wfd_subelem_ext_capab_tdls_persistent_bssid;
79
static int hf_wfd_subelem_ext_capab_reserved;
80
81
static int hf_wfd_subelem_alt_mac_addr;
82
83
static int ett_wfd_subelem;
84
static int ett_wfd_dev_info_descr;
85
86
static expert_field ei_wfd_subelem_len_invalid;
87
static expert_field ei_wfd_subelem_session_descr_invalid;
88
static expert_field ei_wfd_subelem_id;
89
90
static dissector_handle_t wifi_display_ie_handle;
91
92
enum wifi_display_subelem {
93
  WFD_SUBELEM_DEVICE_INFO = 0,
94
  WFD_SUBELEM_ASSOCIATED_BSSID = 1,
95
  WFD_SUBELEM_AUDIO_FORMATS = 2,
96
  WFD_SUBELEM_VIDEO_FORMATS = 3,
97
  WFD_SUBELEM_3D_VIDEO_FORMATS = 4,
98
  WFD_SUBELEM_CONTENT_PROTECTION = 5,
99
  WFD_SUBELEM_COUPLED_SINK = 6,
100
  WFD_SUBELEM_EXT_CAPAB = 7,
101
  WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
102
  WFD_SUBELEM_SESSION_INFO = 9,
103
  WFD_SUBELEM_ALT_MAC_ADDR = 10
104
};
105
106
static const value_string wfd_subelem_ids[] = {
107
  { WFD_SUBELEM_DEVICE_INFO, "WFD Device Information" },
108
  { WFD_SUBELEM_ASSOCIATED_BSSID, "Associated BSSID" },
109
  { WFD_SUBELEM_AUDIO_FORMATS, "WFD Audio Formats" },
110
  { WFD_SUBELEM_VIDEO_FORMATS, "WFD Video Formats" },
111
  { WFD_SUBELEM_3D_VIDEO_FORMATS, "WFD 3D Video Formats" },
112
  { WFD_SUBELEM_CONTENT_PROTECTION, "WFD Content Protection" },
113
  { WFD_SUBELEM_COUPLED_SINK, "Coupled Sink Information" },
114
  { WFD_SUBELEM_EXT_CAPAB, "WFD Extended Capability" },
115
  { WFD_SUBELEM_LOCAL_IP_ADDRESS, "Local IP Address" },
116
  { WFD_SUBELEM_SESSION_INFO, "WFD Session Information" },
117
  { WFD_SUBELEM_ALT_MAC_ADDR, "Alternative MAC Address" },
118
  { 0, NULL }
119
};
120
121
122
static const value_string wfd_dev_info_types[] = {
123
  { 0, "WFD source" },
124
  { 1, "WFD primary sink" },
125
  { 2, "WFD secondary sink" },
126
  { 3, "WFD source/primary sink" },
127
  { 0, NULL }
128
};
129
130
static const value_string wfd_dev_info_avail[] = {
131
  { 0, "Not available for WFD Session" },
132
  { 1, "Available for WFD Session" },
133
  { 0, NULL }
134
};
135
136
static const value_string wfd_dev_info_pc[] = {
137
  { 0, "P2P" },
138
  { 1, "TDLS" },
139
  { 0, NULL }
140
};
141
142
static const value_string wfd_coupled_sink_status_bitmap[] = {
143
  { 0, "Not coupled/Available for Coupling" },
144
  { 1, "Coupled" },
145
  { 2, "Teardown Coupling" },
146
  { 3, "Reserved" },
147
  { 0, NULL }
148
};
149
150
static void
151
dissect_wfd_subelem_device_info(proto_tree *tree, tvbuff_t *tvb, int offset)
152
0
{
153
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_type,
154
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
155
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_coupled_sink_source,
156
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
157
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_coupled_sink_sink,
158
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
159
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_available,
160
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
161
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_wsd,
162
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
163
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_pc,
164
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
165
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_content_protection,
166
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
167
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_time_sync,
168
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
169
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_audio_unsupp_pri_sink,
170
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
171
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_audio_only_supp_source,
172
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
173
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_tdls_persistent_group,
174
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
175
0
  proto_tree_add_item(tree,
176
0
                      hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke,
177
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
178
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_reserved,
179
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
180
0
  offset += 2;
181
182
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_control_port,
183
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
184
0
  offset += 2;
185
186
0
  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_max_throughput,
187
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
188
0
}
189
190
static void
191
dissect_wfd_subelem_associated_bssid(packet_info *pinfo, proto_tree *tree,
192
                                     tvbuff_t *tvb, int offset, int len)
193
0
{
194
0
  if (len < 6) {
195
0
    expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Associated BSSID");
196
0
    return;
197
0
  }
198
0
  proto_tree_add_item(tree, hf_wfd_subelem_assoc_bssid, tvb, offset, 6, ENC_NA);
199
0
}
200
201
static void
202
dissect_wfd_subelem_coupled_sink(packet_info *pinfo, proto_tree *tree,
203
                                 tvbuff_t *tvb, int offset, int len)
204
0
{
205
0
  if (len < 1) {
206
0
    expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Coupled Sink");
207
0
    return;
208
0
  }
209
0
  proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_status_bitmap,
210
0
                      tvb, offset, 1, ENC_BIG_ENDIAN);
211
0
  proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_reserved,
212
0
                      tvb, offset, 1, ENC_BIG_ENDIAN);
213
0
  if (len < 1 + 6) {
214
0
    expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Coupled Sink");
215
0
    return;
216
0
  }
217
0
  proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_mac_addr, tvb,
218
0
                      offset + 1, 6, ENC_NA);
219
0
}
220
221
static void
222
dissect_wfd_subelem_session_info(packet_info *pinfo, proto_tree *tree,
223
                                 tvbuff_t *tvb, int offset, uint16_t len)
224
0
{
225
0
  int end = offset + len, next;
226
0
  proto_item *item;
227
0
  proto_tree *descr;
228
229
0
  while (offset < end) {
230
0
    uint8_t dlen = tvb_get_uint8(tvb, offset);
231
0
    next = offset + 1 + dlen;
232
233
0
    descr = proto_tree_add_subtree(tree, tvb, offset, 1 + dlen,
234
0
                               ett_wfd_dev_info_descr, &item, "WFD Device Info Descriptor");
235
0
    if (offset + 1 + dlen > end || dlen < 23) {
236
0
      expert_add_info(pinfo, item, &ei_wfd_subelem_session_descr_invalid);
237
0
      break;
238
0
    }
239
240
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_descr_len,
241
0
                        tvb, offset, 1, ENC_BIG_ENDIAN);
242
0
    offset++;
243
244
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_addr, tvb, offset, 6,
245
0
                        ENC_NA);
246
0
    proto_item_append_text(descr, ": %s", tvb_ether_to_str(pinfo->pool, tvb, offset));
247
0
    offset += 6;
248
249
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_assoc_bssid,
250
0
                        tvb, offset, 6, ENC_NA);
251
0
    offset += 6;
252
253
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_type,
254
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
255
0
    proto_tree_add_item(descr,
256
0
                        hf_wfd_subelem_session_dev_info_coupled_sink_source,
257
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
258
0
    proto_tree_add_item(descr,
259
0
                        hf_wfd_subelem_session_dev_info_coupled_sink_sink,
260
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
261
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_available,
262
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
263
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_wsd,
264
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
265
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_pc,
266
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
267
0
    proto_tree_add_item(descr,
268
0
                        hf_wfd_subelem_session_dev_info_content_protection,
269
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
270
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_time_sync,
271
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
272
0
    proto_tree_add_item(tree,
273
0
                        hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink,
274
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
275
0
    proto_tree_add_item(tree,
276
0
                        hf_wfd_subelem_session_dev_info_audio_only_supp_source,
277
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
278
0
    proto_tree_add_item(tree,
279
0
                        hf_wfd_subelem_session_dev_info_tdls_persistent_group,
280
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
281
0
    proto_tree_add_item(tree,
282
0
                        hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke,
283
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
284
0
    proto_tree_add_item(tree,
285
0
                        hf_wfd_subelem_session_dev_info_reserved,
286
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
287
0
    offset += 2;
288
289
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_max_throughput,
290
0
                        tvb, offset, 2, ENC_BIG_ENDIAN);
291
0
    offset += 2;
292
293
0
    proto_tree_add_item(descr,
294
0
                        hf_wfd_subelem_session_coupled_sink_status_bitmap,
295
0
                        tvb, offset, 1, ENC_BIG_ENDIAN);
296
0
    proto_tree_add_item(descr,
297
0
                        hf_wfd_subelem_session_coupled_sink_reserved,
298
0
                        tvb, offset, 1, ENC_BIG_ENDIAN);
299
0
    offset++;
300
301
0
    proto_tree_add_item(descr, hf_wfd_subelem_session_coupled_sink_addr,
302
0
                        tvb, offset, 6, ENC_NA);
303
0
    offset += 6;
304
305
0
    if (offset < next) {
306
0
      proto_tree_add_item(descr, hf_wfd_subelem_session_extra_info, tvb, offset, next - offset, ENC_NA);
307
0
    }
308
309
0
    offset = next;
310
0
  }
311
0
}
312
313
static void
314
dissect_wfd_subelem_ext_capab(packet_info *pinfo, proto_tree *tree,
315
                                 tvbuff_t *tvb, int offset, int len)
316
0
{
317
0
  if (len<2) {
318
0
    expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid,
319
0
                           "Too short Wi-Fi Display Extended Capability");
320
0
    return;
321
0
  }
322
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab,
323
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
324
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_uibc,
325
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
326
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_i2c_read_write,
327
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
328
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_preferred_display_mode,
329
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
330
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_standby_resume_control,
331
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
332
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_tdls_persistent,
333
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
334
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_tdls_persistent_bssid,
335
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
336
0
  proto_tree_add_item(tree, hf_wfd_subelem_ext_capab_reserved,
337
0
                      tvb, offset, 2, ENC_BIG_ENDIAN);
338
0
}
339
340
static void
341
dissect_wfd_subelem_alt_mac_addr(packet_info *pinfo, proto_tree *tree,
342
                                 tvbuff_t *tvb, int offset, int len)
343
0
{
344
0
  if (len<6) {
345
0
    expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid,
346
0
                           "Too short Wi-Fi Display Alternative MAC Address");
347
0
    return;
348
0
  }
349
0
  proto_tree_add_item(tree, hf_wfd_subelem_alt_mac_addr,
350
0
                      tvb, offset, 6, ENC_NA);
351
0
}
352
353
static int
354
dissect_wifi_display_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
355
0
{
356
0
  int end = tvb_reported_length(tvb);
357
0
  int offset = 0;
358
0
  uint8_t id;
359
0
  uint16_t len;
360
0
  proto_tree *wfd_tree;
361
0
  proto_item *subelem;
362
363
0
  while (offset < end) {
364
0
    if (end - offset < 2) {
365
0
      expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Packet too short for Wi-Fi Display subelement");
366
0
      break;
367
0
    }
368
369
0
    id = tvb_get_uint8(tvb, offset);
370
0
    len = tvb_get_ntohs(tvb, offset + 1);
371
0
    wfd_tree = proto_tree_add_subtree(tree, tvb, offset, 3 + len,
372
0
                                  ett_wfd_subelem, &subelem,
373
0
                                  val_to_str(pinfo->pool, id, wfd_subelem_ids,
374
0
                                             "Unknown subelement ID (%u)"));
375
0
    if (offset + 3 + len > end) {
376
0
      expert_add_info_format(pinfo, subelem, &ei_wfd_subelem_len_invalid, "Packet too short for Wi-Fi Display subelement payload");
377
0
    }
378
379
0
    proto_tree_add_item(wfd_tree, hf_wfd_subelem_id, tvb, offset, 1,
380
0
                        ENC_BIG_ENDIAN);
381
0
    offset++;
382
0
    proto_tree_add_item(wfd_tree, hf_wfd_subelem_len, tvb, offset, 2,
383
0
                        ENC_BIG_ENDIAN);
384
0
    offset += 2;
385
386
0
    switch (id) {
387
0
    case WFD_SUBELEM_DEVICE_INFO:
388
0
      dissect_wfd_subelem_device_info(wfd_tree, tvb, offset);
389
0
      break;
390
0
    case WFD_SUBELEM_ASSOCIATED_BSSID:
391
0
      dissect_wfd_subelem_associated_bssid(pinfo, wfd_tree, tvb, offset, len);
392
0
      break;
393
0
    case WFD_SUBELEM_COUPLED_SINK:
394
0
      dissect_wfd_subelem_coupled_sink(pinfo, wfd_tree, tvb, offset, len);
395
0
      break;
396
0
    case WFD_SUBELEM_SESSION_INFO:
397
0
      dissect_wfd_subelem_session_info(pinfo, wfd_tree, tvb, offset, len);
398
0
      break;
399
0
    case WFD_SUBELEM_EXT_CAPAB:
400
0
      dissect_wfd_subelem_ext_capab(pinfo, wfd_tree, tvb, offset, len);
401
0
      break;
402
0
    case WFD_SUBELEM_ALT_MAC_ADDR:
403
0
      dissect_wfd_subelem_alt_mac_addr(pinfo, wfd_tree, tvb, offset, len);
404
0
      break;
405
0
    default:
406
0
      expert_add_info(pinfo, subelem, &ei_wfd_subelem_id);
407
0
      break;
408
0
    }
409
410
0
    offset += len;
411
0
  }
412
413
0
  return tvb_captured_length(tvb);
414
0
}
415
416
void
417
proto_register_wifi_display(void)
418
14
{
419
14
  static hf_register_info hf[] = {
420
14
    { &hf_wfd_subelem_id,
421
14
      { "Subelement ID", "wifi_display.subelem.id",
422
14
        FT_UINT8, BASE_DEC, VALS(wfd_subelem_ids), 0, NULL, HFILL }},
423
14
    { &hf_wfd_subelem_len,
424
14
      { "Length", "wifi_display.subelem.length",
425
14
        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
426
14
    { &hf_wfd_subelem_dev_info_type,
427
14
      { "Device type", "wifi_display.subelem.dev_info.type",
428
14
        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_types), 0x0003, NULL, HFILL }},
429
14
    { &hf_wfd_subelem_dev_info_coupled_sink_source,
430
14
      { "Coupled sink operation supported by WFD source",
431
14
        "wifi_display.subelem.dev_info.coupled_sink_by_source",
432
14
        FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
433
14
    { &hf_wfd_subelem_dev_info_coupled_sink_sink,
434
14
      { "Coupled sink operation supported by WFD sink",
435
14
        "wifi_display.subelem.dev_info.coupled_sink_by_sink",
436
14
        FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
437
14
    { &hf_wfd_subelem_dev_info_available,
438
14
      { "Available for WFD Session", "wifi_display.subelem.dev_info.available",
439
14
        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_avail), 0x0030, NULL, HFILL }},
440
14
    { &hf_wfd_subelem_dev_info_wsd,
441
14
      { "WFD Service Discovery", "wifi_display.subelem.dev_info.wsd",
442
14
        FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }},
443
14
    { &hf_wfd_subelem_dev_info_pc,
444
14
      { "Preferred Connectivity", "wifi_display.subelem.dev_info.pc",
445
14
        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_pc), 0x0080, NULL, HFILL }},
446
14
    { &hf_wfd_subelem_dev_info_content_protection,
447
14
      { "Content Protection using HDCP2.0",
448
14
        "wifi_display.subelem.dev_info.content_protection",
449
14
        FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
450
14
    { &hf_wfd_subelem_dev_info_time_sync,
451
14
      { "Time Synchronization using 802.1AS",
452
14
        "wifi_display.subelem.dev_info.time_sync",
453
14
        FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
454
14
    { &hf_wfd_subelem_dev_info_audio_unsupp_pri_sink,
455
14
      { "Audio un-supported at Primary sink",
456
14
        "wifi_display.subelem.session.audio_unsupp_pri_sink",
457
14
        FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
458
14
    { &hf_wfd_subelem_dev_info_audio_only_supp_source,
459
14
      { "Audio only support af WFD source",
460
14
        "wifi_display.subelem.session.audio_only_supp_source",
461
14
        FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }},
462
14
    { &hf_wfd_subelem_dev_info_tdls_persistent_group,
463
14
      { "TDLS Persistent Group",
464
14
        "wifi_display.subelem.session.tdls_persistent_group",
465
14
        FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }},
466
14
    { &hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke,
467
14
      { "TDLS Persistent Group Re-invoke",
468
14
        "wifi_display.subelem.session.tdls_persistent_group_reinvoke",
469
14
        FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
470
14
    { &hf_wfd_subelem_dev_info_reserved,
471
14
      { "Reserved", "wifi_display.subelem.session.reserved",
472
14
        FT_UINT16, BASE_DEC, NULL, 0xc000, NULL, HFILL }},
473
14
    { &hf_wfd_subelem_dev_info_control_port,
474
14
      { "Session Management Control Port",
475
14
        "wifi_display.subelem.dev_info.control_port",
476
14
        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
477
14
    { &hf_wfd_subelem_dev_info_max_throughput,
478
14
      { "WFD Device Maximum Throughput (Mbps)",
479
14
        "wifi_display.subelem.dev_info.max_throughput",
480
14
        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
481
14
    { &hf_wfd_subelem_assoc_bssid,
482
14
      { "Associated BSSID", "wifi_display.subelem.assoc_bssid.bssid",
483
14
        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
484
14
    { &hf_wfd_subelem_coupled_sink_status_bitmap,
485
14
      { "Coupled Sink Status bitmap",
486
14
        "wifi_display.subelem.coupled_sink.status",
487
14
        FT_UINT8, BASE_DEC, VALS(wfd_coupled_sink_status_bitmap), 0x03,
488
14
        NULL, HFILL }},
489
14
    { &hf_wfd_subelem_coupled_sink_reserved,
490
14
      { "Reserved", "wifi_display.subelem.coupled_sink.reserved",
491
14
        FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL }},
492
14
    { &hf_wfd_subelem_coupled_sink_mac_addr,
493
14
      { "Coupled Sink MAC Address",
494
14
        "wifi_display.subelem.coupled_sink.mac_addr",
495
14
        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
496
14
    { &hf_wfd_subelem_session_descr_len,
497
14
      { "Descriptor length",
498
14
        "wifi_display.subelem.session.descr_len",
499
14
        FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
500
14
    { &hf_wfd_subelem_session_dev_addr,
501
14
      { "Device address",
502
14
        "wifi_display.subelem.session.device_address",
503
14
        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
504
14
    { &hf_wfd_subelem_session_assoc_bssid,
505
14
      { "Associated BSSID",
506
14
        "wifi_display.subelem.session.associated_bssid",
507
14
        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
508
14
    { &hf_wfd_subelem_session_dev_info_type,
509
14
      { "Device type", "wifi_display.subelem.session.type",
510
14
        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_types), 0x0003, NULL, HFILL }},
511
14
    { &hf_wfd_subelem_session_dev_info_coupled_sink_source,
512
14
      { "Coupled sink operation supported by WFD source",
513
14
        "wifi_display.subelem.session.coupled_sink_by_source",
514
14
        FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
515
14
    { &hf_wfd_subelem_session_dev_info_coupled_sink_sink,
516
14
      { "Coupled sink operation supported by WFD sink",
517
14
        "wifi_display.subelem.session.coupled_sink_by_sink",
518
14
        FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
519
14
    { &hf_wfd_subelem_session_dev_info_available,
520
14
      { "Available for WFD Session", "wifi_display.subelem.session.available",
521
14
        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_avail), 0x0030, NULL, HFILL }},
522
14
    { &hf_wfd_subelem_session_dev_info_wsd,
523
14
      { "WFD Service Discovery", "wifi_display.subelem.session.wsd",
524
14
        FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }},
525
14
    { &hf_wfd_subelem_session_dev_info_pc,
526
14
      { "Preferred Connectivity", "wifi_display.subelem.session.pc",
527
14
        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_pc), 0x0080, NULL, HFILL }},
528
14
    { &hf_wfd_subelem_session_dev_info_content_protection,
529
14
      { "Content Protection using HDCP2.0",
530
14
        "wifi_display.subelem.session.content_protection",
531
14
        FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
532
14
    { &hf_wfd_subelem_session_dev_info_time_sync,
533
14
      { "Time Synchronization using 802.1AS",
534
14
        "wifi_display.subelem.session.time_sync",
535
14
        FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
536
14
    { &hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink,
537
14
      { "Audio un-supported at Primary sink",
538
14
        "wifi_display.subelem.session.audio_unsupp_pri_sink",
539
14
        FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
540
14
    { &hf_wfd_subelem_session_dev_info_audio_only_supp_source,
541
14
      { "Audio only support af WFD source",
542
14
        "wifi_display.subelem.session.audio_only_supp_source",
543
14
        FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }},
544
14
    { &hf_wfd_subelem_session_dev_info_tdls_persistent_group,
545
14
      { "TDLS Persistent Group",
546
14
        "wifi_display.subelem.session.tdls_persistent_group",
547
14
        FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }},
548
14
    { &hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke,
549
14
      { "TDLS Persistent Group Re-invoke",
550
14
        "wifi_display.subelem.session.tdls_persistent_group_reinvoke",
551
14
        FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
552
14
    { &hf_wfd_subelem_session_dev_info_reserved,
553
14
      { "Reserved", "wifi_display.subelem.session.reserved",
554
14
        FT_UINT16, BASE_DEC, NULL, 0xc000, NULL, HFILL }},
555
14
    { &hf_wfd_subelem_session_dev_info_max_throughput,
556
14
      { "WFD Device Maximum Throughput (Mbps)",
557
14
        "wifi_display.subelem.session.max_throughput",
558
14
        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
559
14
    { &hf_wfd_subelem_session_coupled_sink_status_bitmap,
560
14
      { "Coupled Sink Status bitmap",
561
14
        "wifi_display.subelem.session.coupled_sink_status",
562
14
        FT_UINT8, BASE_DEC, VALS(wfd_coupled_sink_status_bitmap), 0x03,
563
14
        NULL, HFILL }},
564
14
    { &hf_wfd_subelem_session_coupled_sink_reserved,
565
14
      { "Reserved", "wifi_display.subelem.session.coupled_sink.reserved",
566
14
        FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL }},
567
14
    { &hf_wfd_subelem_session_coupled_sink_addr,
568
14
      { "Coupled peer sink address",
569
14
        "wifi_display.subelem.session.coupled_peer_sink_addr",
570
14
        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
571
14
    { &hf_wfd_subelem_session_extra_info,
572
14
      { "Extra info in the end of descriptor",
573
14
        "wifi_display.subelem.session.extra_info",
574
14
        FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
575
14
    { &hf_wfd_subelem_ext_capab,
576
14
      { "WFD Extended Capability Bitmap",
577
14
        "wifi_display.subelem.ext_capab",
578
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
579
14
    { &hf_wfd_subelem_ext_capab_uibc,
580
14
      { "User Input Back Channel(UIBC)",
581
14
        "wifi_display.subelem.ext_capab.uibc",
582
14
        FT_BOOLEAN, 16, TFS (&tfs_supported_not_supported), 0x0001, NULL, HFILL }},
583
14
    { &hf_wfd_subelem_ext_capab_i2c_read_write,
584
14
      { "I2C Read/Write",
585
14
        "wifi_display.subelem.ext_capab.i2c_read_write",
586
14
        FT_BOOLEAN, 16, TFS (&tfs_supported_not_supported), 0x0002, NULL, HFILL }},
587
14
    { &hf_wfd_subelem_ext_capab_preferred_display_mode,
588
14
      { "Preferred Display Mode",
589
14
        "wifi_display.subelem.ext_capab.preferred_display_mode",
590
14
        FT_BOOLEAN, 16, TFS (&tfs_supported_not_supported), 0x0004, NULL, HFILL }},
591
14
    { &hf_wfd_subelem_ext_capab_standby_resume_control,
592
14
      { "Standby and Resume Control",
593
14
        "wifi_display.subelem.ext_capab.standby_resume_control",
594
14
        FT_BOOLEAN, 16, TFS (&tfs_supported_not_supported), 0x0008, NULL, HFILL }},
595
14
    { &hf_wfd_subelem_ext_capab_tdls_persistent,
596
14
      { "TDLS Persistent",
597
14
        "wifi_display.subelem.ext_capab.tdls_persistent",
598
14
        FT_BOOLEAN, 16, TFS (&tfs_supported_not_supported), 0x0010, NULL, HFILL }},
599
14
    { &hf_wfd_subelem_ext_capab_tdls_persistent_bssid,
600
14
      { "TDLS Persistent BSSID",
601
14
        "wifi_display.subelem.ext_capab.tdls_persistent_bssid",
602
14
        FT_BOOLEAN, 16, TFS (&tfs_supported_not_supported), 0x0020, NULL, HFILL }},
603
14
    { &hf_wfd_subelem_ext_capab_reserved,
604
14
      { "Reserved", "wifi_display.subelem.ext_capab.reserved",
605
14
        FT_UINT16, BASE_HEX, NULL, 0xffc0, NULL, HFILL }},
606
14
    { &hf_wfd_subelem_alt_mac_addr,
607
14
      { "Alternative MAC Address", "wifi_display.subelem.alt_mac_addr",
608
14
        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
609
14
  };
610
14
  static int *ett[] = {
611
14
    &ett_wfd_subelem,
612
14
    &ett_wfd_dev_info_descr
613
14
  };
614
615
14
  static ei_register_info ei[] = {
616
14
      { &ei_wfd_subelem_len_invalid, { "wifi_display.subelem.length.invalid", PI_MALFORMED, PI_ERROR, "Subelement length invalid", EXPFILL }},
617
14
      { &ei_wfd_subelem_session_descr_invalid, { "wifi_display.subelem.session.descr_invalid", PI_MALFORMED, PI_ERROR, "Invalid WFD Device Info Descriptor", EXPFILL }},
618
14
      { &ei_wfd_subelem_id, { "wifi_display.subelem.id.unknown", PI_PROTOCOL, PI_WARN, "Unknown subelement payload", EXPFILL }},
619
14
  };
620
621
14
  expert_module_t* expert_wifi_display;
622
623
14
  proto_wifi_display = proto_register_protocol("Wi-Fi Display", "WFD", "wifi_display");
624
14
  proto_register_field_array(proto_wifi_display, hf, array_length(hf));
625
14
  proto_register_subtree_array(ett, array_length(ett));
626
627
14
  expert_wifi_display = expert_register_protocol(proto_wifi_display);
628
14
  expert_register_field_array(expert_wifi_display, ei, array_length(ei));
629
630
14
  wifi_display_ie_handle = register_dissector("wifi_display_ie", dissect_wifi_display_ie, proto_wifi_display);
631
632
14
}
633
634
void
635
proto_reg_handoff_wifi_display(void)
636
14
{
637
14
  dissector_add_uint("wlan.ie.wifi_alliance.subtype", WFA_SUBTYPE_WIFI_DISPLAY, wifi_display_ie_handle);
638
14
}
639
640
/*
641
 * Editor modelines
642
 *
643
 * Local Variables:
644
 * c-basic-offset: 2
645
 * tab-width: 8
646
 * indent-tabs-mode: nil
647
 * End:
648
 *
649
 * ex: set shiftwidth=2 tabstop=8 expandtab:
650
 * :indentSize=2:tabSize=8:noTabs=true:
651
 */