HTTPS (almost) everywhere.
[metze/wireshark/wip.git] / epan / dissectors / packet-usb-video.c
1 /* packet-usb-video.c
2  *
3  * Forked from packet-usb-masstorage.c 35224 2010-12-20 05:35:29Z guy
4  * which was authored by Ronnie Sahlberg (2006)
5  *
6  * usb video dissector
7  * Steven J. Magnani 2013
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include "config.h"
13
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include "packet-usb.h"
17
18 void proto_register_usb_vid(void);
19 void proto_reg_handoff_usb_vid(void);
20
21 /* References are to sections in USB Video Class specifications -
22  * specifically V1.5, but versions have tended to keep
23  * the same numbering (as of this writing).
24  *
25  * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_5.zip
26  */
27
28 /* Table 2-1. Interrupt originators */
29 #define INT_VIDEOCONTROL               1
30 #define INT_VIDEOSTREAMING             2
31
32 #define INT_ORIGINATOR_MASK            0xF
33
34 /* Table 2-2. Video Control Status Packet bAttribute */
35 #define CONTROL_CHANGE_VALUE           0x00
36 #define CONTROL_CHANGE_INFO            0x01
37 #define CONTROL_CHANGE_FAILURE         0x02
38 #define CONTROL_CHANGE_MIN             0x03   /* UVC 1.5+ */
39 #define CONTROL_CHANGE_MAX             0x04   /* UVC 1.5+ */
40
41
42 /* A.2 Video Interface Subclass Codes */
43 #define SC_UNDEFINED                   0
44 #define SC_VIDEOCONTROL                1
45 #define SC_VIDEOSTREAMING              2
46 #define SC_VIDEO_INTERFACE_COLLECTION  3
47
48 /* A.4. Video Class-Specific Descriptor Types */
49 #define CS_INTERFACE       0x24
50 #define CS_ENDPOINT        0x25
51
52 /* A.5 Video Class-Specific VC Interface Descriptor Subtypes */
53 #define VC_HEADER           1
54 #define VC_INPUT_TERMINAL   2
55 #define VC_OUTPUT_TERMINAL  3
56 #define VC_SELECTOR_UNIT    4
57 #define VC_PROCESSING_UNIT  5
58 #define VC_EXTENSION_UNIT   6
59 #define VC_ENCODING_UNIT    7
60
61 /* A.6 Video Class-Specific VS Interface Descriptor Subtypes */
62 #define VS_UNDEFINED             0x00
63 #define VS_INPUT_HEADER          0x01
64 #define VS_OUTPUT_HEADER         0x02
65 #define VS_STILL_IMAGE_FRAME     0x03
66 #define VS_FORMAT_UNCOMPRESSED   0x04
67 #define VS_FRAME_UNCOMPRESSED    0x05
68 #define VS_FORMAT_MJPEG          0x06
69 #define VS_FRAME_MJPEG           0x07
70 #define VS_FORMAT_MPEG1          0x08     /* Pre-UVC 1.1 */
71 #define VS_FORMAT_MPEG2PS        0x09     /* Pre-UVC 1.1 */
72 #define VS_FORMAT_MPEG2TS        0x0A
73 #define VS_FORMAT_MPEG4SL        0x0B     /* Pre-UVC 1.1 */
74 #define VS_FORMAT_DV             0x0C
75 #define VS_COLORFORMAT           0x0D
76 #define VS_FORMAT_VENDOR         0x0E     /* Pre-UVC 1.1 */
77 #define VS_FRAME_VENDOR          0x0F     /* Pre-UVC 1.1 */
78 #define VS_FORMAT_FRAME_BASED    0x10
79 #define VS_FRAME_FRAME_BASED     0x11
80 #define VS_FORMAT_STREAM_BASED   0x12
81 #define VS_FORMAT_H264           0x13       /* UVC 1.5 */
82 #define VS_FRAME_H264            0x14       /* UVC 1.5 */
83 #define VS_FORMAT_H264_SIMULCAST 0x15       /* UVC 1.5 */
84 #define VS_FORMAT_VP8            0x16       /* UVC 1.5 */
85 #define VS_FRAME_VP8             0x17       /* UVC 1.5 */
86 #define VS_FORMAT_VP8_SIMULCAST  0x18       /* UVC 1.5 */
87
88 /* A.7 Video Class-Specific Endpoint Descriptor Subtypes */
89 #define EP_INTERRUPT           0x03
90
91 /* A.9.1 Video Control Interface Control Selectors */
92 #define VC_CONTROL_UNDEFINED                      0x00
93 #define VC_VIDEO_POWER_MODE_CONTROL               0x01
94 #define VC_REQUEST_ERROR_CODE_CONTROL             0x02
95 #define VC_REQUEST_INDICATE_HOST_CLOCK_CONTROL    0x03  /* Pre-UVC 1.1 */
96
97 /* A.9.3 Selector Unit Control Selectors */
98 #define SU_CONTROL_UNDEFINED                      0x00
99 #define SU_INPUT_SELECT_CONTROL                   0x01
100
101 /* A.9.4 Camera Terminal Control Selectors */
102 #define CT_CONTROL_UNDEFINED                      0x00
103 #define CT_SCANNING_MODE_CONTROL                  0x01
104 #define CT_AE_MODE_CONTROL                        0x02
105 #define CT_AE_PRIORITY_CONTROL                    0x03
106 #define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL         0x04
107 #define CT_EXPOSURE_TIME_RELATIVE_CONTROL         0x05
108 #define CT_FOCUS_ABSOLUTE_CONTROL                 0x06
109 #define CT_FOCUS_RELATIVE_CONTROL                 0x07
110 #define CT_FOCUS_AUTO_CONTROL                     0x08
111 #define CT_IRIS_ABSOLUTE_CONTROL                  0x09
112 #define CT_IRIS_RELATIVE_CONTROL                  0x0A
113 #define CT_ZOOM_ABSOLUTE_CONTROL                  0x0B
114 #define CT_ZOOM_RELATIVE_CONTROL                  0x0C
115 #define CT_PANTILT_ABSOLUTE_CONTROL               0x0D
116 #define CT_PANTILT_RELATIVE_CONTROL               0x0E
117 #define CT_ROLL_ABSOLUTE_CONTROL                  0x0F
118 #define CT_ROLL_RELATIVE_CONTROL                  0x10
119 #define CT_PRIVACY_CONTROL                        0x11
120 #define CT_FOCUS_SIMPLE_CONTROL                   0x12  /* UVC 1.5 */
121 #define CT_WINDOW_CONTROL                         0x13  /* UVC 1.5 */
122 #define CT_REGION_OF_INTEREST_CONTROL             0x14  /* UVC 1.5 */
123
124 /* A.9.5 Processing Unit Control Selectors */
125 #define PU_CONTROL_UNDEFINED                      0x00
126 #define PU_BACKLIGHT_COMPENSATION_CONTROL         0x01
127 #define PU_BRIGHTNESS_CONTROL                     0x02
128 #define PU_CONTRAST_CONTROL                       0x03
129 #define PU_GAIN_CONTROL                           0x04
130 #define PU_POWER_LINE_FREQUENCY_CONTROL           0x05
131 #define PU_HUE_CONTROL                            0x06
132 #define PU_SATURATION_CONTROL                     0x07
133 #define PU_SHARPNESS_CONTROL                      0x08
134 #define PU_GAMMA_CONTROL                          0x09
135 #define PU_WHITE_BALANCE_TEMPERATURE_CONTROL      0x0A
136 #define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B
137 #define PU_WHITE_BALANCE_COMPONENT_CONTROL        0x0C
138 #define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL   0x0D
139 #define PU_DIGITAL_MULTIPLIER_CONTROL             0x0E
140 #define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL       0x0F
141 #define PU_HUE_AUTO_CONTROL                       0x10
142 #define PU_ANALOG_VIDEO_STANDARD_CONTROL          0x11
143 #define PU_ANALOG_LOCK_STATUS_CONTROL             0x12
144 #define PU_CONTRAST_AUTO_CONTROL                  0x13
145
146 /* A.9.7 VideoStreaming Interface Control Selectors */
147 #define VS_CONTROL_UNDEFINED                      0x00
148 #define VS_PROBE_CONTROL                          0x01
149 #define VS_COMMIT_CONTROL                         0x02
150 #define VS_STILL_PROBE_CONTROL                    0x03
151 #define VS_STILL_COMMIT_CONTROL                   0x04
152 #define VS_STILL_IMAGE_TRIGGER_CONTROL            0x05
153 #define VS_STREAM_ERROR_CODE_CONTROL              0x06
154 #define VS_GENERATE_KEY_FRAME_CONTROL             0x07
155 #define VS_UPDATE_FRAME_SEGMENT_CONTROL           0x08
156 #define VS_SYNCH_DELAY_CONTROL                    0x09
157
158 /* Appendix B Terminal Types */
159 #define TT_VENDOR_SPECIFIC          0x100
160 #define TT_STREAMING                0x101
161 #define ITT_VENDOR_SPECIFIC         0x200
162 #define ITT_CAMERA                  0x201
163 #define ITT_MEDIA_TRANSPORT_INPUT   0x202
164 #define OTT_VENDOR_SPECIFIC         0x300
165 #define OTT_DISPLAY                 0x301
166 #define OTT_MEDIA_TRANSPORT_OUTPUT  0x302
167 #define EXTERNAL_VENDOR_SPECIFIC    0x400
168 #define COMPOSITE_CONNECTOR         0x401
169 #define SVIDEO_CONNECTOR            0x402
170 #define COMPONENT_CONNECTOR         0x403
171
172 /* Table 2-2 Status Packet Format (VideoControl Interface as the Originator) */
173 #define CONTROL_INTERRUPT_EVENT_CONTROL_CHANGE  0
174
175 /* Table 4-7 Request Error Code Control bRequestErrorCode */
176 #define UVC_ERROR_NONE              0
177 #define UVC_ERROR_NOT_READY         1
178 #define UVC_ERROR_WRONG_STATE       2
179 #define UVC_ERROR_POWER             3
180 #define UVC_ERROR_OUT_OF_RANGE      4
181 #define UVC_ERROR_INVALID_UNIT      5
182 #define UVC_ERROR_INVALID_CONTROL   6
183 #define UVC_ERROR_INVALID_REQUEST   7
184 #define UVC_ERROR_INVALID_VALUE     8
185 #define UVC_ERROR_UNKNOWN           255
186
187 /* A.8 Video Class-Specific Request Codes */
188 #define USB_SETUP_SET_CUR           0x01
189 #define USB_SETUP_SET_CUR_ALL       0x11    /* UVC 1.5 */
190 #define USB_SETUP_GET_CUR           0x81
191 #define USB_SETUP_GET_MIN           0x82
192 #define USB_SETUP_GET_MAX           0x83
193 #define USB_SETUP_GET_RES           0x84
194 #define USB_SETUP_GET_LEN           0x85
195 #define USB_SETUP_GET_INFO          0x86
196 #define USB_SETUP_GET_DEF           0x87
197 #define USB_SETUP_GET_CUR_ALL       0x91    /* UVC 1.5 */
198 #define USB_SETUP_GET_MIN_ALL       0x92    /* UVC 1.5 */
199 #define USB_SETUP_GET_MAX_ALL       0x93    /* UVC 1.5 */
200 #define USB_SETUP_GET_RES_ALL       0x94    /* UVC 1.5 */
201 #define USB_SETUP_GET_DEF_ALL       0x97    /* UVC 1.5 */
202
203 /* protocols and header fields */
204 static int proto_usb_vid = -1;
205
206 static int hf_usb_vid_control_entity    = -1;
207 static int hf_usb_vid_control_interface = -1;
208 static int hf_usb_vid_control_selector  = -1;
209 static int hf_usb_vid_epdesc_subtype = -1;
210 static int hf_usb_vid_epdesc_max_transfer_sz = -1;
211 static int hf_usb_vid_control_ifdesc_subtype = -1;
212 static int hf_usb_vid_control_ifdesc_terminal_id = -1;
213 static int hf_usb_vid_control_ifdesc_terminal_type = -1;
214 static int hf_usb_vid_control_ifdesc_assoc_terminal = -1;
215 static int hf_usb_vid_streaming_ifdesc_subtype = -1;
216 static int hf_usb_vid_streaming_ifdesc_bNumFormats = -1;
217 static int hf_usb_vid_control_ifdesc_unit_id = -1;
218 static int hf_usb_vid_request = -1;
219 static int hf_usb_vid_length = -1;
220 static int hf_usb_vid_interrupt_bStatusType = -1;
221 static int hf_usb_vid_interrupt_bOriginator = -1;
222 static int hf_usb_vid_interrupt_bAttribute = -1;
223 static int hf_usb_vid_control_interrupt_bEvent = -1;
224 static int hf_usb_vid_control_ifdesc_bcdUVC = -1;
225 static int hf_usb_vid_ifdesc_wTotalLength = -1;
226 static int hf_usb_vid_control_ifdesc_dwClockFrequency = -1;
227 static int hf_usb_vid_control_ifdesc_bInCollection = -1;
228 static int hf_usb_vid_control_ifdesc_baInterfaceNr = -1;
229 static int hf_usb_vid_control_ifdesc_iTerminal = -1;
230 static int hf_usb_vid_control_ifdesc_src_id = -1;
231 static int hf_usb_vid_cam_objective_focal_len_min = -1;
232 static int hf_usb_vid_cam_objective_focal_len_max = -1;
233 static int hf_usb_vid_cam_ocular_focal_len = -1;
234 static int hf_usb_vid_bControlSize = -1;
235 static int hf_usb_vid_bmControl = -1;
236 static int hf_usb_vid_bmControl_bytes = -1;
237 static int hf_usb_vid_control_default = -1;
238 static int hf_usb_vid_control_min = -1;
239 static int hf_usb_vid_control_max = -1;
240 static int hf_usb_vid_control_res = -1;
241 static int hf_usb_vid_control_cur = -1;
242 static int hf_usb_vid_control_info = -1;
243 static int hf_usb_vid_control_info_D[7]   = { -1, -1, -1, -1, -1, -1, -1 };
244 static int hf_usb_vid_control_length = -1;
245 static int hf_usb_vid_cam_control_D[22]   = { -1, -1, -1, -1, -1, -1, -1, -1,
246                                               -1, -1, -1, -1, -1, -1, -1, -1,
247                                               -1, -1, -1, -1, -1, -1 };
248 static int hf_usb_vid_proc_control_D[19]  = { -1, -1, -1, -1, -1, -1, -1, -1,
249                                               -1, -1, -1, -1, -1, -1, -1, -1,
250                                               -1, -1, -1 };
251 static int hf_usb_vid_proc_standards_D[6] = { -1, -1, -1, -1, -1, -1 };
252 static int hf_usb_vid_exten_guid = -1;
253 static int hf_usb_vid_exten_num_controls = -1;
254 static int hf_usb_vid_num_inputs = -1;
255 static int hf_usb_vid_sources = -1;
256 static int hf_usb_vid_streaming_bmInfo = -1;
257 static int hf_usb_vid_streaming_info_D[1] = { -1 };
258 static int hf_usb_vid_streaming_terminal_link = -1;
259 static int hf_usb_vid_streaming_still_capture_method = -1;
260 static int hf_usb_vid_streaming_trigger_support = -1;
261 static int hf_usb_vid_streaming_trigger_usage = -1;
262 static int hf_usb_vid_streaming_control_D[6] = { -1, -1, -1, -1, -1, -1 };
263 static int hf_usb_vid_format_index = -1;
264 static int hf_usb_vid_format_num_frame_descriptors = -1;
265 static int hf_usb_vid_format_guid = -1;
266 static int hf_usb_vid_format_bits_per_pixel = -1;
267 static int hf_usb_vid_default_frame_index = -1;
268 static int hf_usb_vid_aspect_ratio_x = -1;
269 static int hf_usb_vid_aspect_ratio_y = -1;
270 static int hf_usb_vid_interlace_flags = -1;
271 static int hf_usb_vid_is_interlaced = -1;
272 static int hf_usb_vid_interlaced_fields = -1;
273 static int hf_usb_vid_field_1_first = -1;
274 static int hf_usb_vid_field_pattern = -1;
275 static int hf_usb_vid_copy_protect = -1;
276 static int hf_usb_vid_variable_size = -1;
277 static int hf_usb_vid_frame_index = -1;
278 static int hf_usb_vid_frame_capabilities = -1;
279 static int hf_usb_vid_frame_stills_supported = -1;
280 static int hf_usb_vid_frame_fixed_frame_rate = -1;
281 static int hf_usb_vid_frame_width = -1;
282 static int hf_usb_vid_frame_height = -1;
283 static int hf_usb_vid_frame_min_bit_rate = -1;
284 static int hf_usb_vid_frame_max_bit_rate = -1;
285 static int hf_usb_vid_frame_max_frame_sz = -1;
286 static int hf_usb_vid_frame_default_interval = -1;
287 static int hf_usb_vid_frame_bytes_per_line = -1;
288 static int hf_usb_vid_mjpeg_flags = -1;
289 static int hf_usb_vid_mjpeg_fixed_samples = -1;
290 static int hf_usb_vid_probe_hint = -1;
291 static int hf_usb_vid_probe_hint_D[5] = { -1, -1, -1, -1, -1 };
292 static int hf_usb_vid_frame_interval = -1;
293 static int hf_usb_vid_probe_key_frame_rate = -1;
294 static int hf_usb_vid_probe_p_frame_rate = -1;
295 static int hf_usb_vid_probe_comp_quality = -1;
296 static int hf_usb_vid_probe_comp_window = -1;
297 static int hf_usb_vid_probe_delay = -1;
298 static int hf_usb_vid_probe_max_frame_sz = -1;
299 static int hf_usb_vid_probe_max_payload_sz = -1;
300 static int hf_usb_vid_probe_clock_freq = -1;
301 static int hf_usb_vid_probe_framing = -1;
302 static int hf_usb_vid_probe_framing_D[2] = { -1, -1 };
303 static int hf_usb_vid_probe_preferred_ver = -1;
304 static int hf_usb_vid_probe_min_ver = -1;
305 static int hf_usb_vid_probe_max_ver = -1;
306 static int hf_usb_vid_frame_interval_type = -1;
307 static int hf_usb_vid_frame_min_interval = -1;
308 static int hf_usb_vid_frame_max_interval = -1;
309 static int hf_usb_vid_frame_step_interval = -1;
310 static int hf_usb_vid_color_primaries = -1;
311 static int hf_usb_vid_transfer_characteristics = -1;
312 static int hf_usb_vid_matrix_coefficients = -1;
313 static int hf_usb_vid_max_multiplier = -1;
314 static int hf_usb_vid_iProcessing = -1;
315 static int hf_usb_vid_iExtension = -1;
316 static int hf_usb_vid_iSelector = -1;
317 static int hf_usb_vid_proc_standards = -1;
318 static int hf_usb_vid_request_error = -1;
319 static int hf_usb_vid_descriptor_data = -1;
320 static int hf_usb_vid_control_data = -1;
321 static int hf_usb_vid_control_value = -1;
322 static int hf_usb_vid_value_data = -1;
323
324
325 /* Subtrees */
326 static gint ett_usb_vid = -1;
327 static gint ett_descriptor_video_endpoint = -1;
328 static gint ett_descriptor_video_control = -1;
329 static gint ett_descriptor_video_streaming = -1;
330 static gint ett_camera_controls = -1;
331 static gint ett_processing_controls = -1;
332 static gint ett_streaming_controls = -1;
333 static gint ett_streaming_info = -1;
334 static gint ett_interlace_flags = -1;
335 static gint ett_frame_capability_flags = -1;
336 static gint ett_mjpeg_flags = -1;
337 static gint ett_video_probe = -1;
338 static gint ett_probe_hint = -1;
339 static gint ett_probe_framing = -1;
340 static gint ett_video_standards = -1;
341 static gint ett_control_capabilities = -1;
342
343 static expert_field ei_usb_vid_subtype_unknown = EI_INIT;
344 static expert_field ei_usb_vid_bitmask_len = EI_INIT;
345
346 /* Lookup tables */
347 static const value_string vc_ep_descriptor_subtypes[] = {
348     { EP_INTERRUPT, "Interrupt" },
349     { 0, NULL }
350 };
351
352 static const value_string vid_descriptor_type_vals[] = {
353     {CS_INTERFACE, "video class interface"},
354     {CS_ENDPOINT, "video class endpoint"},
355     {0,NULL}
356 };
357 static value_string_ext vid_descriptor_type_vals_ext =
358     VALUE_STRING_EXT_INIT(vid_descriptor_type_vals);
359
360 static const value_string vc_if_descriptor_subtypes[] = {
361     { VC_HEADER,              "Header" },
362     { VC_INPUT_TERMINAL,      "Input Terminal" },
363     { VC_OUTPUT_TERMINAL,     "Output Terminal" },
364     { VC_SELECTOR_UNIT,       "Selector Unit" },
365     { VC_PROCESSING_UNIT,     "Processing Unit" },
366     { VC_EXTENSION_UNIT,      "Extension Unit" },
367     { VC_ENCODING_UNIT,       "Encoding Unit" },
368     { 0, NULL }
369 };
370 static value_string_ext vc_if_descriptor_subtypes_ext =
371     VALUE_STRING_EXT_INIT(vc_if_descriptor_subtypes);
372
373 static const value_string cs_control_interface[] = {
374     { VC_CONTROL_UNDEFINED,          "Undefined" },
375     { VC_VIDEO_POWER_MODE_CONTROL,   "Video Power Mode" },
376     { VC_REQUEST_ERROR_CODE_CONTROL, "Request Error Code" },
377     { VC_REQUEST_INDICATE_HOST_CLOCK_CONTROL, "Request Indicate Host Clock" },
378     { 0, NULL }
379 };
380 static value_string_ext cs_control_interface_ext =
381     VALUE_STRING_EXT_INIT(cs_control_interface);
382
383 static const value_string cs_streaming_interface[] = {
384     { VS_CONTROL_UNDEFINED,            "Undefined" },
385     { VS_PROBE_CONTROL,                "Probe" },
386     { VS_COMMIT_CONTROL,               "Commit" },
387     { VS_STILL_PROBE_CONTROL,          "Still Probe" },
388     { VS_STILL_COMMIT_CONTROL,         "Still Commit" },
389     { VS_STILL_IMAGE_TRIGGER_CONTROL,  "Still Image Trigger" },
390     { VS_STREAM_ERROR_CODE_CONTROL,    "Stream Error Code" },
391     { VS_GENERATE_KEY_FRAME_CONTROL,   "Generate Key Frame" },
392     { VS_UPDATE_FRAME_SEGMENT_CONTROL, "Update Frame Segment" },
393     { VS_SYNCH_DELAY_CONTROL,          "Synch Delay" },
394     { 0, NULL }
395 };
396 static value_string_ext cs_streaming_interface_ext =
397     VALUE_STRING_EXT_INIT(cs_streaming_interface);
398
399 static const value_string cs_selector_unit[] = {
400     { SU_CONTROL_UNDEFINED,              "Undefined" },
401     { SU_INPUT_SELECT_CONTROL,           "Input Select" },
402     { 0, NULL }
403 };
404 static value_string_ext cs_selector_unit_ext =
405     VALUE_STRING_EXT_INIT(cs_selector_unit);
406
407 static const value_string cs_camera_terminal[] = {
408     { CT_CONTROL_UNDEFINED,              "Undefined" },
409     { CT_SCANNING_MODE_CONTROL,          "Scanning Mode" },
410     { CT_AE_MODE_CONTROL,                "Auto-Exposure Mode" },
411     { CT_AE_PRIORITY_CONTROL,            "Auto-Exposure Priority" },
412     { CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, "Exposure Time (Absolute)" },
413     { CT_EXPOSURE_TIME_RELATIVE_CONTROL, "Exposure Time (Relative)" },
414     { CT_FOCUS_ABSOLUTE_CONTROL,         "Focus (Absolute)" },
415     { CT_FOCUS_RELATIVE_CONTROL,         "Focus (Relative)" },
416     { CT_FOCUS_AUTO_CONTROL,             "Focus, Auto" },
417     { CT_IRIS_ABSOLUTE_CONTROL,          "Iris (Absolute)" },
418     { CT_IRIS_RELATIVE_CONTROL,          "Iris (Relative)" },
419     { CT_ZOOM_ABSOLUTE_CONTROL,          "Zoom (Absolute)" },
420     { CT_ZOOM_RELATIVE_CONTROL,          "Zoom (Relative)" },
421     { CT_PANTILT_ABSOLUTE_CONTROL,       "PanTilt (Absolute)" },
422     { CT_PANTILT_RELATIVE_CONTROL,       "PanTilt (Relative)" },
423     { CT_ROLL_ABSOLUTE_CONTROL,          "Roll (Absolute)" },
424     { CT_ROLL_RELATIVE_CONTROL,          "Roll (Relative)" },
425     { CT_PRIVACY_CONTROL,                "Privacy" },
426     { CT_FOCUS_SIMPLE_CONTROL,           "Focus (Simple)" },
427     { CT_WINDOW_CONTROL,                 "Window" },
428     { CT_REGION_OF_INTEREST_CONTROL,     "Region of Interest" },
429     { 0, NULL }
430 };
431 static value_string_ext cs_camera_terminal_ext =
432     VALUE_STRING_EXT_INIT(cs_camera_terminal);
433
434 static const value_string cs_processing_unit[] = {
435     { PU_CONTROL_UNDEFINED,                     "Undefined" },
436     { PU_BACKLIGHT_COMPENSATION_CONTROL,        "Backlight Compensation" },
437     { PU_BRIGHTNESS_CONTROL,                    "Brightness" },
438     { PU_CONTRAST_CONTROL,                      "Contrast" },
439     { PU_GAIN_CONTROL,                          "Gain" },
440     { PU_POWER_LINE_FREQUENCY_CONTROL,          "Power Line Frequency" },
441     { PU_HUE_CONTROL,                           "Hue" },
442     { PU_SATURATION_CONTROL,                    "Saturation" },
443     { PU_SHARPNESS_CONTROL,                     "Sharpness" },
444     { PU_GAMMA_CONTROL,                         "Gamma" },
445     { PU_WHITE_BALANCE_TEMPERATURE_CONTROL,     "White Balance Temperature" },
446     { PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,"White Balance Temperature Auto" },
447     { PU_WHITE_BALANCE_COMPONENT_CONTROL,       "White Balance Component" },
448     { PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,  "White Balance Component Auto" },
449     { PU_DIGITAL_MULTIPLIER_CONTROL,            "Digital Multiplier" },
450     { PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,      "Digital Multiplier Limit" },
451     { PU_HUE_AUTO_CONTROL,                      "Hue Auto" },
452     { PU_ANALOG_VIDEO_STANDARD_CONTROL,         "Video Standard" },
453     { PU_ANALOG_LOCK_STATUS_CONTROL,            "Analog Lock Status" },
454     { PU_CONTRAST_AUTO_CONTROL,                 "Contrast Auto" },
455     { 0, NULL }
456 };
457 static value_string_ext cs_processing_unit_ext =
458     VALUE_STRING_EXT_INIT(cs_processing_unit);
459
460 static const value_string vc_terminal_types[] = {
461     { TT_VENDOR_SPECIFIC,         "Vendor Specific", },
462     { TT_STREAMING,               "Streaming" },
463     { ITT_VENDOR_SPECIFIC,        "Vendor Specific Input" },
464     { ITT_CAMERA,                 "Camera Input" },
465     { ITT_MEDIA_TRANSPORT_INPUT,  "Media Transport Input" },
466     { OTT_VENDOR_SPECIFIC,        "Vendor Specific Output" },
467     { OTT_DISPLAY,                "Display Output" },
468     { OTT_MEDIA_TRANSPORT_OUTPUT, "Media Transport Output" },
469     { EXTERNAL_VENDOR_SPECIFIC,   "Vendor Specific External" },
470     { COMPOSITE_CONNECTOR,        "Composite Connector" },
471     { SVIDEO_CONNECTOR,           "SVideo Connector" },
472     { COMPONENT_CONNECTOR,        "Component Connector" },
473     { 0, NULL }
474 };
475 static value_string_ext vc_terminal_types_ext =
476     VALUE_STRING_EXT_INIT(vc_terminal_types);
477
478 static const value_string vs_if_descriptor_subtypes[] = {
479     { VS_UNDEFINED,             "Undefined" },
480     { VS_INPUT_HEADER,          "Input Header" },
481     { VS_OUTPUT_HEADER,         "Output Header" },
482     { VS_STILL_IMAGE_FRAME,     "Still Image Frame" },
483     { VS_FORMAT_UNCOMPRESSED,   "Format Uncompressed" },
484     { VS_FRAME_UNCOMPRESSED,    "Frame Uncompressed" },
485     { VS_FORMAT_MJPEG,          "Format MJPEG" },
486     { VS_FRAME_MJPEG,           "Frame MJPEG" },
487     { VS_FORMAT_MPEG1,          "Format MPEG1" },
488     { VS_FORMAT_MPEG2PS,        "Format MPEG2-PS" },
489     { VS_FORMAT_MPEG2TS,        "Format MPEG2-TS" },
490     { VS_FORMAT_MPEG4SL,        "Format MPEG4-SL" },
491     { VS_FORMAT_DV,             "Format DV" },
492     { VS_COLORFORMAT,           "Colorformat" },
493     { VS_FORMAT_VENDOR,         "Format Vendor" },
494     { VS_FRAME_VENDOR,          "Frame Vendor" },
495     { VS_FORMAT_FRAME_BASED,    "Format Frame-Based" },
496     { VS_FRAME_FRAME_BASED,     "Frame Frame-Based" },
497     { VS_FORMAT_STREAM_BASED,   "Format Stream Based" },
498     { VS_FORMAT_H264,           "Format H.264" },
499     { VS_FRAME_H264,            "Frame H.264" },
500     { VS_FORMAT_H264_SIMULCAST, "Format H.264 Simulcast" },
501     { VS_FORMAT_VP8,            "Format VP8" },
502     { VS_FRAME_VP8,             "Frame VP8" },
503     { VS_FORMAT_VP8_SIMULCAST,  "Format VP8 Simulcast" },
504     { 0, NULL }
505 };
506 static value_string_ext vs_if_descriptor_subtypes_ext =
507     VALUE_STRING_EXT_INIT(vs_if_descriptor_subtypes);
508
509 static const value_string interrupt_status_types[] = {
510     { INT_VIDEOCONTROL,       "VideoControl Interface"   },
511     { INT_VIDEOSTREAMING,     "VideoStreaming Interface" },
512     { 0, NULL }
513 };
514
515 static const value_string control_change_types[] = {
516     { CONTROL_CHANGE_VALUE,   "Value" },
517     { CONTROL_CHANGE_INFO,    "Info" },
518     { CONTROL_CHANGE_FAILURE, "Failure" },
519     { CONTROL_CHANGE_MIN,     "Min" },
520     { CONTROL_CHANGE_MAX,     "Max" },
521     { 0, NULL }
522 };
523 static value_string_ext control_change_types_ext =
524     VALUE_STRING_EXT_INIT(control_change_types);
525
526 static const value_string control_interrupt_events[] = {
527     { CONTROL_INTERRUPT_EVENT_CONTROL_CHANGE,  "Control Change" },
528     { 0, NULL }
529 };
530
531 /* Table 3-13 VS Interface Input Header Descriptor - bStillCaptureMethod field */
532 static const value_string vs_still_capture_methods[] = {
533     { 0,  "None" },
534     { 1,  "Uninterrupted streaming" },
535     { 2,  "Suspended streaming" },
536     { 3,  "Dedicated pipe" },
537     { 0, NULL }
538 };
539 static value_string_ext vs_still_capture_methods_ext =
540     VALUE_STRING_EXT_INIT(vs_still_capture_methods);
541
542 /* Table 3-13 VS Interface Input Header Descriptor - bTriggerUsage field */
543 static const value_string vs_trigger_usage[] = {
544     { 0,  "Initiate still image capture" },
545     { 1,  "General purpose button event" },
546     { 0, NULL }
547 };
548
549 /* bmInterlaceFlags for format descriptors */
550 static const true_false_string is_interlaced_meaning = {
551     "Interlaced",
552     "Non-interlaced"
553 };
554
555 /* bmInterlaceFlags for format descriptors */
556 static const true_false_string interlaced_fields_meaning = {
557     "1 field",
558     "2 fields"
559 };
560
561 /* bmInterlaceFlags for format descriptors */
562 static const value_string field_pattern_meaning[] = {
563     { 0,  "Field 1 only" },
564     { 1,  "Field 2 only" },
565     { 2,  "Regular pattern of fields 1 and 2" },
566     { 3,  "Random pattern of fields 1 and 2" },
567     {0, NULL},
568 };
569 static value_string_ext field_pattern_meaning_ext =
570     VALUE_STRING_EXT_INIT(field_pattern_meaning);
571
572 /* bCopyProtect for format descriptors */
573 static const value_string copy_protect_meaning[] = {
574     { 0,  "No restrictions" },
575     { 1,  "Restrict duplication" },
576     {0, NULL},
577 };
578
579 /* Table 4-46 Video Probe and Commit Controls - bmHint field */
580 static const true_false_string probe_hint_meaning = {
581     "Constant",
582     "Variable"
583 };
584
585 /* Table 3-19 Color Matching Descriptor - bColorPrimaries field */
586 static const value_string color_primaries_meaning[] = {
587     { 0,  "Unspecified" },
588     { 1,  "BT.709, sRGB" },
589     { 2,  "BT.470-2 (M)" },
590     { 3,  "BT.470-2 (B,G)" },
591     { 4,  "SMPTE 170M" },
592     { 5,  "SMPTE 240M" },
593     {0, NULL},
594 };
595 static value_string_ext color_primaries_meaning_ext =
596     VALUE_STRING_EXT_INIT(color_primaries_meaning);
597
598 /* Table 3-19 Color Matching Descriptor - bTransferCharacteristics field */
599 static const value_string color_transfer_characteristics[] = {
600     { 0,  "Unspecified" },
601     { 1,  "BT.709" },
602     { 2,  "BT.470-2 (M)" },
603     { 3,  "BT.470-2 (B,G)" },
604     { 4,  "SMPTE 170M" },
605     { 5,  "SMPTE 240M" },
606     { 6,  "Linear (V=Lc)" },
607     { 7,  "sRGB" },
608     {0, NULL},
609 };
610 static value_string_ext color_transfer_characteristics_ext =
611     VALUE_STRING_EXT_INIT(color_transfer_characteristics);
612
613 /* Table 3-19 Color Matching Descriptor - bMatrixCoefficients field */
614 static const value_string matrix_coefficients_meaning[] = {
615     { 0,  "Unspecified" },
616     { 1,  "BT.709" },
617     { 2,  "FCC" },
618     { 3,  "BT.470-2 (B,G)" },
619     { 4,  "SMPTE 170M (BT.601)" },
620     { 5,  "SMPTE 240M" },
621     {0, NULL},
622 };
623 static value_string_ext matrix_coefficients_meaning_ext =
624     VALUE_STRING_EXT_INIT(matrix_coefficients_meaning);
625
626 static const value_string request_error_codes[] = {
627     { UVC_ERROR_NONE,             "No error" },
628     { UVC_ERROR_NOT_READY,        "Not ready" },
629     { UVC_ERROR_WRONG_STATE,      "Wrong state" },
630     { UVC_ERROR_POWER,            "Insufficient power" } ,
631     { UVC_ERROR_OUT_OF_RANGE,     "Out of range" },
632     { UVC_ERROR_INVALID_UNIT,     "Invalid unit" },
633     { UVC_ERROR_INVALID_CONTROL,  "Invalid control" },
634     { UVC_ERROR_INVALID_REQUEST,  "Invalid request" },
635     { UVC_ERROR_INVALID_VALUE,    "Invalid value within range" },
636     { UVC_ERROR_UNKNOWN,          "Unknown" },
637     {0, NULL},
638 };
639 static value_string_ext request_error_codes_ext =
640     VALUE_STRING_EXT_INIT(request_error_codes);
641
642 /* There is one such structure per terminal or unit per interface */
643 typedef struct
644 {
645     guint8  entityID;
646     guint8  subtype;
647     guint16 terminalType;
648 } video_entity_t;
649
650 /* video_entity_t's (units/terminals) associated with each video interface */
651 /* There is one such structure for each video conversation (interface) */
652 typedef struct _video_conv_info_t {
653     wmem_tree_t* entities;      /* indexed by entity ID */
654 } video_conv_info_t;
655
656 /*****************************************************************************/
657 /*                            UTILITY FUNCTIONS                              */
658 /*****************************************************************************/
659
660 /**
661  * Dissector for variable-length bmControl bitmask / bControlSize pair.
662  *
663  * Creates an item for bControlSize, and a subtree for the bmControl bitmask.
664  *
665  * @param tree            protocol tree to be the parent of the bitmask subtree
666  * @param tvb             the tv_buff with the (remaining) packet data
667  * @param offset          where in tvb to find bControlSize field
668  * @param ett_subtree     index of the subtree to use for this bitmask
669  * @param bm_items        NULL-terminated array of pointers that lists all the fields
670  *                        of the bitmask
671  *
672  * @return   offset within tvb at which dissection should continue
673  */
674 static int
675 dissect_bmControl(proto_tree *tree, tvbuff_t *tvb, int offset,
676                   gint ett_subtree, const int** bm_items)
677 {
678     guint8 bm_size = 0;
679
680     bm_size = tvb_get_guint8(tvb, offset);
681     proto_tree_add_item(tree, hf_usb_vid_bControlSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
682     ++offset;
683
684     if (bm_size > 0)
685     {
686         proto_tree_add_bitmask_len(tree, tvb, offset, bm_size, hf_usb_vid_bmControl,
687                                    ett_subtree, bm_items, &ei_usb_vid_bitmask_len, ENC_LITTLE_ENDIAN);
688         offset += bm_size;
689     }
690
691     return offset;
692 }
693
694 /*****************************************************************************/
695 /*                          VIDEO CONTROL DESCRIPTORS                        */
696 /*****************************************************************************/
697
698 /* Dissect a Camera Terminal descriptor */
699 static int
700 dissect_usb_video_camera_terminal(proto_tree *tree, tvbuff_t *tvb, int offset)
701 {
702     static const int *control_bits[] = {
703         &hf_usb_vid_cam_control_D[0],
704         &hf_usb_vid_cam_control_D[1],
705         &hf_usb_vid_cam_control_D[2],
706         &hf_usb_vid_cam_control_D[3],
707         &hf_usb_vid_cam_control_D[4],
708         &hf_usb_vid_cam_control_D[5],
709         &hf_usb_vid_cam_control_D[6],
710         &hf_usb_vid_cam_control_D[7],
711         &hf_usb_vid_cam_control_D[8],
712         &hf_usb_vid_cam_control_D[9],
713         &hf_usb_vid_cam_control_D[10],
714         &hf_usb_vid_cam_control_D[11],
715         &hf_usb_vid_cam_control_D[12],
716         &hf_usb_vid_cam_control_D[13],
717         &hf_usb_vid_cam_control_D[14],
718         &hf_usb_vid_cam_control_D[15],
719         &hf_usb_vid_cam_control_D[16],
720         &hf_usb_vid_cam_control_D[17],
721         &hf_usb_vid_cam_control_D[18],
722         &hf_usb_vid_cam_control_D[19],
723         &hf_usb_vid_cam_control_D[20],
724         &hf_usb_vid_cam_control_D[21],
725         NULL
726     };
727
728     DISSECTOR_ASSERT(array_length(control_bits) == (1+array_length(hf_usb_vid_cam_control_D)));
729
730     proto_tree_add_item(tree, hf_usb_vid_cam_objective_focal_len_min,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
731     offset += 2;
732     proto_tree_add_item(tree, hf_usb_vid_cam_objective_focal_len_max,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
733     offset += 2;
734     proto_tree_add_item(tree, hf_usb_vid_cam_ocular_focal_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
735     offset += 2;
736
737     offset = dissect_bmControl(tree, tvb, offset, ett_camera_controls, control_bits);
738
739     return offset;
740 }
741
742 /* Dissect a Processing Unit descriptor */
743 static int
744 dissect_usb_video_processing_unit(proto_tree *tree, tvbuff_t *tvb, int offset)
745 {
746     static const int *control_bits[] = {
747         &hf_usb_vid_proc_control_D[0],
748         &hf_usb_vid_proc_control_D[1],
749         &hf_usb_vid_proc_control_D[2],
750         &hf_usb_vid_proc_control_D[3],
751         &hf_usb_vid_proc_control_D[4],
752         &hf_usb_vid_proc_control_D[5],
753         &hf_usb_vid_proc_control_D[6],
754         &hf_usb_vid_proc_control_D[7],
755         &hf_usb_vid_proc_control_D[8],
756         &hf_usb_vid_proc_control_D[9],
757         &hf_usb_vid_proc_control_D[10],
758         &hf_usb_vid_proc_control_D[11],
759         &hf_usb_vid_proc_control_D[12],
760         &hf_usb_vid_proc_control_D[13],
761         &hf_usb_vid_proc_control_D[14],
762         &hf_usb_vid_proc_control_D[15],
763         &hf_usb_vid_proc_control_D[16],
764         &hf_usb_vid_proc_control_D[17],
765         &hf_usb_vid_proc_control_D[18],
766         NULL
767     };
768
769     DISSECTOR_ASSERT(array_length(control_bits) == (1+array_length(hf_usb_vid_proc_control_D)));
770
771     proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_src_id, tvb, offset,   1, ENC_LITTLE_ENDIAN);
772     proto_tree_add_item(tree, hf_usb_vid_max_multiplier,        tvb, offset+1, 2, ENC_LITTLE_ENDIAN);
773     offset += 3;
774
775     offset = dissect_bmControl(tree, tvb, offset, ett_processing_controls, control_bits);
776
777     proto_tree_add_item(tree, hf_usb_vid_iProcessing, tvb, offset, 1, ENC_LITTLE_ENDIAN);
778     ++offset;
779
780     /* UVC 1.1 added bmVideoStandards */
781     if (tvb_reported_length_remaining(tvb, offset) > 0)
782     {
783         static const int *standard_bits[] = {
784             &hf_usb_vid_proc_standards_D[0],
785             &hf_usb_vid_proc_standards_D[1],
786             &hf_usb_vid_proc_standards_D[2],
787             &hf_usb_vid_proc_standards_D[3],
788             &hf_usb_vid_proc_standards_D[4],
789             &hf_usb_vid_proc_standards_D[5],
790             NULL
791         };
792
793         DISSECTOR_ASSERT(array_length(standard_bits) == (1+array_length(hf_usb_vid_proc_standards_D)));
794
795         proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_proc_standards,
796                                ett_video_standards, standard_bits, ENC_NA);
797         ++offset;
798     }
799
800     return offset;
801 }
802
803 /* Dissect a Selector Unit descriptor */
804 static int
805 dissect_usb_video_selector_unit(proto_tree *tree, tvbuff_t *tvb, int offset)
806 {
807     guint8 num_inputs;
808
809     num_inputs = tvb_get_guint8(tvb, offset);
810     proto_tree_add_item(tree, hf_usb_vid_num_inputs, tvb, offset, 1, ENC_LITTLE_ENDIAN);
811     ++offset;
812
813     if (num_inputs > 0)
814     {
815         proto_tree_add_item(tree, hf_usb_vid_sources, tvb, offset, num_inputs, ENC_NA);
816         offset += num_inputs;
817     }
818
819     proto_tree_add_item(tree, hf_usb_vid_iSelector, tvb, offset, 1, ENC_LITTLE_ENDIAN);
820     ++offset;
821
822     return offset;
823 }
824
825 /* Dissect an Extension Unit descriptor */
826 static int
827 dissect_usb_video_extension_unit(proto_tree *tree, tvbuff_t *tvb, int offset)
828 {
829     guint8 num_inputs;
830     guint8 control_size;
831
832     proto_tree_add_item(tree, hf_usb_vid_exten_guid,         tvb, offset,    16, ENC_LITTLE_ENDIAN);
833     proto_tree_add_item(tree, hf_usb_vid_exten_num_controls, tvb, offset+16,  1, ENC_LITTLE_ENDIAN);
834     offset += 17;
835
836     num_inputs = tvb_get_guint8(tvb, offset);
837     proto_tree_add_item(tree, hf_usb_vid_num_inputs,   tvb, offset,  1, ENC_LITTLE_ENDIAN);
838     ++offset;
839
840     if (num_inputs > 0)
841     {
842         proto_tree_add_item(tree, hf_usb_vid_sources, tvb, offset, num_inputs, ENC_NA);
843         offset += num_inputs;
844     }
845
846     control_size = tvb_get_guint8(tvb, offset);
847     proto_tree_add_item(tree, hf_usb_vid_bControlSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
848     ++offset;
849
850     if (control_size > 0)
851     {
852         if (control_size <= proto_registrar_get_length(hf_usb_vid_bmControl))
853         {
854             proto_tree_add_item(tree, hf_usb_vid_bmControl, tvb, offset, control_size,
855                                 ENC_LITTLE_ENDIAN);
856         }
857         else
858         {
859             /* Too big to display as integer */
860             /* @todo Display as FT_BYTES with a big-endian disclaimer?
861              * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7933
862              */
863             proto_tree_add_bytes_format(tree, hf_usb_vid_bmControl_bytes, tvb, offset, control_size, NULL, "bmControl");
864         }
865         offset += control_size;
866     }
867
868     proto_tree_add_item(tree, hf_usb_vid_iExtension, tvb, offset, 1, ENC_LITTLE_ENDIAN);
869     ++offset;
870
871     return offset;
872 }
873
874 /**
875  * Dissector for video class control interface descriptors
876  *
877  * @param parent_tree     the protocol tree to be the parent of the descriptor subtree
878  * @param tvb             the tv_buff with the (remaining) packet data
879  *                        On entry the gaze is set to the descriptor length field.
880  * @param descriptor_len  Length of the descriptor to dissect
881  * @param pinfo           Information associated with the packet being dissected
882  *
883  * @return   offset within tvb at which dissection should continue
884  */
885 static int
886 dissect_usb_video_control_interface_descriptor(proto_tree *parent_tree, tvbuff_t *tvb,
887                                                guint8 descriptor_len, packet_info *pinfo, usb_conv_info_t *usb_conv_info)
888 {
889     video_conv_info_t *video_conv_info = NULL;
890     video_entity_t    *entity          = NULL;
891     proto_item *item          = NULL;
892     proto_item *subtype_item  = NULL;
893     proto_tree *tree          = NULL;
894     guint8      entity_id     = 0;
895     guint16     terminal_type = 0;
896     int         offset        = 0;
897     guint8      subtype;
898
899     subtype = tvb_get_guint8(tvb, offset+2);
900
901     if (parent_tree)
902     {
903         const gchar *subtype_str;
904
905         subtype_str = val_to_str_ext(subtype, &vc_if_descriptor_subtypes_ext, "Unknown (0x%x)");
906
907         tree = proto_tree_add_subtree_format(parent_tree, tvb, offset, descriptor_len,
908                                    ett_descriptor_video_control, &item, "VIDEO CONTROL INTERFACE DESCRIPTOR [%s]",
909                                    subtype_str);
910     }
911
912     /* Common fields */
913     dissect_usb_descriptor_header(tree, tvb, offset, &vid_descriptor_type_vals_ext);
914     subtype_item = proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_subtype, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
915     offset += 3;
916
917     if (subtype == VC_HEADER)
918     {
919         guint8 num_vs_interfaces;
920
921         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_bcdUVC,            tvb, offset,   2, ENC_LITTLE_ENDIAN);
922         proto_tree_add_item(tree, hf_usb_vid_ifdesc_wTotalLength,              tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
923         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_dwClockFrequency,  tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
924
925         num_vs_interfaces = tvb_get_guint8(tvb, offset+8);
926         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_bInCollection,     tvb, offset+8, 1, ENC_LITTLE_ENDIAN);
927
928         if (num_vs_interfaces > 0)
929         {
930             proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_baInterfaceNr, tvb, offset+9, num_vs_interfaces, ENC_NA);
931         }
932
933         offset += 9 + num_vs_interfaces;
934     }
935     else if ((subtype == VC_INPUT_TERMINAL) || (subtype == VC_OUTPUT_TERMINAL))
936     {
937         /* Fields common to input and output terminals */
938         entity_id     = tvb_get_guint8(tvb, offset);
939         terminal_type = tvb_get_letohs(tvb, offset+1);
940
941         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_terminal_id,    tvb, offset,   1, ENC_LITTLE_ENDIAN);
942         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_terminal_type,  tvb, offset+1, 2, ENC_LITTLE_ENDIAN);
943         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_assoc_terminal, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
944         offset += 4;
945
946         if (subtype == VC_OUTPUT_TERMINAL)
947         {
948             proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_src_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
949             ++offset;
950         }
951
952         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_iTerminal, tvb, offset, 1, ENC_LITTLE_ENDIAN);
953         ++offset;
954
955         if (subtype == VC_INPUT_TERMINAL)
956         {
957             if (terminal_type == ITT_CAMERA)
958             {
959                 offset = dissect_usb_video_camera_terminal(tree, tvb, offset);
960             }
961             else if (terminal_type == ITT_MEDIA_TRANSPORT_INPUT)
962             {
963                 /* @todo */
964             }
965         }
966
967         if (subtype == VC_OUTPUT_TERMINAL)
968         {
969             if (terminal_type == OTT_MEDIA_TRANSPORT_OUTPUT)
970             {
971                 /* @todo */
972             }
973         }
974     }
975     else
976     {
977         /* Field common to extension / processing / selector / encoding units */
978         entity_id = tvb_get_guint8(tvb, offset);
979         proto_tree_add_item(tree, hf_usb_vid_control_ifdesc_unit_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
980         ++offset;
981
982         if (subtype == VC_PROCESSING_UNIT)
983         {
984             offset = dissect_usb_video_processing_unit(tree, tvb, offset);
985         }
986         else if (subtype == VC_SELECTOR_UNIT)
987         {
988             offset = dissect_usb_video_selector_unit(tree, tvb, offset);
989         }
990         else if (subtype == VC_EXTENSION_UNIT)
991         {
992             offset = dissect_usb_video_extension_unit(tree, tvb, offset);
993         }
994         else if (subtype == VC_ENCODING_UNIT)
995         {
996             /* @todo UVC 1.5 */
997         }
998         else
999         {
1000             expert_add_info_format(pinfo, subtype_item, &ei_usb_vid_subtype_unknown,
1001                                    "Unknown VC subtype %u", subtype);
1002         }
1003     }
1004
1005     /* Soak up descriptor bytes beyond those we know how to dissect */
1006     if (offset < descriptor_len)
1007     {
1008         proto_tree_add_item(tree, hf_usb_vid_descriptor_data, tvb, offset, descriptor_len-offset, ENC_NA);
1009         /* offset = descriptor_len; */
1010     }
1011
1012     if (entity_id != 0)
1013         proto_item_append_text(item, " (Entity %d)", entity_id);
1014
1015     if (subtype != VC_HEADER && usb_conv_info)
1016     {
1017         /* Switch to the usb_conv_info of the Video Control interface */
1018         usb_conv_info = get_usb_iface_conv_info(pinfo, usb_conv_info->interfaceNum);
1019         video_conv_info = (video_conv_info_t *)usb_conv_info->class_data;
1020
1021         if (!video_conv_info)
1022         {
1023             video_conv_info = wmem_new(wmem_file_scope(), video_conv_info_t);
1024             video_conv_info->entities = wmem_tree_new(wmem_file_scope());
1025             usb_conv_info->class_data = video_conv_info;
1026             usb_conv_info->class_data_type = USB_CONV_VIDEO;
1027         } else if (usb_conv_info->class_data_type != USB_CONV_VIDEO) {
1028             /* Stop dissection if another USB type is in the conversation */
1029             return descriptor_len;
1030         }
1031
1032         entity = (video_entity_t*) wmem_tree_lookup32(video_conv_info->entities, entity_id);
1033         if (!entity)
1034         {
1035             entity = wmem_new(wmem_file_scope(), video_entity_t);
1036             entity->entityID     = entity_id;
1037             entity->subtype      = subtype;
1038             entity->terminalType = terminal_type;
1039
1040             wmem_tree_insert32(video_conv_info->entities, entity_id, entity);
1041         }
1042     }
1043
1044     return descriptor_len;
1045 }
1046
1047 /*****************************************************************************/
1048 /*                        VIDEO STREAMING DESCRIPTORS                        */
1049 /*****************************************************************************/
1050
1051 /* Dissect a Video Streaming Input Header descriptor */
1052 static int
1053 dissect_usb_video_streaming_input_header(proto_tree *tree, tvbuff_t *tvb, int offset)
1054 {
1055     guint8 num_formats;
1056     guint8 bm_size;
1057
1058     static const int *info_bits[] = {
1059         &hf_usb_vid_streaming_info_D[0],
1060         NULL
1061     };
1062     static const int *control_bits[] = {
1063         &hf_usb_vid_streaming_control_D[0],
1064         &hf_usb_vid_streaming_control_D[1],
1065         &hf_usb_vid_streaming_control_D[2],
1066         &hf_usb_vid_streaming_control_D[3],
1067         &hf_usb_vid_streaming_control_D[4],
1068         &hf_usb_vid_streaming_control_D[5],
1069         NULL
1070     };
1071
1072     DISSECTOR_ASSERT(array_length(control_bits) == (1+array_length(hf_usb_vid_streaming_control_D)));
1073
1074     num_formats = tvb_get_guint8(tvb, offset);
1075     proto_tree_add_item(tree, hf_usb_vid_streaming_ifdesc_bNumFormats, tvb, offset,   1, ENC_LITTLE_ENDIAN);
1076     proto_tree_add_item(tree, hf_usb_vid_ifdesc_wTotalLength,          tvb, offset+1, 2, ENC_LITTLE_ENDIAN);
1077     offset += 3;
1078
1079     dissect_usb_endpoint_address(tree, tvb, offset);
1080     offset++;
1081
1082     proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_streaming_bmInfo,
1083                            ett_streaming_info, info_bits, ENC_NA);
1084
1085     proto_tree_add_item(tree, hf_usb_vid_streaming_terminal_link,        tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1086     proto_tree_add_item(tree, hf_usb_vid_streaming_still_capture_method, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1087     offset += 3;
1088
1089     proto_tree_add_item(tree, hf_usb_vid_streaming_trigger_support,      tvb, offset,   1, ENC_NA);
1090     if (tvb_get_guint8(tvb, offset) > 0)
1091     {
1092         proto_tree_add_item(tree, hf_usb_vid_streaming_trigger_usage,    tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1093     }
1094     else
1095     {
1096         proto_tree_add_uint_format_value(tree, hf_usb_vid_streaming_trigger_usage, tvb, offset+1, 1, 0, "Not applicable");
1097     }
1098
1099     offset += 2;
1100
1101     /* NOTE: Can't use dissect_bmControl here because there's only one size
1102      *       field for (potentially) multiple bmControl fields
1103      */
1104     bm_size = tvb_get_guint8(tvb, offset);
1105     proto_tree_add_item(tree, hf_usb_vid_bControlSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1106     ++offset;
1107
1108     if (bm_size > 0)
1109     {
1110         guint8 i;
1111         for (i=0; i<num_formats; ++i)
1112         {
1113             proto_tree_add_bitmask_len(tree, tvb, offset, bm_size, hf_usb_vid_bmControl,
1114                                        ett_streaming_controls, control_bits, &ei_usb_vid_bitmask_len,
1115                                        ENC_LITTLE_ENDIAN);
1116             offset += bm_size;
1117         }
1118     }
1119
1120     return offset;
1121 }
1122
1123 /**
1124  * Dissect a known Video Payload Format descriptor.
1125  *
1126  * @param tree     protocol tree to which fields should be added
1127  * @param tvb      the tv_buff with the (remaining) packet data
1128  * @param offset   where in tvb to begin dissection.
1129  *                 On entry this refers to the bFormatIndex field.
1130  * @param subtype  Type of format descriptor, from the
1131  *                 bDescriptorSubtype field
1132  *
1133  * @return   offset within tvb at which dissection should continue
1134  */
1135 static int
1136 dissect_usb_video_format(proto_tree *tree, tvbuff_t *tvb, int offset,
1137                          guint8 subtype)
1138 {
1139     static const int *interlace_bits[] = {
1140         &hf_usb_vid_is_interlaced,
1141         &hf_usb_vid_interlaced_fields,
1142         &hf_usb_vid_field_1_first,
1143         &hf_usb_vid_field_pattern,
1144         NULL
1145     };
1146
1147     proto_item *desc_item;
1148     guint8 format_index;
1149
1150     /* Augment the descriptor root item with the index of this descriptor */
1151     format_index = tvb_get_guint8(tvb, offset);
1152     desc_item = proto_tree_get_parent(tree);
1153     proto_item_append_text(desc_item, "  (Format %u)", format_index);
1154
1155     proto_tree_add_item(tree, hf_usb_vid_format_index,                  tvb, offset,    1, ENC_LITTLE_ENDIAN);
1156     proto_tree_add_item(tree, hf_usb_vid_format_num_frame_descriptors,  tvb, offset+1,  1, ENC_LITTLE_ENDIAN);
1157     offset += 2;
1158
1159     if ((subtype == VS_FORMAT_UNCOMPRESSED) || (subtype == VS_FORMAT_FRAME_BASED))
1160     {
1161         /* Augment the descriptor root item with the format's four-character-code */
1162         char fourcc[5];
1163         tvb_memcpy(tvb, (guint8 *)fourcc, offset, 4);
1164         fourcc[4] = '\0';
1165         proto_item_append_text(desc_item, ": %s", fourcc);
1166
1167         proto_tree_add_item(tree, hf_usb_vid_format_guid, tvb, offset,   16, ENC_LITTLE_ENDIAN);
1168         proto_tree_add_item(tree, hf_usb_vid_format_bits_per_pixel,        tvb, offset+16, 1, ENC_LITTLE_ENDIAN);
1169         offset += 17;
1170     }
1171     else if (subtype == VS_FORMAT_MJPEG)
1172     {
1173         static const int * flags[] = {
1174             &hf_usb_vid_mjpeg_fixed_samples,
1175             NULL
1176         };
1177
1178         proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_mjpeg_flags, ett_mjpeg_flags, flags, ENC_NA);
1179         offset++;
1180     }
1181     else
1182     {
1183         /* We should only be called for known format descriptor subtypes */
1184         DISSECTOR_ASSERT_NOT_REACHED();
1185     }
1186
1187     proto_tree_add_item(tree, hf_usb_vid_default_frame_index, tvb, offset,   1, ENC_LITTLE_ENDIAN);
1188     proto_tree_add_item(tree, hf_usb_vid_aspect_ratio_x,      tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1189     proto_tree_add_item(tree, hf_usb_vid_aspect_ratio_y,      tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1190     offset += 3;
1191
1192 #if 0
1193     /* @todo Display "N/A" if Camera Terminal does not support scanning mode control */
1194     if (something)
1195         proto_tree_add_uint_format_value(tree, hf_usb_vid_interlace_flags, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Not applicable");
1196 #endif
1197
1198     proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_interlace_flags,
1199                                 ett_interlace_flags, interlace_bits, ENC_NA);
1200     offset++;
1201
1202     proto_tree_add_item(tree, hf_usb_vid_copy_protect, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1203     offset++;
1204
1205     if (subtype == VS_FORMAT_FRAME_BASED)
1206     {
1207         proto_tree_add_item(tree, hf_usb_vid_variable_size, tvb, offset, 1, ENC_NA);
1208         offset++;
1209     }
1210
1211     return offset;
1212 }
1213
1214 /**
1215  * Dissect a known Video Frame descriptor.
1216  *
1217  * @param tree     protocol tree to which fields should be added
1218  * @param tvb      the tv_buff with the (remaining) packet data
1219  * @param offset   where in tvb to begin dissection.
1220  *                 On entry this refers to the bFrameIndex field.
1221  * @param subtype  Type of frame descriptor, from the
1222  *                 bDescriptorSubtype field
1223  *
1224  * @return   offset within tvb at which dissection should continue
1225  */
1226 static int
1227 dissect_usb_video_frame(proto_tree *tree, tvbuff_t *tvb, int offset,
1228                         guint8 subtype)
1229 {
1230     static const int *capability_bits[] = {
1231         &hf_usb_vid_frame_stills_supported,
1232         &hf_usb_vid_frame_fixed_frame_rate,
1233         NULL
1234     };
1235     proto_item *desc_item;
1236     guint8      bFrameIntervalType;
1237     guint8      frame_index;
1238     guint16     frame_width;
1239     guint16     frame_height;
1240
1241     frame_index = tvb_get_guint8(tvb, offset);
1242     proto_tree_add_item(tree, hf_usb_vid_frame_index, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1243     offset++;
1244
1245     proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_frame_capabilities,
1246                            ett_frame_capability_flags, capability_bits, ENC_NA);
1247     offset++;
1248
1249     proto_tree_add_item(tree, hf_usb_vid_frame_width,        tvb, offset,    2, ENC_LITTLE_ENDIAN);
1250     proto_tree_add_item(tree, hf_usb_vid_frame_height,       tvb, offset+2,  2, ENC_LITTLE_ENDIAN);
1251
1252     /* Augment the descriptor root item with useful information */
1253     frame_width = tvb_get_letohs(tvb, offset);
1254     frame_height = tvb_get_letohs(tvb, offset+2);
1255     desc_item = proto_tree_get_parent(tree);
1256     proto_item_append_text(desc_item, "   (Index %2u): %4u x %4u", frame_index, frame_width, frame_height);
1257
1258     proto_tree_add_item(tree, hf_usb_vid_frame_min_bit_rate, tvb, offset+4,  4, ENC_LITTLE_ENDIAN);
1259     proto_tree_add_item(tree, hf_usb_vid_frame_max_bit_rate, tvb, offset+8,  4, ENC_LITTLE_ENDIAN);
1260     offset += 12;
1261
1262     if (subtype != VS_FRAME_FRAME_BASED)
1263     {
1264         proto_tree_add_item(tree, hf_usb_vid_frame_max_frame_sz, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1265         offset += 4;
1266     }
1267
1268     proto_tree_add_item(tree, hf_usb_vid_frame_default_interval, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1269     offset += 4;
1270
1271     bFrameIntervalType = tvb_get_guint8(tvb, offset);
1272     if (bFrameIntervalType == 0)
1273     {
1274         proto_tree_add_uint_format_value(tree, hf_usb_vid_frame_interval_type, tvb, offset, 1,
1275                                          bFrameIntervalType, "Continuous (0)");
1276         offset++;
1277
1278         if (subtype == VS_FRAME_FRAME_BASED)
1279         {
1280             proto_tree_add_item(tree, hf_usb_vid_frame_bytes_per_line, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1281             offset += 4;
1282         }
1283
1284         proto_tree_add_item(tree, hf_usb_vid_frame_min_interval,  tvb, offset,   4, ENC_LITTLE_ENDIAN);
1285         proto_tree_add_item(tree, hf_usb_vid_frame_max_interval,  tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1286         proto_tree_add_item(tree, hf_usb_vid_frame_step_interval, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1287         offset += 12;
1288     }
1289     else
1290     {
1291         guint8 i;
1292         proto_tree_add_uint_format_value(tree, hf_usb_vid_frame_interval_type, tvb, offset, 1,
1293                                          bFrameIntervalType, "Discrete (%u choice%s)",
1294                                          bFrameIntervalType, (bFrameIntervalType > 1) ? "s" : "");
1295         offset++;
1296
1297         if (subtype == VS_FRAME_FRAME_BASED)
1298         {
1299             proto_tree_add_item(tree, hf_usb_vid_frame_bytes_per_line, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1300             offset += 4;
1301         }
1302
1303         for (i=0; i<bFrameIntervalType; ++i)
1304         {
1305             proto_tree_add_item(tree, hf_usb_vid_frame_interval,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
1306             offset += 4;
1307         }
1308     }
1309
1310     return offset;
1311 }
1312
1313 /* Dissect a Color Matching descriptor */
1314 static int
1315 dissect_usb_video_colorformat(proto_tree *tree, tvbuff_t *tvb, int offset)
1316 {
1317     proto_tree_add_item(tree, hf_usb_vid_color_primaries,          tvb, offset,   1, ENC_LITTLE_ENDIAN);
1318     proto_tree_add_item(tree, hf_usb_vid_transfer_characteristics, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1319     proto_tree_add_item(tree, hf_usb_vid_matrix_coefficients,      tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1320     offset +=3;
1321
1322     return offset;
1323 }
1324
1325 /**
1326  * Dissector for video class streaming interface descriptors.
1327  *
1328  * @param parent_tree     the protocol tree to be the parent of the descriptor subtree
1329  * @param tvb             the tv_buff with the (remaining) packet data
1330  *                        On entry the gaze is set to the descriptor length field.
1331  * @param descriptor_len  Length of the descriptor to dissect
1332  *
1333  * @return   offset within tvb at which dissection should continue
1334  */
1335 static int
1336 dissect_usb_video_streaming_interface_descriptor(proto_tree *parent_tree, tvbuff_t *tvb,
1337                                                  guint8 descriptor_len)
1338 {
1339     proto_tree  *tree;
1340     int          offset = 0;
1341     const gchar *subtype_str;
1342     guint8       subtype;
1343
1344     subtype = tvb_get_guint8(tvb, offset+2);
1345
1346     subtype_str = val_to_str_ext(subtype, &vs_if_descriptor_subtypes_ext, "Unknown (0x%x)");
1347     tree = proto_tree_add_subtree_format(parent_tree, tvb, offset, descriptor_len,
1348             ett_descriptor_video_streaming, NULL, "VIDEO STREAMING INTERFACE DESCRIPTOR [%s]",
1349             subtype_str);
1350
1351     dissect_usb_descriptor_header(tree, tvb, offset, &vid_descriptor_type_vals_ext);
1352     proto_tree_add_item(tree, hf_usb_vid_streaming_ifdesc_subtype, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1353     offset += 3;
1354
1355     switch (subtype)
1356     {
1357         case VS_INPUT_HEADER:
1358             offset = dissect_usb_video_streaming_input_header(tree, tvb, offset);
1359             break;
1360
1361         case VS_FORMAT_UNCOMPRESSED:
1362         case VS_FORMAT_MJPEG:
1363         case VS_FORMAT_FRAME_BASED:
1364             offset = dissect_usb_video_format(tree, tvb, offset, subtype);
1365             break;
1366
1367         /* @todo MPEG2, H.264, VP8, Still Image Frame */
1368         /* @todo Obsolete UVC-1.0 descriptors? */
1369
1370         case VS_FRAME_UNCOMPRESSED:
1371         case VS_FRAME_MJPEG:
1372         case VS_FRAME_FRAME_BASED:
1373             offset = dissect_usb_video_frame(tree, tvb, offset, subtype);
1374             break;
1375
1376         case VS_COLORFORMAT:
1377             offset = dissect_usb_video_colorformat(tree, tvb, offset);
1378             break;
1379
1380         default:
1381             break;
1382     }
1383
1384     /* Soak up descriptor bytes beyond those we know how to dissect */
1385     if (offset < descriptor_len)
1386         proto_tree_add_item(tree, hf_usb_vid_descriptor_data, tvb, offset, descriptor_len-offset, ENC_NA);
1387
1388     return descriptor_len;
1389 }
1390
1391 /*****************************************************************************/
1392
1393 /**
1394  * Dissector for video class-specific endpoint descriptor.
1395  *
1396  * @param parent_tree     the protocol tree to be the parent of the descriptor subtree
1397  * @param tvb             the tv_buff with the (remaining) packet data
1398  *                        On entry the gaze is set to the descriptor length field.
1399  * @param descriptor_len  Length of the descriptor to dissect
1400  *
1401  * @return   offset within tvb at which dissection should continue
1402  */
1403 static int
1404 dissect_usb_video_endpoint_descriptor(proto_tree *parent_tree, tvbuff_t *tvb,
1405                                       guint8 descriptor_len)
1406 {
1407     proto_tree *tree   = NULL;
1408     int         offset = 0;
1409     guint8      subtype;
1410
1411     subtype = tvb_get_guint8(tvb, offset+2);
1412
1413     if (parent_tree)
1414     {
1415         const gchar* subtype_str;
1416
1417         subtype_str = val_to_str(subtype, vc_ep_descriptor_subtypes, "Unknown (0x%x)");
1418         tree = proto_tree_add_subtree_format(parent_tree, tvb, offset, descriptor_len,
1419                 ett_descriptor_video_endpoint, NULL, "VIDEO CONTROL ENDPOINT DESCRIPTOR [%s]",
1420                 subtype_str);
1421     }
1422
1423     dissect_usb_descriptor_header(tree, tvb, offset, &vid_descriptor_type_vals_ext);
1424     proto_tree_add_item(tree, hf_usb_vid_epdesc_subtype, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1425     offset += 3;
1426
1427     if (subtype == EP_INTERRUPT)
1428     {
1429         proto_tree_add_item(tree, hf_usb_vid_epdesc_max_transfer_sz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1430         offset += 2;
1431     }
1432
1433     /* Soak up descriptor bytes beyond those we know how to dissect */
1434     if (offset < descriptor_len)
1435         proto_tree_add_item(tree, hf_usb_vid_descriptor_data, tvb, offset, descriptor_len-offset, ENC_NA);
1436
1437     return descriptor_len;
1438 }
1439
1440 /**
1441  * Registered dissector for video class-specific descriptors
1442  *
1443  * @param tvb    the tv_buff with the (remaining) packet data
1444  *               On entry the gaze is set to the descriptor length field.
1445  * @param pinfo  the packet info of this packet (additional info)
1446  * @param tree   the protocol tree to be built or NULL
1447  * @param data   Not used
1448  *
1449  * @return   0   no class specific dissector was found
1450  * @return  <0   not enough data
1451  * @return  >0   amount of data in the descriptor
1452  */
1453 static int
1454 dissect_usb_vid_descriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1455 {
1456     int    offset = 0;
1457     guint8 descriptor_len;
1458     guint8 descriptor_type;
1459     gint   bytes_available;
1460     usb_conv_info_t  *usb_conv_info = (usb_conv_info_t *)data;
1461
1462     tvbuff_t         *desc_tvb;
1463
1464     descriptor_len  = tvb_get_guint8(tvb, offset);
1465     descriptor_type = tvb_get_guint8(tvb, offset+1);
1466
1467     bytes_available = tvb_captured_length_remaining(tvb, offset);
1468     desc_tvb = tvb_new_subset_length_caplen(tvb, 0, bytes_available, descriptor_len);
1469
1470     if (descriptor_type == CS_ENDPOINT)
1471     {
1472         offset = dissect_usb_video_endpoint_descriptor(tree, desc_tvb,
1473                                                        descriptor_len);
1474     }
1475     else if (descriptor_type == CS_INTERFACE)
1476     {
1477         if (usb_conv_info && usb_conv_info->interfaceSubclass == SC_VIDEOCONTROL)
1478         {
1479             offset = dissect_usb_video_control_interface_descriptor(tree, desc_tvb,
1480                                                                     descriptor_len,
1481                                                                     pinfo, usb_conv_info);
1482         }
1483         else if (usb_conv_info && usb_conv_info->interfaceSubclass == SC_VIDEOSTREAMING)
1484         {
1485             offset = dissect_usb_video_streaming_interface_descriptor(tree, desc_tvb,
1486                                                                       descriptor_len);
1487         }
1488     }
1489     /* else not something we recognize, just return offset = 0 */
1490
1491     return offset;
1492 }
1493
1494 /*****************************************************************************/
1495 /*                            CONTROL TRANSFERS                              */
1496 /*****************************************************************************/
1497
1498 /**
1499  * Dissect GET/SET transactions on the Video Probe and Commit controls.
1500  *
1501  * @param  parent_tree  protocol tree to which the probe/commit subtree should be added
1502  * @param  tvb          the tv_buff with the (remaining) packet data
1503  * @param  offset       where in tvb to begin dissection.
1504  *                      On entry this refers to the probe/commit bmHint field.
1505  *
1506  * @return offset within tvb at which dissection should continue
1507  */
1508 static int
1509 dissect_usb_vid_probe(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
1510 {
1511     proto_tree *tree;
1512
1513     static const int *hint_bits[] = {
1514         &hf_usb_vid_probe_hint_D[0],
1515         &hf_usb_vid_probe_hint_D[1],
1516         &hf_usb_vid_probe_hint_D[2],
1517         &hf_usb_vid_probe_hint_D[3],
1518         &hf_usb_vid_probe_hint_D[4],
1519         NULL
1520     };
1521
1522     DISSECTOR_ASSERT(array_length(hint_bits) == (1+array_length(hf_usb_vid_probe_hint_D)));
1523
1524     tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_video_probe, NULL, "Probe/Commit Info");
1525
1526     proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_probe_hint,
1527                            ett_probe_hint, hint_bits, ENC_LITTLE_ENDIAN);
1528
1529     proto_tree_add_item(tree, hf_usb_vid_format_index,         tvb, offset+2,  1, ENC_LITTLE_ENDIAN);
1530     proto_tree_add_item(tree, hf_usb_vid_frame_index,          tvb, offset+3,  1, ENC_LITTLE_ENDIAN);
1531     proto_tree_add_item(tree, hf_usb_vid_frame_interval,       tvb, offset+4,  4, ENC_LITTLE_ENDIAN);
1532     proto_tree_add_item(tree, hf_usb_vid_probe_key_frame_rate, tvb, offset+8,  2, ENC_LITTLE_ENDIAN);
1533     proto_tree_add_item(tree, hf_usb_vid_probe_p_frame_rate,   tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
1534     proto_tree_add_item(tree, hf_usb_vid_probe_comp_quality,   tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
1535     proto_tree_add_item(tree, hf_usb_vid_probe_comp_window,    tvb, offset+14, 2, ENC_LITTLE_ENDIAN);
1536     proto_tree_add_item(tree, hf_usb_vid_probe_delay,          tvb, offset+16, 2, ENC_LITTLE_ENDIAN);
1537     proto_tree_add_item(tree, hf_usb_vid_probe_max_frame_sz,   tvb, offset+18, 4, ENC_LITTLE_ENDIAN);
1538     proto_tree_add_item(tree, hf_usb_vid_probe_max_payload_sz, tvb, offset+22, 4, ENC_LITTLE_ENDIAN);
1539     offset += 26;
1540
1541     /* UVC 1.1 fields */
1542     if (tvb_reported_length_remaining(tvb, offset) > 0)
1543     {
1544         static const int *framing_bits[] = {
1545             &hf_usb_vid_probe_framing_D[0],
1546             &hf_usb_vid_probe_framing_D[1],
1547             NULL
1548         };
1549
1550         DISSECTOR_ASSERT(array_length(framing_bits) == (1+array_length(hf_usb_vid_probe_framing_D)));
1551
1552         proto_tree_add_item(tree, hf_usb_vid_probe_clock_freq,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
1553         offset += 4;
1554
1555         proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_probe_framing,
1556                                ett_probe_framing, framing_bits, ENC_NA);
1557         offset++;
1558
1559         proto_tree_add_item(tree, hf_usb_vid_probe_preferred_ver, tvb, offset,   1, ENC_LITTLE_ENDIAN);
1560         proto_tree_add_item(tree, hf_usb_vid_probe_min_ver,       tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1561         proto_tree_add_item(tree, hf_usb_vid_probe_max_ver,       tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1562         offset += 3;
1563     }
1564
1565     return offset;
1566 }
1567
1568 /**
1569  * Fetch the table that describes known control selectors for the specified unit/terminal.
1570  *
1571  * @param  entity_id      Unit or terminal of interest
1572  * @param  usb_conv_info  Information about the interface the entity is part of
1573  *
1574  * @return Table describing control selectors for the specified entity (may be NULL)
1575  */
1576 static value_string_ext*
1577 get_control_selector_values(guint8 entity_id, usb_conv_info_t *usb_conv_info)
1578 {
1579     video_conv_info_t *video_conv_info;
1580     video_entity_t    *entity = NULL;
1581     value_string_ext  *selectors = NULL;
1582
1583     if (usb_conv_info == NULL)
1584         return NULL;
1585
1586     video_conv_info = (video_conv_info_t *)usb_conv_info->class_data;
1587     if (video_conv_info)
1588         entity = (video_entity_t*) wmem_tree_lookup32(video_conv_info->entities, entity_id);
1589
1590     if (entity_id == 0)
1591     {
1592         /* Interface Request*/
1593         switch (usb_conv_info->interfaceSubclass)
1594         {
1595             case SC_VIDEOCONTROL:
1596                 selectors = &cs_control_interface_ext;
1597                 break;
1598
1599             case SC_VIDEOSTREAMING:
1600                 selectors = &cs_streaming_interface_ext;
1601                 break;
1602
1603             default:
1604                 break;
1605         }
1606     }
1607     else if (entity)
1608     {
1609         switch (entity->subtype)
1610         {
1611             case VC_INPUT_TERMINAL:
1612                 if (entity->terminalType == ITT_CAMERA)
1613                 {
1614                     selectors = &cs_camera_terminal_ext;
1615                 }
1616                 break;
1617
1618             case VC_PROCESSING_UNIT:
1619                 selectors = &cs_processing_unit_ext;
1620                 break;
1621
1622             case VC_SELECTOR_UNIT:
1623                 selectors = &cs_selector_unit_ext;
1624                 break;
1625
1626             default:
1627                 break;
1628         }
1629     }
1630
1631     return selectors;
1632 }
1633
1634 /**
1635  * Fetch the name of an entity's control.
1636  *
1637  * @param  entity_id      Unit or terminal of interest
1638  * @param  control_sel    Control of interest
1639  * @param  usb_conv_info  Information about the interface the entity is part of
1640  *
1641  * @return Table describing control selectors for the specified entity (may be NULL)
1642  */
1643 static const gchar*
1644 get_control_selector_name(guint8 entity_id, guint8 control_sel, usb_conv_info_t *usb_conv_info)
1645 {
1646     const gchar      *control_name = NULL;
1647     value_string_ext *selectors = NULL;
1648
1649     selectors = get_control_selector_values(entity_id, usb_conv_info);
1650
1651     if (selectors)
1652         control_name = try_val_to_str_ext(control_sel, selectors);
1653
1654     return control_name;
1655 }
1656
1657 /* Dissect the response to a GET INFO request */
1658 static int
1659 dissect_usb_vid_control_info(proto_tree *tree, tvbuff_t *tvb, int offset)
1660 {
1661     static const int *capability_bits[] = {
1662         &hf_usb_vid_control_info_D[0],
1663         &hf_usb_vid_control_info_D[1],
1664         &hf_usb_vid_control_info_D[2],
1665         &hf_usb_vid_control_info_D[3],
1666         &hf_usb_vid_control_info_D[4],
1667         &hf_usb_vid_control_info_D[5],
1668         &hf_usb_vid_control_info_D[6],
1669         NULL
1670     };
1671
1672     DISSECTOR_ASSERT(array_length(capability_bits) == (1+array_length(hf_usb_vid_control_info_D)));
1673
1674     proto_tree_add_bitmask(tree, tvb, offset, hf_usb_vid_control_info,
1675                            ett_control_capabilities, capability_bits, ENC_NA);
1676
1677     return offset+1;
1678 }
1679
1680 /* Dissect all remaining bytes in the tvb as a specified type of UVC value.
1681  * These are displayed as an unsigned integer where possible, otherwise just as
1682  * a text item.
1683  *
1684  * @param tree     the protocol tree to which an item will be added
1685  * @param tvb      the tv_buff with the (remaining) packet data
1686  * @param offset   How far into tvb the value data begins
1687  * @param request  Identifies type of value - either bRequest from a CONTROL
1688  *                 transfer (i.e., USB_SETUP_GET_MAX), or bValue from an
1689  *                 INTERRUPT transfer (i.e., CONTROL_CHANGE_MAX).
1690  */
1691 static void
1692 dissect_usb_vid_control_value(proto_tree *tree, tvbuff_t *tvb, int offset, guint8 request)
1693 {
1694     gint        value_size;
1695     const char *fallback_name;
1696     int         hf;
1697
1698     switch (request)
1699     {
1700         case USB_SETUP_GET_DEF:
1701             hf = hf_usb_vid_control_default;
1702             fallback_name = "Default Value";
1703             break;
1704
1705         case USB_SETUP_GET_MIN:
1706         case CONTROL_CHANGE_MIN:
1707             hf = hf_usb_vid_control_min;
1708             fallback_name = "Min Value";
1709             break;
1710
1711         case USB_SETUP_GET_MAX:
1712         case CONTROL_CHANGE_MAX:
1713             hf = hf_usb_vid_control_max;
1714             fallback_name = "Max Value";
1715             break;
1716
1717         case USB_SETUP_GET_RES:
1718             hf = hf_usb_vid_control_res;
1719             fallback_name = "Resolution";
1720             break;
1721
1722         case USB_SETUP_GET_CUR:
1723         case USB_SETUP_SET_CUR:
1724         case CONTROL_CHANGE_VALUE:
1725             hf = hf_usb_vid_control_cur;
1726             fallback_name = "Current Value";
1727             break;
1728
1729         /* @todo UVC 1.5 USB_SETUP_x_ALL?
1730          *       They are poorly specified.
1731          */
1732
1733         default:
1734             hf = -1;
1735             fallback_name = "Value";
1736             break;
1737     }
1738
1739     value_size = tvb_reported_length_remaining(tvb, offset);
1740
1741     if (hf != -1)
1742     {
1743         header_field_info *hfinfo;
1744         hfinfo = proto_registrar_get_nth(hf);
1745         DISSECTOR_ASSERT(IS_FT_INT(hfinfo->type) || IS_FT_UINT(hfinfo->type));
1746     }
1747
1748     if ((hf != -1) && (value_size <= 4))
1749     {
1750         proto_tree_add_item(tree, hf, tvb, offset, value_size, ENC_LITTLE_ENDIAN);
1751     }
1752     else
1753     {
1754         /* @todo Display as FT_BYTES with a big-endian disclaimer?
1755          * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7933
1756          */
1757         proto_tree_add_bytes_format(tree, hf_usb_vid_control_value, tvb, offset, value_size, NULL, "%s", fallback_name);
1758     }
1759 }
1760
1761 /**
1762  * Dissect video class GET/SET transactions.
1763  *
1764  * @param  pinfo           Information associated with the packet being dissected
1765  * @param  tree            protocol tree to which fields should be added
1766  * @param  tvb             the tv_buff with the (remaining) packet data
1767  * @param  offset          where in tvb to begin dissection.
1768  *                         On entry this refers to the bRequest field of the SETUP
1769  *                         transaction.
1770  * @param  is_request      true if the packet is host-to-device,
1771  *                         false if device-to-host
1772  * @param  usb_trans_info  Information specific to this request/response pair
1773  * @param  usb_conv_info   Information about the conversation with the host
1774  */
1775 static int
1776 dissect_usb_vid_get_set(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
1777                         int offset, gboolean is_request,
1778                         usb_trans_info_t *usb_trans_info,
1779                         usb_conv_info_t *usb_conv_info)
1780 {
1781     const gchar *short_name = NULL;
1782     guint8       control_sel;
1783     guint8       entity_id;
1784
1785     entity_id   = usb_trans_info->setup.wIndex >> 8;
1786     control_sel = usb_trans_info->setup.wValue >> 8;
1787
1788     /* Display something informative in the INFO column */
1789     col_append_str(pinfo->cinfo, COL_INFO, " [");
1790     short_name = get_control_selector_name(entity_id, control_sel, usb_conv_info);
1791
1792     if (short_name)
1793         col_append_str(pinfo->cinfo, COL_INFO, short_name);
1794     else
1795     {
1796         short_name = "Unknown";
1797
1798         if (entity_id == 0)
1799         {
1800             col_append_fstr(pinfo->cinfo, COL_INFO, "Interface %u control 0x%x",
1801                             usb_conv_info->interfaceNum, control_sel);
1802         }
1803         else
1804         {
1805             col_append_fstr(pinfo->cinfo, COL_INFO, "Unit %u control 0x%x",
1806                             entity_id, control_sel);
1807         }
1808     }
1809
1810     col_append_str(pinfo->cinfo, COL_INFO, "]");
1811     col_set_fence(pinfo->cinfo, COL_INFO);
1812
1813     /* Add information on request context,
1814      * as GENERATED fields if not directly available (for filtering)
1815      */
1816     if (is_request)
1817     {
1818         /* Move gaze to control selector (MSB of wValue) */
1819         offset++;
1820         proto_tree_add_uint_format_value(tree, hf_usb_vid_control_selector, tvb,
1821                                      offset, 1, control_sel, "%s (0x%02x)", short_name, control_sel);
1822         offset++;
1823
1824         proto_tree_add_item(tree, hf_usb_vid_control_interface, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1825         offset++;
1826
1827         proto_tree_add_item(tree, hf_usb_vid_control_entity, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1828         offset++;
1829
1830         proto_tree_add_item(tree, hf_usb_vid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1831         offset += 2;
1832     }
1833     else
1834     {
1835         proto_item *ti;
1836
1837         ti = proto_tree_add_uint(tree, hf_usb_vid_control_interface, tvb, 0, 0,
1838                                  usb_trans_info->setup.wIndex & 0xFF);
1839         proto_item_set_generated(ti);
1840
1841         ti = proto_tree_add_uint(tree, hf_usb_vid_control_entity, tvb, 0, 0, entity_id);
1842         proto_item_set_generated(ti);
1843
1844         ti = proto_tree_add_uint_format_value(tree, hf_usb_vid_control_selector, tvb,
1845                                      0, 0, control_sel, "%s (0x%02x)", short_name, control_sel);
1846         proto_item_set_generated(ti);
1847     }
1848
1849     if (!is_request || (usb_trans_info->setup.request == USB_SETUP_SET_CUR))
1850     {
1851         gint value_size = tvb_reported_length_remaining(tvb, offset);
1852
1853         if (value_size != 0)
1854         {
1855             if ((entity_id == 0) && (usb_conv_info->interfaceSubclass == SC_VIDEOSTREAMING))
1856             {
1857                 if ((control_sel == VS_PROBE_CONTROL) || (control_sel == VS_COMMIT_CONTROL))
1858                 {
1859                     int old_offset = offset;
1860                     offset = dissect_usb_vid_probe(tree, tvb, offset);
1861                     value_size -= (offset - old_offset);
1862                 }
1863             }
1864             else
1865             {
1866                 if (usb_trans_info->setup.request == USB_SETUP_GET_INFO)
1867                 {
1868                     dissect_usb_vid_control_info(tree, tvb, offset);
1869                     offset++;
1870                     value_size--;
1871                 }
1872                 else if (usb_trans_info->setup.request == USB_SETUP_GET_LEN)
1873                 {
1874                     proto_tree_add_item(tree, hf_usb_vid_control_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1875                     offset += 2;
1876                     value_size -= 2;
1877                 }
1878                 else if (   (usb_trans_info->setup.request == USB_SETUP_GET_CUR)
1879                          && (entity_id == 0)
1880                          && (usb_conv_info->interfaceSubclass == SC_VIDEOCONTROL)
1881                          && (control_sel == VC_REQUEST_ERROR_CODE_CONTROL))
1882                 {
1883                     proto_tree_add_item(tree, hf_usb_vid_request_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1884                     offset++;
1885                     value_size--;
1886                 }
1887                 else
1888                 {
1889                     dissect_usb_vid_control_value(tree, tvb, offset, usb_trans_info->setup.request);
1890                     offset += value_size;
1891                     value_size = 0;
1892                 }
1893             }
1894
1895             if (value_size > 0)
1896             {
1897                 proto_tree_add_item(tree, hf_usb_vid_control_data, tvb, offset, -1, ENC_NA);
1898                 offset += value_size;
1899             }
1900         }
1901     }
1902
1903     return offset;
1904 }
1905
1906 /* Table for dispatch of video class SETUP transactions based on bRequest.
1907  * At the moment this is overkill since the same function handles all defined
1908  * requests.
1909  */
1910 typedef int (*usb_setup_dissector)(packet_info *pinfo, proto_tree *tree,
1911         tvbuff_t *tvb, int offset,
1912         gboolean is_request,
1913         usb_trans_info_t *usb_trans_info,
1914         usb_conv_info_t *usb_conv_info);
1915
1916 typedef struct _usb_setup_dissector_table_t
1917 {
1918     guint8 request;
1919     usb_setup_dissector dissector;
1920 } usb_setup_dissector_table_t;
1921
1922 static const usb_setup_dissector_table_t setup_dissectors[] = {
1923         {USB_SETUP_SET_CUR,      dissect_usb_vid_get_set},
1924         {USB_SETUP_SET_CUR_ALL,  dissect_usb_vid_get_set},
1925         {USB_SETUP_GET_CUR,      dissect_usb_vid_get_set},
1926         {USB_SETUP_GET_MIN,      dissect_usb_vid_get_set},
1927         {USB_SETUP_GET_MAX,      dissect_usb_vid_get_set},
1928         {USB_SETUP_GET_RES,      dissect_usb_vid_get_set},
1929         {USB_SETUP_GET_LEN,      dissect_usb_vid_get_set},
1930         {USB_SETUP_GET_INFO,     dissect_usb_vid_get_set},
1931         {USB_SETUP_GET_DEF,      dissect_usb_vid_get_set},
1932         {USB_SETUP_GET_CUR_ALL,  dissect_usb_vid_get_set},
1933         {USB_SETUP_GET_MIN_ALL,  dissect_usb_vid_get_set},
1934         {USB_SETUP_GET_MAX_ALL,  dissect_usb_vid_get_set},
1935         {USB_SETUP_GET_RES_ALL,  dissect_usb_vid_get_set},
1936         {0, NULL}
1937 };
1938
1939 static const value_string setup_request_names_vals[] = {
1940         {USB_SETUP_SET_CUR,      "SET CUR"},
1941         {USB_SETUP_SET_CUR_ALL,  "SET CUR ALL"},
1942         {USB_SETUP_GET_CUR,      "GET CUR"},
1943         {USB_SETUP_GET_MIN,      "GET MIN"},
1944         {USB_SETUP_GET_MAX,      "GET MAX"},
1945         {USB_SETUP_GET_RES,      "GET RES"},
1946         {USB_SETUP_GET_LEN,      "GET LEN"},
1947         {USB_SETUP_GET_INFO,     "GET INFO"},
1948         {USB_SETUP_GET_DEF,      "GET DEF"},
1949         {USB_SETUP_GET_CUR_ALL,  "GET CUR ALL"},
1950         {USB_SETUP_GET_MIN_ALL,  "GET MIN ALL"},
1951         {USB_SETUP_GET_MAX_ALL,  "GET MAX ALL"},
1952         {USB_SETUP_GET_RES_ALL,  "GET RES ALL"},
1953         {USB_SETUP_GET_DEF_ALL,  "GET DEF ALL"},
1954         {0, NULL}
1955 };
1956
1957 /* Registered dissector for video class-specific control requests.
1958  * Dispatch to an appropriate dissector function.
1959  *
1960  * @param tvb    the tv_buff with the (remaining) packet data.
1961  *               On entry, the gaze is set to SETUP bRequest field.
1962  * @param pinfo  the packet info of this packet (additional info)
1963  * @param tree   the protocol tree to be built or NULL
1964  * @param data   Not used
1965  *
1966  * @return   0   no class specific dissector was found
1967  * @return  <0   not enough data
1968  * @return  >0   amount of data in the descriptor
1969  */
1970 static int
1971 dissect_usb_vid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1972 {
1973     gboolean             is_request = (pinfo->srcport == NO_ENDPOINT);
1974     usb_conv_info_t     *usb_conv_info;
1975     usb_trans_info_t    *usb_trans_info;
1976     int                  offset     = 0;
1977     usb_setup_dissector  dissector  = NULL;
1978     const usb_setup_dissector_table_t *tmp;
1979
1980     /* Reject the packet if data or usb_trans_info are NULL */
1981     if (data == NULL || ((usb_conv_info_t *)data)->usb_trans_info == NULL)
1982         return 0;
1983     usb_conv_info = (usb_conv_info_t *)data;
1984     usb_trans_info = usb_conv_info->usb_trans_info;
1985
1986     /* See if we can find a class specific dissector for this request */
1987     for (tmp=setup_dissectors; tmp->dissector; tmp++)
1988     {
1989         if (tmp->request == usb_trans_info->setup.request)
1990         {
1991             dissector = tmp->dissector;
1992             break;
1993         }
1994     }
1995     /* No we could not find any class specific dissector for this request
1996      * return FALSE and let USB try any of the standard requests.
1997      */
1998     if (!dissector)
1999         return 0;
2000
2001     col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBVIDEO");
2002     col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2003                 val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
2004                 is_request?"Request ":"Response");
2005
2006     if (is_request)
2007     {
2008         proto_tree_add_item(tree, hf_usb_vid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2009         offset += 1;
2010     }
2011
2012     offset = dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
2013     return offset;
2014 }
2015
2016 /* Registered dissector for video class-specific URB_INTERRUPT
2017  *
2018  * @param tvb    the tv_buff with the (remaining) packet data
2019  * @param pinfo  the packet info of this packet (additional info)
2020  * @param tree   the protocol tree to be built or NULL
2021  * @param data   Unused API parameter
2022  *
2023  * @return   0   no class specific dissector was found
2024  * @return  <0   not enough data
2025  * @return  >0   amount of data in the descriptor
2026  */
2027 static int
2028 dissect_usb_vid_interrupt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2029 {
2030     usb_conv_info_t *usb_conv_info;
2031     gint bytes_available;
2032     int  offset = 0;
2033
2034     usb_conv_info   = (usb_conv_info_t *)data;
2035     bytes_available = tvb_reported_length_remaining(tvb, offset);
2036
2037     col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBVIDEO");
2038
2039     if (bytes_available > 0)
2040     {
2041         guint8 originating_interface;
2042         guint8 originating_entity;
2043
2044         originating_interface = tvb_get_guint8(tvb, offset) & INT_ORIGINATOR_MASK;
2045         proto_tree_add_item(tree, hf_usb_vid_interrupt_bStatusType, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2046         offset++;
2047
2048         originating_entity = tvb_get_guint8(tvb, offset);
2049         proto_tree_add_item(tree, hf_usb_vid_interrupt_bOriginator, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2050         offset++;
2051
2052         if (originating_interface == INT_VIDEOCONTROL)
2053         {
2054             guint8 control_sel;
2055             guint8 attribute;
2056             const gchar *control_name;
2057
2058             proto_tree_add_item(tree, hf_usb_vid_control_interrupt_bEvent, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2059             offset++;
2060
2061             control_sel = tvb_get_guint8(tvb, offset);
2062             control_name = get_control_selector_name(originating_entity, control_sel, usb_conv_info);
2063             if (!control_name)
2064                 control_name = "Unknown";
2065
2066             proto_tree_add_uint_format_value(tree, hf_usb_vid_control_selector, tvb,
2067                                              offset, 1, control_sel, "%s (0x%02x)",
2068                                              control_name, control_sel);
2069             offset++;
2070
2071             attribute = tvb_get_guint8(tvb, offset);
2072             proto_tree_add_item(tree, hf_usb_vid_interrupt_bAttribute, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2073             offset++;
2074
2075             switch (attribute)
2076             {
2077                 case CONTROL_CHANGE_FAILURE:
2078                     proto_tree_add_item(tree, hf_usb_vid_request_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2079                     offset++;
2080                     break;
2081
2082                 case CONTROL_CHANGE_INFO:
2083                     offset = dissect_usb_vid_control_info(tree, tvb, offset);
2084                     break;
2085
2086                 case CONTROL_CHANGE_VALUE:
2087                 case CONTROL_CHANGE_MIN:
2088                 case CONTROL_CHANGE_MAX:
2089                     dissect_usb_vid_control_value(tree, tvb, offset, attribute);
2090                     offset += tvb_reported_length_remaining(tvb, offset);
2091                     break;
2092
2093                 default:
2094                     proto_tree_add_item(tree, hf_usb_vid_value_data, tvb, offset, -1, ENC_NA);
2095                     offset += tvb_reported_length_remaining(tvb, offset);
2096                     break;
2097             }
2098         }
2099         else if (originating_interface == INT_VIDEOSTREAMING)
2100         {
2101             /* @todo */
2102         }
2103     }
2104     else
2105         offset = -2;
2106
2107     return offset;
2108 }
2109
2110 void
2111 proto_register_usb_vid(void)
2112 {
2113     static hf_register_info hf[] = {
2114         /***** Setup *****/
2115             { &hf_usb_vid_request,
2116                     { "bRequest", "usbvideo.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
2117                             NULL, HFILL }
2118             },
2119
2120             { &hf_usb_vid_length,
2121                     { "wLength", "usbvideo.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
2122                             NULL, HFILL }
2123             },
2124
2125         /***** Request Error Control *****/
2126             { &hf_usb_vid_request_error,
2127                     { "bRequestErrorCode", "usbvideo.reqerror.code",
2128                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
2129                             &request_error_codes_ext, 0,
2130                             "Request Error Code", HFILL }
2131             },
2132
2133         /***** Unit/Terminal Controls *****/
2134             { &hf_usb_vid_control_selector,
2135                     { "Control Selector", "usbvideo.control.selector", FT_UINT8, BASE_HEX, NULL, 0x0,
2136                             "ID of the control within its entity", HFILL }
2137             },
2138
2139             { &hf_usb_vid_control_entity,
2140                     { "Entity", "usbvideo.control.entity", FT_UINT8, BASE_HEX, NULL, 0x0,
2141                             "Unit or terminal to which the control belongs", HFILL }
2142             },
2143
2144             { &hf_usb_vid_control_interface,
2145                     { "Interface", "usbvideo.control.interface", FT_UINT8, BASE_HEX, NULL, 0x0,
2146                             "Interface to which the control belongs", HFILL }
2147             },
2148
2149             { &hf_usb_vid_control_info,
2150                     { "Info (Capabilities/State)", "usbvideo.control.info",
2151                             FT_UINT8, BASE_HEX, NULL, 0,
2152                             "Control capabilities and current state", HFILL }
2153             },
2154
2155             { &hf_usb_vid_control_info_D[0],
2156                     { "Supports GET", "usbvideo.control.info.D0",
2157                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<0),
2158                             NULL, HFILL }
2159             },
2160
2161             { &hf_usb_vid_control_info_D[1],
2162                     { "Supports SET", "usbvideo.control.info.D1",
2163                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<1),
2164                             NULL, HFILL }
2165             },
2166
2167             { &hf_usb_vid_control_info_D[2],
2168                     { "Disabled due to automatic mode", "usbvideo.control.info.D2",
2169                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<2),
2170                             NULL, HFILL }
2171             },
2172
2173             { &hf_usb_vid_control_info_D[3],
2174                     { "Autoupdate", "usbvideo.control.info.D3",
2175                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<3),
2176                             NULL, HFILL }
2177             },
2178
2179             { &hf_usb_vid_control_info_D[4],
2180                     { "Asynchronous", "usbvideo.control.info.D4",
2181                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<4),
2182                             NULL, HFILL }
2183             },
2184
2185             { &hf_usb_vid_control_info_D[5],
2186                     { "Disabled due to incompatibility with Commit state", "usbvideo.control.info.D5",
2187                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<5),
2188                             NULL, HFILL }
2189             },
2190
2191             { &hf_usb_vid_control_info_D[6],
2192                     { "Reserved", "usbvideo.control.info.D6",
2193                             FT_UINT8, BASE_HEX, NULL, (3<<6),
2194                             NULL, HFILL }
2195             },
2196
2197             { &hf_usb_vid_control_length,
2198                     { "Control Length", "usbvideo.control.len",
2199                             FT_UINT16, BASE_DEC, NULL, 0,
2200                             "Control size in bytes", HFILL }
2201             },
2202
2203             { &hf_usb_vid_control_default,
2204                     { "Default value", "usbvideo.control.value.default",
2205                             FT_UINT32, BASE_DEC_HEX, NULL, 0,
2206                             NULL, HFILL }
2207             },
2208
2209             { &hf_usb_vid_control_min,
2210                     { "Minimum value", "usbvideo.control.value.min",
2211                             FT_UINT32, BASE_DEC_HEX, NULL, 0,
2212                             NULL, HFILL }
2213             },
2214
2215             { &hf_usb_vid_control_max,
2216                     { "Maximum value", "usbvideo.control.value.max",
2217                             FT_UINT32, BASE_DEC_HEX, NULL, 0,
2218                             NULL, HFILL }
2219             },
2220
2221             { &hf_usb_vid_control_res,
2222                     { "Resolution", "usbvideo.control.value.res",
2223                             FT_UINT32, BASE_DEC_HEX, NULL, 0,
2224                             NULL, HFILL }
2225             },
2226
2227             { &hf_usb_vid_control_cur,
2228                     { "Current value", "usbvideo.control.value.cur",
2229                             FT_UINT32, BASE_DEC_HEX, NULL, 0,
2230                             NULL, HFILL }
2231             },
2232
2233         /***** Terminal Descriptors *****/
2234
2235             /* @todo Decide whether to unify .name fields */
2236             { &hf_usb_vid_control_ifdesc_iTerminal,
2237                     { "iTerminal", "usbvideo.terminal.name", FT_UINT8, BASE_DEC, NULL, 0x0,
2238                             "String Descriptor describing this terminal", HFILL }
2239             },
2240
2241             /* @todo Decide whether to unify .terminal.id and .unit.id under .entityID */
2242             { &hf_usb_vid_control_ifdesc_terminal_id,
2243                     { "bTerminalID", "usbvideo.terminal.id", FT_UINT8, BASE_DEC, NULL, 0x0,
2244                             NULL, HFILL }
2245             },
2246
2247             { &hf_usb_vid_control_ifdesc_terminal_type,
2248                     { "wTerminalType", "usbvideo.terminal.type",
2249                             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &vc_terminal_types_ext, 0,
2250                             NULL, HFILL }
2251             },
2252
2253             { &hf_usb_vid_control_ifdesc_assoc_terminal,
2254                     { "bAssocTerminal", "usbvideo.terminal.assocTerminal", FT_UINT8, BASE_DEC, NULL, 0x0,
2255                             "Associated Terminal", HFILL }
2256             },
2257
2258         /***** Camera Terminal Descriptor *****/
2259
2260             { &hf_usb_vid_cam_objective_focal_len_min,
2261                     { "wObjectiveFocalLengthMin", "usbvideo.camera.objectiveFocalLengthMin",
2262                             FT_UINT16, BASE_DEC, NULL, 0,
2263                             "Minimum Focal Length for Optical Zoom", HFILL }
2264             },
2265
2266             { &hf_usb_vid_cam_objective_focal_len_max,
2267                     { "wObjectiveFocalLengthMax", "usbvideo.camera.objectiveFocalLengthMax",
2268                             FT_UINT16, BASE_DEC, NULL, 0,
2269                             "Minimum Focal Length for Optical Zoom", HFILL }
2270             },
2271
2272             { &hf_usb_vid_cam_ocular_focal_len,
2273                     { "wOcularFocalLength", "usbvideo.camera.ocularFocalLength",
2274                             FT_UINT16, BASE_DEC, NULL, 0,
2275                             "Ocular Focal Length for Optical Zoom", HFILL }
2276             },
2277
2278             { &hf_usb_vid_cam_control_D[0],
2279                     { "Scanning Mode", "usbvideo.camera.control.D0",
2280                             FT_BOOLEAN,
2281                             array_length(hf_usb_vid_cam_control_D),
2282                             TFS(&tfs_yes_no), (1<<0),
2283                             NULL, HFILL }
2284             },
2285
2286             { &hf_usb_vid_cam_control_D[1],
2287                     { "Auto Exposure Mode", "usbvideo.camera.control.D1",
2288                             FT_BOOLEAN,
2289                             array_length(hf_usb_vid_cam_control_D),
2290                             TFS(&tfs_yes_no), (1<<1),
2291                             NULL, HFILL }
2292             },
2293
2294             { &hf_usb_vid_cam_control_D[2],
2295                     { "Auto Exposure Priority", "usbvideo.camera.control.D2",
2296                             FT_BOOLEAN,
2297                             array_length(hf_usb_vid_cam_control_D),
2298                             TFS(&tfs_yes_no), (1<<2),
2299                             NULL, HFILL }
2300             },
2301
2302             { &hf_usb_vid_cam_control_D[3],
2303                     { "Exposure Time (Absolute)", "usbvideo.camera.control.D3",
2304                             FT_BOOLEAN,
2305                             array_length(hf_usb_vid_cam_control_D),
2306                             TFS(&tfs_yes_no), (1<<3),
2307                             NULL, HFILL }
2308             },
2309
2310             { &hf_usb_vid_cam_control_D[4],
2311                     { "Exposure Time (Relative)", "usbvideo.camera.control.D4",
2312                             FT_BOOLEAN,
2313                             array_length(hf_usb_vid_cam_control_D),
2314                             TFS(&tfs_yes_no), (1<<4),
2315                             NULL, HFILL }
2316             },
2317
2318             { &hf_usb_vid_cam_control_D[5],
2319                     { "Focus (Absolute)", "usbvideo.camera.control.D5",
2320                             FT_BOOLEAN,
2321                             array_length(hf_usb_vid_cam_control_D),
2322                             TFS(&tfs_yes_no), (1<<5),
2323                             NULL, HFILL }
2324             },
2325
2326             { &hf_usb_vid_cam_control_D[6],
2327                     { "Focus (Relative)", "usbvideo.camera.control.D6",
2328                             FT_BOOLEAN,
2329                             array_length(hf_usb_vid_cam_control_D),
2330                             TFS(&tfs_yes_no), (1<<6),
2331                             NULL, HFILL }
2332             },
2333
2334             { &hf_usb_vid_cam_control_D[7],
2335                     { "Iris (Absolute)", "usbvideo.camera.control.D7",
2336                             FT_BOOLEAN,
2337                             array_length(hf_usb_vid_cam_control_D),
2338                             TFS(&tfs_yes_no), (1<<7),
2339                             NULL, HFILL }
2340             },
2341
2342             { &hf_usb_vid_cam_control_D[8],
2343                     { "Iris (Relative)", "usbvideo.camera.control.D8",
2344                             FT_BOOLEAN,
2345                             array_length(hf_usb_vid_cam_control_D),
2346                             TFS(&tfs_yes_no), (1<<8),
2347                             NULL, HFILL }
2348             },
2349
2350             { &hf_usb_vid_cam_control_D[9],
2351                     { "Zoom (Absolute)", "usbvideo.camera.control.D9",
2352                             FT_BOOLEAN,
2353                             array_length(hf_usb_vid_cam_control_D),
2354                             TFS(&tfs_yes_no), (1<<9),
2355                             NULL, HFILL }
2356             },
2357
2358             { &hf_usb_vid_cam_control_D[10],
2359                     { "Zoom (Relative)", "usbvideo.camera.control.D10",
2360                             FT_BOOLEAN,
2361                             array_length(hf_usb_vid_cam_control_D),
2362                             TFS(&tfs_yes_no), (1<<10),
2363                             NULL, HFILL }
2364             },
2365
2366             { &hf_usb_vid_cam_control_D[11],
2367                     { "PanTilt (Absolute)", "usbvideo.camera.control.D11",
2368                             FT_BOOLEAN,
2369                             array_length(hf_usb_vid_cam_control_D),
2370                             TFS(&tfs_yes_no), (1<<11),
2371                             NULL, HFILL }
2372             },
2373
2374             { &hf_usb_vid_cam_control_D[12],
2375                     { "PanTilt (Relative)", "usbvideo.camera.control.D12",
2376                             FT_BOOLEAN,
2377                             array_length(hf_usb_vid_cam_control_D),
2378                             TFS(&tfs_yes_no), (1<<12),
2379                             NULL, HFILL }
2380             },
2381
2382             { &hf_usb_vid_cam_control_D[13],
2383                     { "Roll (Absolute)", "usbvideo.camera.control.D13",
2384                             FT_BOOLEAN,
2385                             array_length(hf_usb_vid_cam_control_D),
2386                             TFS(&tfs_yes_no), (1<<13),
2387                             NULL, HFILL }
2388             },
2389
2390             { &hf_usb_vid_cam_control_D[14],
2391                     { "Roll (Relative)", "usbvideo.camera.control.D14",
2392                             FT_BOOLEAN,
2393                             array_length(hf_usb_vid_cam_control_D),
2394                             TFS(&tfs_yes_no), (1<<14),
2395                             NULL, HFILL }
2396             },
2397
2398             { &hf_usb_vid_cam_control_D[15],
2399                     { "D15", "usbvideo.camera.control.D15",
2400                             FT_BOOLEAN,
2401                             array_length(hf_usb_vid_cam_control_D),
2402                             TFS(&tfs_yes_no), (1<<15),
2403                             "Reserved", HFILL }
2404             },
2405
2406             { &hf_usb_vid_cam_control_D[16],
2407                     { "D16", "usbvideo.camera.control.D16",
2408                             FT_BOOLEAN,
2409                             array_length(hf_usb_vid_cam_control_D),
2410                             TFS(&tfs_yes_no), (1<<16),
2411                             "Reserved", HFILL }
2412             },
2413
2414             { &hf_usb_vid_cam_control_D[17],
2415                     { "Auto Focus", "usbvideo.camera.control.D17",
2416                             FT_BOOLEAN,
2417                             array_length(hf_usb_vid_cam_control_D),
2418                             TFS(&tfs_yes_no), (1<<17),
2419                             NULL, HFILL }
2420             },
2421
2422             { &hf_usb_vid_cam_control_D[18],
2423                     { "Privacy", "usbvideo.camera.control.D18",
2424                             FT_BOOLEAN,
2425                             array_length(hf_usb_vid_cam_control_D),
2426                             TFS(&tfs_yes_no), (1<<18),
2427                             NULL, HFILL }
2428             },
2429
2430             { &hf_usb_vid_cam_control_D[19],
2431                     { "Focus (Simple)", "usbvideo.camera.control.D19",
2432                             FT_BOOLEAN,
2433                             array_length(hf_usb_vid_cam_control_D),
2434                             TFS(&tfs_yes_no), (1<<19),
2435                             NULL, HFILL }
2436             },
2437
2438             { &hf_usb_vid_cam_control_D[20],
2439                     { "Window", "usbvideo.camera.control.D20",
2440                             FT_BOOLEAN,
2441                             array_length(hf_usb_vid_cam_control_D),
2442                             TFS(&tfs_yes_no), (1<<20),
2443                             NULL, HFILL }
2444             },
2445
2446             { &hf_usb_vid_cam_control_D[21],
2447                     { "Region of Interest", "usbvideo.camera.control.D21",
2448                             FT_BOOLEAN,
2449                             array_length(hf_usb_vid_cam_control_D),
2450                             TFS(&tfs_yes_no), (1<<21),
2451                             NULL, HFILL }
2452             },
2453
2454         /***** Unit Descriptors *****/
2455
2456             { &hf_usb_vid_control_ifdesc_unit_id,
2457                     { "bUnitID", "usbvideo.unit.id", FT_UINT8, BASE_DEC, NULL, 0x0,
2458                             NULL, HFILL }
2459             },
2460
2461             { &hf_usb_vid_num_inputs,
2462                     { "bNrInPins", "usbvideo.unit.numInputs",
2463                             FT_UINT8, BASE_DEC, NULL, 0,
2464                             "Number of input pins", HFILL }
2465             },
2466
2467             { &hf_usb_vid_sources,
2468                     { "baSourceID", "usbvideo.unit.sources",
2469                             FT_BYTES, BASE_NONE, NULL, 0,
2470                             "Input entity IDs", HFILL }
2471             },
2472
2473
2474         /***** Processing Unit Descriptor *****/
2475
2476             { &hf_usb_vid_iProcessing,
2477                     { "iProcessing", "usbvideo.processor.name", FT_UINT8, BASE_DEC, NULL, 0x0,
2478                             "String Descriptor describing this terminal", HFILL }
2479             },
2480
2481             { &hf_usb_vid_proc_control_D[0],
2482                     { "Brightness", "usbvideo.processor.control.D0",
2483                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<0),
2484                             NULL, HFILL }
2485             },
2486
2487             { &hf_usb_vid_proc_control_D[1],
2488                     { "Contrast", "usbvideo.processor.control.D1",
2489                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<1),
2490                             NULL, HFILL }
2491             },
2492
2493             { &hf_usb_vid_proc_control_D[2],
2494                     { "Hue", "usbvideo.processor.control.D2",
2495                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<2),
2496                             NULL, HFILL }
2497             },
2498
2499             { &hf_usb_vid_proc_control_D[3],
2500                     { "Saturation", "usbvideo.processor.control.D3",
2501                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<3),
2502                             NULL, HFILL }
2503             },
2504
2505             { &hf_usb_vid_proc_control_D[4],
2506                     { "Sharpness", "usbvideo.processor.control.D4",
2507                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<4),
2508                             NULL, HFILL }
2509             },
2510
2511             { &hf_usb_vid_proc_control_D[5],
2512                     { "Gamma", "usbvideo.processor.control.D5",
2513                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<5),
2514                             NULL, HFILL }
2515             },
2516
2517             { &hf_usb_vid_proc_control_D[6],
2518                     { "White Balance Temperature", "usbvideo.processor.control.D6",
2519                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<6),
2520                             NULL, HFILL }
2521             },
2522
2523             { &hf_usb_vid_proc_control_D[7],
2524                     { "White Balance Component", "usbvideo.processor.control.D7",
2525                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<7),
2526                             NULL, HFILL }
2527             },
2528
2529             { &hf_usb_vid_proc_control_D[8],
2530                     { "Backlight Compensation", "usbvideo.processor.control.D8",
2531                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<8),
2532                             NULL, HFILL }
2533             },
2534
2535             { &hf_usb_vid_proc_control_D[9],
2536                     { "Gain", "usbvideo.processor.control.D9",
2537                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<9),
2538                             NULL, HFILL }
2539             },
2540
2541             { &hf_usb_vid_proc_control_D[10],
2542                     { "Power Line Frequency", "usbvideo.processor.control.D10",
2543                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<10),
2544                             NULL, HFILL }
2545             },
2546
2547             { &hf_usb_vid_proc_control_D[11],
2548                     { "Hue, Auto", "usbvideo.processor.control.D11",
2549                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<11),
2550                             NULL, HFILL }
2551             },
2552
2553             { &hf_usb_vid_proc_control_D[12],
2554                     { "White Balance Temperature, Auto", "usbvideo.processor.control.D12",
2555                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<12),
2556                             NULL, HFILL }
2557             },
2558
2559             { &hf_usb_vid_proc_control_D[13],
2560                     { "White Balance Component, Auto", "usbvideo.processor.control.D13",
2561                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<13),
2562                             NULL, HFILL }
2563             },
2564
2565             { &hf_usb_vid_proc_control_D[14],
2566                     { "Digital Multiplier", "usbvideo.processor.control.D14",
2567                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<14),
2568                             NULL, HFILL }
2569             },
2570
2571             { &hf_usb_vid_proc_control_D[15],
2572                     { "Digital Multiplier Limit", "usbvideo.processor.control.D15",
2573                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<15),
2574                             "Reserved", HFILL }
2575             },
2576
2577             { &hf_usb_vid_proc_control_D[16],
2578                     { "Analog Video Standard", "usbvideo.processor.control.D16",
2579                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<16),
2580                             "Reserved", HFILL }
2581             },
2582
2583             { &hf_usb_vid_proc_control_D[17],
2584                     { "Analog Video Lock Status", "usbvideo.processor.control.D17",
2585                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<17),
2586                             NULL, HFILL }
2587             },
2588
2589             { &hf_usb_vid_proc_control_D[18],
2590                     { "Contrast, Auto", "usbvideo.processor.control.D18",
2591                             FT_BOOLEAN, 24, TFS(&tfs_yes_no), (1<<18),
2592                             NULL, HFILL }
2593             },
2594
2595             { &hf_usb_vid_proc_standards,
2596                     { "bmVideoStandards", "usbvideo.processor.standards",
2597                             FT_UINT8, BASE_HEX, NULL, 0,
2598                             "Supported analog video standards", HFILL }
2599             },
2600
2601             { &hf_usb_vid_proc_standards_D[0],
2602                     { "None", "usbvideo.processor.standards.D0",
2603                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<0),
2604                             NULL, HFILL }
2605             },
2606
2607             { &hf_usb_vid_proc_standards_D[1],
2608                     { "NTSC - 525/60", "usbvideo.processor.standards.D1",
2609                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<1),
2610                             NULL, HFILL }
2611             },
2612
2613             { &hf_usb_vid_proc_standards_D[2],
2614                     { "PAL - 625/50", "usbvideo.processor.standards.D2",
2615                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<2),
2616                             NULL, HFILL }
2617             },
2618
2619             { &hf_usb_vid_proc_standards_D[3],
2620                     { "SECAM - 625/50", "usbvideo.processor.standards.D3",
2621                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<3),
2622                             NULL, HFILL }
2623             },
2624
2625             { &hf_usb_vid_proc_standards_D[4],
2626                     { "NTSC - 625/50", "usbvideo.processor.standards.D4",
2627                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<4),
2628                             NULL, HFILL }
2629             },
2630
2631             { &hf_usb_vid_proc_standards_D[5],
2632                     { "PAL - 525/60", "usbvideo.processor.standards.D5",
2633                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<5),
2634                             NULL, HFILL }
2635             },
2636
2637             { &hf_usb_vid_max_multiplier,
2638                     { "wMaxMultiplier", "usbvideo.processor.maxMultiplier",
2639                             FT_UINT16, BASE_DEC, NULL, 0,
2640                             "100 x max digital multiplication", HFILL }
2641             },
2642
2643         /***** Selector Unit Descriptor *****/
2644
2645             { &hf_usb_vid_iSelector,
2646                     { "iSelector", "usbvideo.selector.name", FT_UINT8, BASE_DEC, NULL, 0x0,
2647                             "String Descriptor describing this terminal", HFILL }
2648             },
2649
2650         /***** Extension Unit Descriptor *****/
2651
2652             { &hf_usb_vid_iExtension,
2653                     { "iExtension", "usbvideo.extension.name", FT_UINT8, BASE_DEC, NULL, 0x0,
2654                             "String Descriptor describing this terminal", HFILL }
2655             },
2656
2657             { &hf_usb_vid_exten_guid,
2658                     { "guid", "usbvideo.extension.guid",
2659                             FT_GUID, BASE_NONE, NULL, 0,
2660                             "Identifier", HFILL }
2661             },
2662
2663             { &hf_usb_vid_exten_num_controls,
2664                     { "bNumControls", "usbvideo.extension.numControls",
2665                             FT_UINT8, BASE_DEC, NULL, 0,
2666                             "Number of controls", HFILL }
2667             },
2668
2669         /***** Probe/Commit *****/
2670
2671             { &hf_usb_vid_probe_hint,
2672                     { "bmHint", "usbvideo.probe.hint",
2673                             FT_UINT16, BASE_HEX, NULL, 0,
2674                             "Fields to hold constant during negotiation", HFILL }
2675             },
2676
2677             { &hf_usb_vid_probe_hint_D[0],
2678                     { "dwFrameInterval", "usbvideo.probe.hint.D0",
2679                             FT_BOOLEAN, 5, TFS(&probe_hint_meaning), (1<<0),
2680                             "Frame Rate", HFILL }
2681             },
2682             { &hf_usb_vid_probe_hint_D[1],
2683                     { "wKeyFrameRate", "usbvideo.probe.hint.D1",
2684                             FT_BOOLEAN, 5, TFS(&probe_hint_meaning), (1<<1),
2685                             "Key Frame Rate", HFILL }
2686             },
2687             { &hf_usb_vid_probe_hint_D[2],
2688                     { "wPFrameRate", "usbvideo.probe.hint.D2",
2689                             FT_BOOLEAN, 5, TFS(&probe_hint_meaning), (1<<2),
2690                             "P-Frame Rate", HFILL }
2691             },
2692             { &hf_usb_vid_probe_hint_D[3],
2693                     { "wCompQuality", "usbvideo.probe.hint.D3",
2694                             FT_BOOLEAN, 5, TFS(&probe_hint_meaning), (1<<3),
2695                             "Compression Quality", HFILL }
2696             },
2697             { &hf_usb_vid_probe_hint_D[4],
2698                     { "wCompWindowSize", "usbvideo.probe.hint.D4",
2699                             FT_BOOLEAN, 5, TFS(&probe_hint_meaning), (1<<4),
2700                             "Compression Window Size", HFILL }
2701             },
2702
2703             { &hf_usb_vid_probe_key_frame_rate,
2704                     { "wKeyFrameRate", "usbvideo.probe.keyFrameRate",
2705                             FT_UINT16, BASE_DEC, NULL, 0,
2706                             "Key frame rate", HFILL }
2707             },
2708
2709             { &hf_usb_vid_probe_p_frame_rate,
2710                     { "wPFrameRate", "usbvideo.probe.pFrameRate",
2711                             FT_UINT16, BASE_DEC, NULL, 0,
2712                             "P frame rate", HFILL }
2713             },
2714
2715             { &hf_usb_vid_probe_comp_quality,
2716                     { "wCompQuality", "usbvideo.probe.compQuality",
2717                             FT_UINT16, BASE_DEC, NULL, 0,
2718                             "Compression quality [0-10000]", HFILL }
2719             },
2720
2721             { &hf_usb_vid_probe_comp_window,
2722                     { "wCompWindow", "usbvideo.probe.compWindow",
2723                             FT_UINT16, BASE_DEC, NULL, 0,
2724                             "Window size for average bit rate control", HFILL }
2725             },
2726             { &hf_usb_vid_probe_delay,
2727                     { "wDelay", "usbvideo.probe.delay",
2728                             FT_UINT16, BASE_DEC, NULL, 0,
2729                             "Latency in ms from capture to USB", HFILL }
2730             },
2731             { &hf_usb_vid_probe_max_frame_sz,
2732                     { "dwMaxVideoFrameSize", "usbvideo.probe.maxVideoFrameSize",
2733                             FT_UINT32, BASE_DEC, NULL, 0,
2734                             NULL, HFILL }
2735             },
2736             { &hf_usb_vid_probe_max_payload_sz,
2737                     { "dwMaxPayloadTransferSize", "usbvideo.probe.maxPayloadTransferSize",
2738                             FT_UINT32, BASE_DEC, NULL, 0,
2739                             NULL, HFILL }
2740             },
2741             { &hf_usb_vid_probe_clock_freq,
2742                     { "dwClockFrequency", "usbvideo.probe.clockFrequency",
2743                             FT_UINT32, BASE_DEC, NULL, 0,
2744                             "Device clock frequency in Hz", HFILL }
2745             },
2746
2747             { &hf_usb_vid_probe_framing,
2748                     { "bmFramingInfo", "usbvideo.probe.framing",
2749                             FT_UINT16, BASE_HEX, NULL, 0,
2750                             NULL, HFILL }
2751             },
2752
2753             { &hf_usb_vid_probe_framing_D[0],
2754                     { "Frame ID required", "usbvideo.probe.framing.D0",
2755                             FT_BOOLEAN, 2, TFS(&tfs_yes_no), (1<<0),
2756                             NULL, HFILL }
2757             },
2758             { &hf_usb_vid_probe_framing_D[1],
2759                     { "EOF utilized", "usbvideo.probe.framing.D1",
2760                             FT_BOOLEAN, 2, TFS(&tfs_yes_no), (1<<1),
2761                             NULL, HFILL }
2762             },
2763
2764             { &hf_usb_vid_probe_preferred_ver,
2765                     { "bPreferredVersion", "usbvideo.probe.preferredVersion",
2766                             FT_UINT8, BASE_DEC, NULL, 0,
2767                             "Preferred payload format version", HFILL }
2768             },
2769             { &hf_usb_vid_probe_min_ver,
2770                     { "bMinVersion", "usbvideo.probe.minVersion",
2771                             FT_UINT8, BASE_DEC, NULL, 0,
2772                             "Min supported payload format version", HFILL }
2773             },
2774             { &hf_usb_vid_probe_max_ver,
2775                     { "bPreferredVersion", "usbvideo.probe.maxVer",
2776                             FT_UINT8, BASE_DEC, NULL, 0,
2777                             "Max supported payload format version", HFILL }
2778             },
2779
2780             { &hf_usb_vid_control_ifdesc_dwClockFrequency,
2781                     { "dwClockFrequency", "usbvideo.probe.clockFrequency",
2782                             FT_UINT32, BASE_DEC, NULL, 0,
2783                             "Device clock frequency (Hz) for selected format", HFILL }
2784             },
2785
2786         /***** Format Descriptors *****/
2787
2788             { &hf_usb_vid_format_index,
2789                     { "bFormatIndex", "usbvideo.format.index",
2790                             FT_UINT8, BASE_DEC, NULL, 0,
2791                             "Index of this format descriptor", HFILL }
2792             },
2793
2794             { &hf_usb_vid_format_num_frame_descriptors,
2795                     { "bNumFrameDescriptors", "usbvideo.format.numFrameDescriptors",
2796                             FT_UINT8, BASE_DEC, NULL, 0,
2797                             "Number of frame descriptors for this format", HFILL }
2798             },
2799
2800             { &hf_usb_vid_format_guid,
2801                     { "guidFormat", "usbvideo.format.guid",
2802                             FT_GUID, BASE_NONE, NULL, 0,
2803                             "Stream encoding format", HFILL }
2804             },
2805
2806             { &hf_usb_vid_format_bits_per_pixel,
2807                     { "bBitsPerPixel", "usbvideo.format.bitsPerPixel",
2808                             FT_UINT8, BASE_DEC, NULL, 0,
2809                             "Bits per pixel", HFILL }
2810             },
2811
2812             { &hf_usb_vid_default_frame_index,
2813                     { "bDefaultFrameIndex", "usbvideo.format.defaultFrameIndex",
2814                             FT_UINT8, BASE_DEC, NULL, 0,
2815                             "Optimum frame index for this stream", HFILL }
2816             },
2817
2818             { &hf_usb_vid_aspect_ratio_x,
2819                     { "bAspectRatioX", "usbvideo.format.aspectRatioX",
2820                             FT_UINT8, BASE_DEC, NULL, 0,
2821                             "X dimension of picture aspect ratio", HFILL }
2822             },
2823
2824             { &hf_usb_vid_aspect_ratio_y,
2825                     { "bAspectRatioY", "usbvideo.format.aspectRatioY",
2826                             FT_UINT8, BASE_DEC, NULL, 0,
2827                             "Y dimension of picture aspect ratio", HFILL }
2828             },
2829
2830             { &hf_usb_vid_interlace_flags,
2831                     { "bmInterlaceFlags", "usbvideo.format.interlace",
2832                             FT_UINT8, BASE_HEX, NULL, 0x0,
2833                             NULL, HFILL }
2834             },
2835
2836             { &hf_usb_vid_is_interlaced,
2837                     { "Interlaced stream", "usbvideo.format.interlace.D0",
2838                             FT_BOOLEAN, 8, TFS(&is_interlaced_meaning), (1<<0),
2839                             NULL, HFILL }
2840             },
2841
2842             { &hf_usb_vid_interlaced_fields,
2843                     { "Fields per frame", "usbvideo.format.interlace.D1",
2844                             FT_BOOLEAN, 8, TFS(&interlaced_fields_meaning), (1<<1),
2845                             NULL, HFILL }
2846             },
2847
2848             { &hf_usb_vid_field_1_first,
2849                     { "Field 1 first", "usbvideo.format.interlace.D2",
2850                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<2),
2851                             NULL, HFILL }
2852             },
2853
2854             { &hf_usb_vid_field_pattern,
2855                     { "Field pattern", "usbvideo.format.interlace.pattern",
2856                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
2857                             &field_pattern_meaning_ext, (3<<4),
2858                             NULL, HFILL }
2859             },
2860
2861             { &hf_usb_vid_copy_protect,
2862                     { "bCopyProtect", "usbvideo.format.copyProtect",
2863                             FT_UINT8, BASE_DEC, VALS(copy_protect_meaning), 0,
2864                             NULL, HFILL }
2865             },
2866
2867             { &hf_usb_vid_variable_size,
2868                     { "Variable size", "usbvideo.format.variableSize",
2869                             FT_BOOLEAN, BASE_DEC, NULL, 0,
2870                             NULL, HFILL }
2871             },
2872
2873         /***** MJPEG Format Descriptor *****/
2874
2875             { &hf_usb_vid_mjpeg_flags,
2876                     { "bmFlags", "usbvideo.mjpeg.flags",
2877                             FT_UINT8, BASE_HEX, NULL, 0,
2878                             "Characteristics", HFILL }
2879             },
2880
2881             { &hf_usb_vid_mjpeg_fixed_samples,
2882                     { "Fixed size samples", "usbvideo.mjpeg.fixed_size",
2883                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<0),
2884                             NULL, HFILL }
2885             },
2886
2887         /***** Frame Descriptors *****/
2888
2889             { &hf_usb_vid_frame_index,
2890                     { "bFrameIndex", "usbvideo.frame.index",
2891                             FT_UINT8, BASE_DEC, NULL, 0,
2892                             "Index of this frame descriptor", HFILL }
2893             },
2894
2895             { &hf_usb_vid_frame_capabilities,
2896                     { "bmCapabilities", "usbvideo.frame.capabilities",
2897                             FT_UINT8, BASE_HEX, NULL, 0,
2898                             "Capabilities", HFILL }
2899             },
2900
2901             { &hf_usb_vid_frame_stills_supported,
2902                     { "Still image", "usbvideo.frame.stills",
2903                             FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), (1<<0),
2904                             NULL, HFILL }
2905             },
2906
2907             { &hf_usb_vid_frame_interval,
2908                     { "dwFrameInterval", "usbvideo.frame.interval",
2909                             FT_UINT32, BASE_DEC, NULL, 0,
2910                             "Frame interval multiple of 100 ns", HFILL }
2911             },
2912
2913             { &hf_usb_vid_frame_fixed_frame_rate,
2914                     { "Fixed frame rate", "usbvideo.frame.fixedRate",
2915                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<1),
2916                             NULL, HFILL }
2917             },
2918             { &hf_usb_vid_frame_width,
2919                     { "wWidth", "usbvideo.frame.width",
2920                             FT_UINT16, BASE_DEC, NULL, 0,
2921                             "Width of frame in pixels", HFILL }
2922             },
2923             { &hf_usb_vid_frame_height,
2924                     { "wHeight", "usbvideo.frame.height",
2925                             FT_UINT16, BASE_DEC, NULL, 0,
2926                             "Height of frame in pixels", HFILL }
2927             },
2928             { &hf_usb_vid_frame_min_bit_rate,
2929                     { "dwMinBitRate", "usbvideo.frame.minBitRate",
2930                             FT_UINT32, BASE_DEC, NULL, 0,
2931                             "Minimum bit rate in bps", HFILL }
2932             },
2933             { &hf_usb_vid_frame_max_bit_rate,
2934                     { "dwMaxBitRate", "usbvideo.frame.maxBitRate",
2935                             FT_UINT32, BASE_DEC, NULL, 0,
2936                             "Maximum bit rate in bps", HFILL }
2937             },
2938
2939             { &hf_usb_vid_frame_max_frame_sz,
2940                     { "dwMaxVideoFrameBufferSize", "usbvideo.frame.maxBuffer",
2941                             FT_UINT32, BASE_DEC, NULL, 0,
2942                             "Maximum bytes per frame", HFILL }
2943             },
2944             { &hf_usb_vid_frame_default_interval,
2945                     { "dwDefaultFrameInterval", "usbvideo.frame.interval.default",
2946                             FT_UINT32, BASE_DEC, NULL, 0,
2947                             "Suggested default", HFILL }
2948             },
2949
2950             { &hf_usb_vid_frame_interval_type,
2951                     { "bFrameIntervalType", "usbvideo.frame.interval.type",
2952                             FT_UINT8, BASE_DEC, NULL, 0,
2953                             "Frame rate control (continuous/discrete)", HFILL }
2954             },
2955
2956             { &hf_usb_vid_frame_min_interval,
2957                     { "dwMinFrameInterval", "usbvideo.frame.interval.min",
2958                             FT_UINT32, BASE_DEC, NULL, 0,
2959                             "Shortest frame interval (* 100 ns)", HFILL }
2960             },
2961
2962             { &hf_usb_vid_frame_max_interval,
2963                     { "dwMaxFrameInterval", "usbvideo.frame.interval.max",
2964                             FT_UINT32, BASE_DEC, NULL, 0,
2965                             "Longest frame interval (* 100 ns)", HFILL }
2966             },
2967             { &hf_usb_vid_frame_step_interval,
2968                     { "dwMinFrameInterval", "usbvideo.frame.interval.step",
2969                             FT_UINT32, BASE_DEC, NULL, 0,
2970                             "Granularity of frame interval (* 100 ns)", HFILL }
2971             },
2972
2973             { &hf_usb_vid_frame_bytes_per_line,
2974                     { "dwBytesPerLine", "usbvideo.frame.bytesPerLine",
2975                             FT_UINT32, BASE_DEC, NULL, 0,
2976                             "Fixed number of bytes per video line", HFILL }
2977             },
2978
2979         /***** Colorformat Descriptor *****/
2980
2981             { &hf_usb_vid_color_primaries,
2982                     { "bColorPrimaries", "usbvideo.color.primaries",
2983                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
2984                             &color_primaries_meaning_ext, 0,
2985                             NULL, HFILL }
2986             },
2987
2988             { &hf_usb_vid_transfer_characteristics,
2989                     { "bTransferCharacteristics", "usbvideo.color.transferCharacteristics",
2990                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
2991                             &color_transfer_characteristics_ext, 0,
2992                             NULL, HFILL }
2993             },
2994
2995             { &hf_usb_vid_matrix_coefficients,
2996                     { "bMatrixCoefficients", "usbvideo.color.matrixCoefficients",
2997                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
2998                             &matrix_coefficients_meaning_ext, 0,
2999                             NULL, HFILL }
3000             },
3001
3002         /***** Video Control Header Descriptor *****/
3003
3004             { &hf_usb_vid_control_ifdesc_bcdUVC,
3005                     { "bcdUVC", "usbvideo.bcdUVC",
3006                             FT_UINT16, BASE_HEX, NULL, 0,
3007                             "Video Device Class Specification release number", HFILL }
3008             },
3009
3010             { &hf_usb_vid_control_ifdesc_bInCollection,
3011                     { "bInCollection", "usbvideo.numStreamingInterfaces",
3012                             FT_UINT8, BASE_DEC, NULL, 0,
3013                             "Number of VideoStreaming interfaces", HFILL }
3014             },
3015
3016             { &hf_usb_vid_control_ifdesc_baInterfaceNr,
3017                     { "baInterfaceNr", "usbvideo.streamingInterfaceNumbers",
3018                             FT_BYTES, BASE_NONE, NULL, 0,
3019                             "Interface numbers of VideoStreaming interfaces", HFILL }},
3020
3021         /***** Video Streaming Input Header Descriptor *****/
3022
3023             { &hf_usb_vid_streaming_ifdesc_bNumFormats,
3024                     { "bNumFormats", "usbvideo.streaming.numFormats",
3025                             FT_UINT8, BASE_DEC, NULL, 0,
3026                             "Number of video payload format descriptors", HFILL }
3027             },
3028
3029             { &hf_usb_vid_streaming_bmInfo,
3030                     { "bmInfo", "usbvideo.streaming.info",
3031                             FT_UINT8, BASE_HEX, NULL, 0,
3032                             "Capabilities", HFILL }
3033             },
3034
3035             { &hf_usb_vid_streaming_info_D[0],
3036                     { "Dynamic Format Change", "usbvideo.streaming.info.D0",
3037                             FT_BOOLEAN, 8, TFS(&tfs_yes_no), (1<<0),
3038                             "Dynamic Format Change", HFILL }
3039             },
3040
3041             { &hf_usb_vid_streaming_control_D[0],
3042                     { "wKeyFrameRate", "usbvideo.streaming.control.D0",
3043                             FT_BOOLEAN, 6, TFS(&tfs_yes_no), (1<<0),
3044                             "Probe and Commit support", HFILL }
3045             },
3046
3047             { &hf_usb_vid_streaming_control_D[1],
3048                     { "wPFrameRate", "usbvideo.streaming.control.D1",
3049                             FT_BOOLEAN, 6, TFS(&tfs_yes_no), (1<<1),
3050                             "Probe and Commit support", HFILL }
3051             },
3052
3053             { &hf_usb_vid_streaming_control_D[2],
3054                     { "wCompQuality", "usbvideo.streaming.control.D2",
3055                             FT_BOOLEAN, 6, TFS(&tfs_yes_no), (1<<2),
3056                             "Probe and Commit support", HFILL }
3057             },
3058
3059             { &hf_usb_vid_streaming_control_D[3],
3060                     { "wCompWindowSize", "usbvideo.streaming.control.D3",
3061                             FT_BOOLEAN, 6, TFS(&tfs_yes_no), (1<<3),
3062                             "Probe and Commit support", HFILL }
3063             },
3064
3065             { &hf_usb_vid_streaming_control_D[4],
3066                     { "Generate Key Frame", "usbvideo.streaming.control.D4",
3067                             FT_BOOLEAN, 6, TFS(&tfs_yes_no), (1<<4),
3068                             "Probe and Commit support", HFILL }
3069             },
3070
3071             { &hf_usb_vid_streaming_control_D[5],
3072                     { "Update Frame Segment", "usbvideo.streaming.control.D5",
3073                             FT_BOOLEAN, 6, TFS(&tfs_yes_no), (1<<5),
3074                             "Probe and Commit support", HFILL }
3075             },
3076
3077             { &hf_usb_vid_streaming_terminal_link,
3078                     { "bTerminalLink", "usbvideo.streaming.terminalLink", FT_UINT8, BASE_DEC, NULL, 0x0,
3079                             "Output terminal ID", HFILL }
3080             },
3081
3082             { &hf_usb_vid_streaming_still_capture_method,
3083                     { "bStillCaptureMethod", "usbvideo.streaming.stillCaptureMethod",
3084                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
3085                             &vs_still_capture_methods_ext, 0,
3086                             "Method of Still Image Capture", HFILL }
3087             },
3088
3089             { &hf_usb_vid_streaming_trigger_support,
3090                     { "HW Triggering", "usbvideo.streaming.triggerSupport",
3091                             FT_BOOLEAN, BASE_DEC, TFS(&tfs_supported_not_supported), 0,
3092                             "Is HW triggering supported", HFILL }
3093             },
3094
3095             { &hf_usb_vid_streaming_trigger_usage,
3096                     { "bTriggerUsage", "usbvideo.streaming.triggerUsage",
3097                             FT_UINT8, BASE_DEC, VALS(vs_trigger_usage), 0,
3098                             "How host SW should respond to trigger", HFILL }
3099             },
3100
3101         /***** Interrupt URB *****/
3102
3103             { &hf_usb_vid_interrupt_bStatusType,
3104                     { "Status Type", "usbvideo.interrupt.statusType",
3105                             FT_UINT8, BASE_HEX, VALS(interrupt_status_types), 0xF,
3106                             NULL, HFILL }
3107             },
3108
3109             { &hf_usb_vid_interrupt_bAttribute,
3110                     { "Change Type", "usbvideo.interrupt.attribute",
3111                             FT_UINT8, BASE_HEX | BASE_EXT_STRING,
3112                             &control_change_types_ext, 0,
3113                             "Type of control change", HFILL }
3114             },
3115
3116             { &hf_usb_vid_interrupt_bOriginator,
3117                     { "Originator", "usbvideo.interrupt.originator",
3118                             FT_UINT8, BASE_DEC, NULL, 0,
3119                             "ID of the entity that reports this interrupt", HFILL }
3120             },
3121
3122             { &hf_usb_vid_control_interrupt_bEvent,
3123                     { "Event", "usbvideo.interrupt.controlEvent",
3124                             FT_UINT8, BASE_HEX, VALS(control_interrupt_events), 0,
3125                             "Type of event", HFILL }
3126             },
3127
3128         /***** Video Control Endpoint Descriptor *****/
3129
3130             { &hf_usb_vid_epdesc_subtype,
3131                     { "Subtype", "usbvideo.ep.descriptorSubType",
3132                             FT_UINT8, BASE_DEC, VALS(vc_ep_descriptor_subtypes), 0,
3133                             "Descriptor Subtype", HFILL }
3134             },
3135
3136             { &hf_usb_vid_epdesc_max_transfer_sz,
3137                     { "wMaxTransferSize", "usbvideo.ep.maxInterruptSize", FT_UINT16,
3138                       BASE_DEC, NULL, 0x0, "Max interrupt structure size", HFILL }
3139             },
3140
3141         /***** Fields used in multiple contexts *****/
3142
3143             { &hf_usb_vid_ifdesc_wTotalLength,
3144                     { "wTotalLength", "usbvideo.totalLength",
3145                             FT_UINT16, BASE_DEC, NULL, 0,
3146                             "Video interface descriptor size", HFILL }
3147             },
3148
3149             { &hf_usb_vid_bControlSize,
3150                     { "bControlSize", "usbvideo.bmcontrolSize",
3151                             FT_UINT8, BASE_DEC, NULL, 0,
3152                             "Size of bmControls field", HFILL }
3153             },
3154
3155             { &hf_usb_vid_bmControl,
3156                     { "bmControl", "usbvideo.availableControls",
3157                             FT_UINT32, BASE_HEX, NULL, 0,
3158                             "Available controls", HFILL }
3159             },
3160
3161             { &hf_usb_vid_bmControl_bytes,
3162                     { "bmControl", "usbvideo.availableControls.bytes",
3163                             FT_BYTES, BASE_NONE, NULL, 0,
3164                             "Available controls", HFILL }
3165             },
3166
3167             { &hf_usb_vid_control_ifdesc_src_id,
3168                     { "bSourceID", "usbvideo.sourceID", FT_UINT8, BASE_DEC, NULL, 0x0,
3169                             "Entity to which this terminal/unit is connected", HFILL }
3170             },
3171
3172         /**********/
3173
3174             { &hf_usb_vid_control_ifdesc_subtype,
3175                     { "Subtype", "usbvideo.control.descriptorSubType",
3176                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
3177                             &vc_if_descriptor_subtypes_ext, 0,
3178                             "Descriptor Subtype", HFILL }
3179             },
3180
3181             { &hf_usb_vid_streaming_ifdesc_subtype,
3182                     { "Subtype", "usbvideo.streaming.descriptorSubType",
3183                             FT_UINT8, BASE_DEC | BASE_EXT_STRING,
3184                             &vs_if_descriptor_subtypes_ext, 0,
3185                             "Descriptor Subtype", HFILL }
3186             },
3187
3188             { &hf_usb_vid_descriptor_data,
3189                     { "Descriptor data", "usbvideo.descriptor_data", FT_BYTES, BASE_NONE, NULL, 0x0,
3190                             NULL, HFILL }
3191             },
3192
3193             { &hf_usb_vid_control_data,
3194                     { "Control data", "usbvideo.control_data", FT_BYTES, BASE_NONE, NULL, 0x0,
3195                             NULL, HFILL }
3196             },
3197
3198             { &hf_usb_vid_control_value,
3199                     { "Control value", "usbvideo.control_value", FT_BYTES, BASE_NONE, NULL, 0x0,
3200                             NULL, HFILL }
3201             },
3202
3203             { &hf_usb_vid_value_data,
3204                     { "Value data", "usbvideo.value_data", FT_BYTES, BASE_NONE, NULL, 0x0,
3205                             NULL, HFILL }
3206             },
3207     };
3208
3209     static gint *usb_vid_subtrees[] = {
3210             &ett_usb_vid,
3211             &ett_descriptor_video_endpoint,
3212             &ett_descriptor_video_control,
3213             &ett_descriptor_video_streaming,
3214             &ett_camera_controls,
3215             &ett_processing_controls,
3216             &ett_streaming_controls,
3217             &ett_streaming_info,
3218             &ett_interlace_flags,
3219             &ett_frame_capability_flags,
3220             &ett_mjpeg_flags,
3221             &ett_video_probe,
3222             &ett_probe_hint,
3223             &ett_probe_framing,
3224             &ett_video_standards,
3225             &ett_control_capabilities
3226     };
3227
3228     static ei_register_info ei[] = {
3229         { &ei_usb_vid_subtype_unknown, { "usbvideo.subtype.unknown", PI_UNDECODED, PI_WARN, "Unknown VC subtype", EXPFILL }},
3230         { &ei_usb_vid_bitmask_len, { "usbvideo.bitmask_len_error", PI_UNDECODED, PI_WARN, "Only least-significant bytes decoded", EXPFILL }},
3231     };
3232
3233     expert_module_t* expert_usb_vid;
3234
3235     proto_usb_vid = proto_register_protocol("USB Video", "USBVIDEO", "usbvideo");
3236     proto_register_field_array(proto_usb_vid, hf, array_length(hf));
3237     proto_register_subtree_array(usb_vid_subtrees, array_length(usb_vid_subtrees));
3238     expert_usb_vid = expert_register_protocol(proto_usb_vid);
3239     expert_register_field_array(expert_usb_vid, ei, array_length(ei));
3240 }
3241
3242 void
3243 proto_reg_handoff_usb_vid(void)
3244 {
3245     dissector_handle_t usb_vid_control_handle;
3246     dissector_handle_t usb_vid_descriptor_handle;
3247     dissector_handle_t usb_vid_interrupt_handle;
3248
3249     usb_vid_control_handle = create_dissector_handle(dissect_usb_vid_control, proto_usb_vid);
3250     dissector_add_uint("usb.control", IF_CLASS_VIDEO, usb_vid_control_handle);
3251
3252     usb_vid_descriptor_handle = create_dissector_handle(dissect_usb_vid_descriptor, proto_usb_vid);
3253     dissector_add_uint("usb.descriptor", IF_CLASS_VIDEO, usb_vid_descriptor_handle);
3254
3255     usb_vid_interrupt_handle = create_dissector_handle(dissect_usb_vid_interrupt, proto_usb_vid);
3256     dissector_add_uint("usb.interrupt", IF_CLASS_VIDEO, usb_vid_interrupt_handle);
3257 }
3258 /*
3259  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3260  *
3261  * Local variables:
3262  * c-basic-offset: 4
3263  * tab-width: 8
3264  * indent-tabs-mode: nil
3265  * End:
3266  *
3267  * vi: set shiftwidth=4 tabstop=8 expandtab:
3268  * :indentSize=4:tabSize=8:noTabs=true:
3269  */