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