Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-mausb.c
blobe27658f8647a036aaac1a0bf2eaaa42ec3ed149f
1 /* packet-mausb.c
2 * Routines for Media Agnostic USB dissection
3 * Copyright 2014, Intel Corporation
4 * Author: Sean O. Stalley <sean.stalley@intel.com>
6 * Dedicated to Robert & Dorothy Stalley
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/oui.h>
20 #include "packet-tcp.h"
21 #include "packet-llc.h"
22 #include "packet-usb.h"
23 #include "packet-mausb.h"
25 void proto_reg_handoff_mausb(void);
26 void proto_register_mausb(void);
28 static dissector_handle_t mausb_tcp_handle;
29 static dissector_handle_t mausb_pkt_handle;
31 /* For SNAP Packets */
32 static int hf_llc_mausb_pid;
34 /* Initialize the protocol and registered fields */
35 static int proto_mausb;
36 static int hf_mausb_version;
37 static int hf_mausb_flags;
38 static int hf_mausb_flag_host;
39 static int hf_mausb_flag_retry;
40 static int hf_mausb_flag_timestamp;
41 static int hf_mausb_flag_reserved;
44 static int * const mausb_flag_fields[] = {
45 &hf_mausb_flag_host,
46 &hf_mausb_flag_retry,
47 &hf_mausb_flag_timestamp,
48 &hf_mausb_flag_reserved,
49 NULL
52 static int hf_mausb_type;
53 static int hf_mausb_length;
54 static int hf_mausb_dev_handle;
55 static int hf_mausb_ep_handle;
56 static int hf_mausb_ep_handle_d;
57 static int hf_mausb_ep_handle_ep_num;
58 static int hf_mausb_ep_handle_dev_addr;
59 static int hf_mausb_ep_handle_bus_num;
60 static int hf_mausb_ma_dev_addr;
61 static int hf_mausb_ssid;
62 static int hf_mausb_status;
64 /* management packet specific */
65 static int hf_mausb_token;
66 static int hf_mausb_mgmt_pad;
67 static int hf_mausb_mgmt_ep_handle_num;
68 static int hf_mausb_mgmt_ep_handle_pad;
69 static int hf_mausb_mgmt_ep_des_num;
70 static int hf_mausb_mgmt_ep_des_size;
71 static int hf_mausb_mgmt_ep_des_pad;
72 static int hf_mausb_mgmt_type_spec;
73 static int hf_mausb_mgmt_type_spec_generic;
75 /* CapResp packet specific */
76 static int hf_mausb_cap_resp_num_ep;
77 static int hf_mausb_cap_resp_num_dev;
78 static int hf_mausb_cap_resp_num_stream;
79 static int hf_mausb_cap_resp_dev_type;
80 static int hf_mausb_cap_resp_desc_count;
81 static int hf_mausb_cap_resp_desc_len;
82 static int hf_mausb_cap_resp_transfer_req;
83 static int hf_mausb_cap_resp_mgmt_req;
84 static int hf_mausb_cap_resp_rsvd;
86 static int hf_mausb_dev_cap_len;
87 static int hf_mausb_dev_cap_type;
88 static int hf_mausb_dev_cap_generic;
90 /* EPHandleReq & Resp packet specific */
91 static int hf_mausb_ep_handle_req_pad;
92 static int hf_mausb_ep_handle_resp_dir;
93 static int hf_mausb_ep_handle_resp_iso;
94 static int hf_mausb_ep_handle_resp_lman;
95 static int hf_mausb_ep_handle_resp_valid;
96 static int hf_mausb_ep_handle_resp_ccu;
97 static int hf_mausb_ep_handle_resp_buf_size;
98 static int hf_mausb_ep_handle_resp_iso_prog_dly;
99 static int hf_mausb_ep_handle_resp_iso_resp_dly;
101 /* (Clear/Cancel)TransferReq & Resp packet specific */
102 static int hf_mausb_clear_transfers_info_block;
103 static int hf_mausb_clear_transfers_status_block;
104 static int hf_mausb_cancel_transfer_rsvd;
105 static int hf_mausb_clear_transfers_req_num;
106 static int hf_mausb_clear_transfers_req_rsvd;
107 static int hf_mausb_clear_transfers_resp_num;
108 static int hf_mausb_clear_transfers_resp_rsvd;
109 static int hf_mausb_cancel_transfer_status;
110 static int hf_mausb_cancel_transfer_rsvd_2;
111 static int hf_mausb_clear_transfers_status;
112 static int hf_mausb_clear_transfers_partial;
113 static int hf_mausb_clear_transfers_start_req_id;
114 static int hf_mausb_clear_transfers_last_req_id;
115 static int hf_mausb_clear_transfers_req_block_rsvd;
116 static int hf_mausb_clear_transfers_resp_block_rsvd;
117 static int hf_mausb_cancel_transfer_seq_num;
118 static int hf_mausb_cancel_transfer_byte_offset;
120 /* data packet specific */
121 static int hf_mausb_eps;
122 static int hf_mausb_eps_rsvd;
123 static int hf_mausb_tflags;
124 static int hf_mausb_tflag_arq;
125 static int hf_mausb_tflag_neg;
126 static int hf_mausb_tflag_eot;
127 static int hf_mausb_tflag_type;
128 static int hf_mausb_tflag_rsvd;
130 static int * const mausb_tflag_fields[] = {
131 &hf_mausb_tflag_arq,
132 &hf_mausb_tflag_neg,
133 &hf_mausb_tflag_eot,
134 &hf_mausb_tflag_type,
135 &hf_mausb_tflag_rsvd,
136 NULL
139 static int hf_mausb_num_iso_hdr;
140 static int hf_mausb_iflags;
141 static int hf_mausb_iflag_mtd;
142 static int hf_mausb_iflag_hdr_format;
143 static int hf_mausb_iflag_asap;
145 static int * const mausb_iflag_fields[] = {
146 &hf_mausb_iflag_mtd,
147 &hf_mausb_iflag_hdr_format,
148 &hf_mausb_iflag_asap,
149 NULL
152 static int hf_mausb_stream_id;
153 static int hf_mausb_seq_num;
154 static int hf_mausb_req_id;
155 static int hf_mausb_present_time;
156 static int hf_mausb_uframe;
157 static int hf_mausb_frame;
158 static int hf_mausb_num_segs;
160 static int hf_mausb_timestamp;
161 static int hf_mausb_delta;
162 static int hf_mausb_nom_interval;
166 static int hf_mausb_mtd;
167 static int hf_mausb_rem_size_credit;
169 /* expert info fields */
170 static expert_field ei_ep_handle_len;
171 static expert_field ei_len;
172 static expert_field ei_mgmt_type_undef;
173 static expert_field ei_mgmt_type_spec_len_long;
174 static expert_field ei_mgmt_type_spec_len_short;
175 static expert_field ei_dev_cap_len;
176 static expert_field ei_dev_cap_resp_desc_len;
177 static expert_field ei_cap_resp_desc_len;
179 /* MAUSB Version, per 6.2.1.1 */
180 #define MAUSB_VERSION_1_0 0x0
181 #define MAUSB_VERSION_MASK 0x0F
183 /* for dissecting snap packets */
185 * TODO: determine assigned PID value
186 * (yet to be assigned as of Earth Day 2014)
188 #define PID_MAUSB 0x1500
190 static const value_string mausb_pid_string[] = {
191 { PID_MAUSB, "MAUSB" },
192 { 0, NULL}
195 static const value_string mausb_version_string[] = {
196 { MAUSB_VERSION_1_0, "MAUSB protocol version 1.0" },
197 { 0, NULL}
200 /* Packet flags, per 6.2.1.2 */
201 #define MAUSB_FLAG_MASK 0xF0
202 #define MAUSB_FLAG_HOST (1 << 0)
203 #define MAUSB_FLAG_RETRY (1 << 1)
204 #define MAUSB_FLAG_TIMESTAMP (1 << 2)
205 #define MAUSB_FLAG_RESERVED (1 << 3)
206 #define MAUSB_FLAG_OFFSET 4
208 /* Packet Types, per 6.2.1.3 */
209 #define MAUSB_PKT_TYPE_MASK 0xC0
210 #define MAUSB_PKT_TYPE_MGMT (0 << 6)
211 #define MAUSB_PKT_TYPE_CTRL (1 << 6)
212 #define MAUSB_PKT_TYPE_DATA (2 << 6)
214 /* Packet Subtypes, per 6.2.1.3 */
215 #define MAUSB_SUBTYPE_MASK 0x3F
217 enum mausb_pkt_type {
218 /* Management packets */
219 CapReq = 0x00 | MAUSB_PKT_TYPE_MGMT,
220 CapResp ,
221 USBDevHandleReq ,
222 USBDevHandleResp ,
223 EPHandleReq ,
224 EPHandleResp ,
225 EPActivateReq ,
226 EPActivateResp ,
227 EPInactivateReq ,
228 EPInactivateResp ,
229 EPResetReq ,
230 EPResetResp ,
231 ClearTransfersReq ,
232 ClearTransfersResp ,
233 EPHandleDeleteReq ,
234 EPHandleDeleteResp ,
236 DevResetReq ,
237 DevResetResp ,
238 ModifyEP0Req ,
239 ModifyEP0Resp ,
240 SetUSBDevAddrReq ,
241 SetUSBDevAddrResp ,
242 UpdateDevReq ,
243 UpdateDevResp ,
244 USBDevDisconnectReq ,
245 USBDevDisconnectResp ,
246 USBSuspendReq ,
247 USBSuspendResp ,
248 USBResumeReq ,
249 USBResumeResp ,
250 RemoteWakeReq ,
251 RemoteWakeResp ,
253 PingReq ,
254 PingResp ,
255 DevDisconnectReq ,
256 DevDisconnectResp ,
257 DevInitDisconnectReq ,
258 DevInitDisconnectResp ,
259 SynchReq ,
260 SynchResp ,
261 CancelTransferReq ,
262 CancelTransferResp ,
263 EPOpenStreamReq ,
264 EPOpenStreamResp ,
265 EPCloseStreamReq ,
266 EPCloseStreamResp ,
267 USBDevResetReq ,
268 USBDevResetResp ,
270 DevNotificationReq ,
271 DevNotificationResp ,
272 EPSetKeepAliveReq ,
273 EPSetKeepAliveResp ,
274 GetPortBWReq ,
275 GetPortBWResp ,
276 SleepReq ,
277 SleepResp ,
278 WakeReq ,
279 WakeResp ,
281 /* Vendor-Specific Management Packets */
282 VendorSpecificReq = 0x3E | MAUSB_PKT_TYPE_MGMT,
283 VendorSpecificResp ,
285 /* Control Packets */
286 TransferSetupReq = 0x00 | MAUSB_PKT_TYPE_CTRL,
287 TransferSetupResp ,
288 TransferTearDownConf ,
290 /* Data Packets */
291 TransferReq = 0x00 | MAUSB_PKT_TYPE_DATA,
292 TransferResp ,
293 TransferAck ,
294 IsochTransferReq ,
295 IsochTransferResp
300 * Type & Subtype values for MAUSB packet variants, per 6.2.1.3, Table 5
302 static const value_string mausb_type_string[] = {
303 /* Management packets */
304 { CapReq , "CapReq" },
305 { CapResp , "CapResp" },
306 { USBDevHandleReq , "USBDevHandleReq" },
307 { USBDevHandleResp , "USBDevHandleResp" },
308 { EPHandleReq , "EPHandleReq" },
309 { EPHandleResp , "EPHandleResp" },
310 { EPActivateReq , "EPActivateReq" },
311 { EPActivateResp , "EPActivateResp" },
312 { EPInactivateReq , "EPInactivateReq" },
313 { EPInactivateResp , "EPInactivateResp" },
314 { EPResetReq , "EPResetReq" },
315 { EPResetResp , "EPResetResp" },
316 { ClearTransfersReq , "ClearTransfersReq" },
317 { ClearTransfersResp , "ClearTransfersResp" },
318 { EPHandleDeleteReq , "EPHandleDeleteReq" },
319 { EPHandleDeleteResp , "EPHandleDeleteResp" },
321 { DevResetReq , "DevResetReq" },
322 { DevResetResp , "DevResetResp" },
323 { ModifyEP0Req , "ModifyEP0Req" },
324 { ModifyEP0Resp , "ModifyEP0Resp" },
325 { SetUSBDevAddrReq , "SetUSBDevAddrReq" },
326 { SetUSBDevAddrResp , "SetUSBDevAddrResp" },
327 { UpdateDevReq , "UpdateDevReq" },
328 { UpdateDevResp , "UpdateDevResp" },
329 { USBDevDisconnectReq , "USBDevDisconnectReq" },
330 { USBDevDisconnectResp , "USBDevDisconnectResp" },
331 { USBSuspendReq , "USBSuspendReq" },
332 { USBSuspendResp , "USBSuspendResp" },
333 { USBResumeReq , "USBResumeReq" },
334 { USBResumeResp , "USBResumeResp" },
335 { RemoteWakeReq , "RemoteWakeReq" },
336 { RemoteWakeResp , "RemoteWakeResp" },
338 { PingReq , "PingReq" },
339 { PingResp , "PingResp" },
340 { DevDisconnectReq , "DevDisconnectReq " },
341 { DevDisconnectResp , "DevDisconnectResp" },
342 { DevInitDisconnectReq , "DevInitDisconnectReq" },
343 { DevInitDisconnectResp, "DevInitDisconnectResp" },
344 { SynchReq , "SynchReq" },
345 { SynchResp , "SynchResp" },
346 { CancelTransferReq , "CancelTransferReq" },
347 { CancelTransferResp , "CancelTransferResp" },
348 { EPOpenStreamReq , "EPOpenStreamReq" },
349 { EPOpenStreamResp , "EPOpenStreamResp" },
350 { EPCloseStreamReq , "EPCloseStreamReq" },
351 { EPCloseStreamResp , "EPCloseStreamResp" },
352 { USBDevResetReq , "USBDevResetReq" },
353 { USBDevResetResp , "USBDevResetResp" },
355 { DevNotificationReq , "DevNotificationReq" },
356 { DevNotificationResp , "DevNotificationResp" },
357 { EPSetKeepAliveReq , "EPSetKeepAliveReq" },
358 { EPSetKeepAliveResp , "EPSetKeepAliveResp" },
359 { GetPortBWReq , "GetPortBWReq" },
360 { GetPortBWResp , "GetPortBWResp" },
361 { SleepReq , "SleepReq" },
362 { SleepResp , "SleepResp" },
363 { WakeReq , "WakeReq" },
364 { WakeResp , "WakeResp" },
366 /* Vendor-Specific Management Packets */
367 { VendorSpecificReq , "VendorSpecificReq" },
368 { VendorSpecificResp , "VendorSpecificResp" },
370 /* Control Packets */
371 { TransferSetupReq , "TransferSetupReq" },
372 { TransferSetupResp , "TransferSetupResp" },
373 { TransferTearDownConf , "TransferTearDownConf" },
375 /* Data Packets */
376 { TransferReq , "TransferReq" },
377 { TransferResp , "TransferResp" },
378 { TransferAck , "TransferAck" },
379 { IsochTransferReq , "IsochTransferReq" },
380 { IsochTransferResp , "IsochTransferResp" },
381 { 0, NULL}
384 #define MAUSB_EP_HANDLE_D 0x0001
385 #define MAUSB_EP_HANDLE_EP_NUM 0x001e
386 #define MAUSB_EP_HANDLE_DEV_ADDR 0x0fe0
387 #define MAUSB_EP_HANDLE_BUS_NUM 0xf000
389 #define MAUSB_EP_HANDLE_D_OFFSET 0
390 #define MAUSB_EP_HANDLE_EP_NUM_OFFSET 1
391 #define MAUSB_EP_HANDLE_DEV_ADDR_OFFSET 5
392 #define MAUSB_EP_HANDLE_BUS_NUM_OFFSET 12
394 static const value_string mausb_status_string[] = {
395 { 0, "SUCCESS (NO_ERROR)" },
396 { 128, "UNSUCCESSFUL" },
397 { 129, "INVALID_MA_USB_SESSION_STATE" },
398 { 130, "INVALID_DEVICE_HANDLE" },
399 { 131, "INVALID_EP_HANDLE" },
400 { 132, "INVALID_EP_HANDLE_STATE" },
401 { 133, "INVALID_REQUEST" },
402 { 134, "MISSING_SEQUENCE_NUMBER" },
403 { 135, "TRANSFER_PENDING" },
404 { 136, "TRANSFER_EP_STALL" },
405 { 137, "TRANSFER_SIZE_ERROR" },
406 { 138, "TRANSFER_DATA_BUFFER_ERROR" },
407 { 139, "TRANSFER_BABBLE_DETECTED" },
408 { 140, "TRANSFER_TRANSACTION_ERROR" },
409 { 141, "TRANSFER_SHORT_TRANSFER" },
410 { 142, "TRANSFER_CANCELLED" },
411 { 143, "INSUFFICIENT_RESOURCES" },
412 { 144, "NOT_SUFFICIENT_BANDWIDTH" },
413 { 145, "INTERNAL_ERROR" },
414 { 146, "DATA_OVERRUN" },
415 { 147, "DEVICE_NOT_ACCESSED" },
416 { 148, "BUFFER_OVERRUN" },
417 { 149, "BUSY" },
418 { 150, "DROPPED_PACKET" },
419 { 151, "ISOC_TIME_EXPIRED" },
420 { 152, "ISOCH_TIME_INVALID" },
421 { 153, "NO_USB_PING_RESPONSE" },
422 { 154, "NOT_SUPPORTED" },
423 { 155, "REQUEST_DENIED" },
424 { 156, "MISSING_REQUEST_ID" },
425 { 0, NULL}
429 /* Number of Isochronous Headers, per 6.5.1.7 */
430 #define MAUSB_NUM_ISO_HDR_MASK 0x0fff
432 /* I-Flags, per 6.5.1.8 */
433 #define MAUSB_IFLAG_ASAP (1 << 0)
434 #define MAUSB_IFLAG_HDR_FORMAT (3 << 1)
435 #define MAUSB_IFLAG_MTD (1 << 3)
436 #define MAUSB_IFLAG_OFFSET 12
437 #define MAUSB_IFLAG_MASK (0xF << MAUSB_IFLAG_OFFSET)
439 /* Presentation Time, per 6.5.1.9 */
440 #define MAUSB_PRESENT_TIME_MASK 0x000fffff
441 #define MAUSB_UFRAME_MASK 0x00000007
442 #define MAUSB_FRAME_MASK 0x000ffff8
444 /* Number of Segments, per 6.5.1.10 */
445 #define MAUSB_NUM_SEGS_MASK 0xfff00000
447 /* MA USB Global Time fields, per 6.6.1 */
448 #define MAUSB_DELTA_MASK 0x00000fff
449 #define MAUSB_INTERVAL_MASK 0xfffff000
453 #define MAUSB_TOKEN_MASK 0x03ff
454 #define MAUSB_MGMT_PAD_MASK 0xfffc
455 #define MAUSB_MGMT_NUM_EP_DES_MASK 0x1f
456 #define MAUSB_MGMT_SIZE_EP_DES_OFFSET 5
457 #define MAUSB_MGMT_SIZE_EP_DES_MASK (0x003f << MAUSB_MGMT_SIZE_EP_DES_OFFSET)
459 #define MAUSB_MGMT_CLEAR_TRANSFER_RESP_NUM_MASK 0x1f
461 /* CapResp Bitfield Masks */
462 #define MAUSB_CAP_RESP_NUM_STREAM_MASK 0x1f
463 #define MAUSB_CAP_RESP_DEV_TYPE_OFFSET 5
464 #define MAUSB_CAP_RESP_DEV_TYPE_MASK (0x07 << MAUSB_CAP_RESP_DEV_TYPE_OFFSET)
465 #define MAUSB_CAP_RESP_MGMT_REQ_MASK 0x0fff
466 #define MAUSB_CAP_RESP_RSVD_MASK 0xf000
468 static const value_string mausb_cap_resp_dev_type[] = {
469 { 0, "Integrated Device" },
470 { 1, "MAUSB 2.0 hub" },
471 { 2, "MAUSB 3.1 hub" },
472 { 0, NULL}
475 static const value_string mausb_dev_cap_string[] = {
476 { 0, "Speed Capability" },
477 { 1, "P-managed OUT Capabilities" },
478 { 2, "Isochronous Capabilities" },
479 { 3, "Synchronization Capabilities" },
480 { 4, "Container ID Capability" },
481 { 5, "Link Sleep Capability" },
482 { 0, NULL}
485 enum mausb_dev_cap_type {
486 SpeedCap = 0,
487 PmanCap,
488 IsoCap,
489 SyncCap,
490 ContainerIDCap,
491 LinkSleepCap
494 #define DWORD_MASK 0xffffffff
495 #define MAUSB_MGMT_NUM_EP_HANDLE_PAD_MASK \
496 (DWORD_MASK & !(MAUSB_MGMT_NUM_EP_DES_MASK))
497 #define MAUSB_MGMT_EP_DES_PAD_MASK \
498 ((DWORD_MASK & !(MAUSB_MGMT_NUM_EP_DES_MASK | \
499 MAUSB_MGMT_SIZE_EP_DES_MASK)) >> 8)
502 /* EPHandleResp Bitfield Masks */
503 #define MAUSB_EP_HANDLE_RESP_DIR_MASK (1 << 0)
504 #define MAUSB_EP_HANDLE_RESP_ISO_MASK (1 << 1)
505 #define MAUSB_EP_HANDLE_RESP_LMAN_MASK (1 << 2)
506 #define MAUSB_EP_HANDLE_RESP_VALID_MASK (1 << 3)
508 static const value_string mausb_eps_string[] = {
509 { 0, "Unassigned" },
510 { 1, "Active" },
511 { 2, "Inactive" },
512 { 3, "Halted" },
513 { 0, NULL}
516 #define MAUSB_EPS_MASK 0x03
518 #define MAUSB_TFLAG_MASK 0xfc
520 #define MAUSB_TX_TYPE_CTRL (0 << 3)
521 #define MAUSB_TX_TYPE_ISOC (1 << 3)
522 #define MAUSB_TX_TYPE_BULK (2 << 3)
523 #define MAUSB_TX_TYPE_INTR (3 << 3)
525 #define MAUSB_TFLAG_OFFSET 2
526 #define MAUSB_TFLAG_ARQ (1 << 0)
527 #define MAUSB_TFLAG_NEG (1 << 1)
528 #define MAUSB_TFLAG_EOT (1 << 2)
529 #define MAUSB_TFLAG_TRANSFER_TYPE (3 << 3)
530 #define MAUSB_TFLAG_RSVD (1 << 5)
532 static const value_string mausb_transfer_type_string[] = {
533 { 0, "Control" },
534 { 1, "Isochronous" },
535 { 2, "Bulk" },
536 { 3, "Interrupt" },
537 { 0, NULL}
540 static const true_false_string tfs_ep_handle_resp_dir = { "IN", "OUT or Control" };
542 #define MAUSB_TRANSFER_TYPE_OFFSET 3 /* Offset from start of TFlags Field */
543 /* (EPS not included) */
544 #define MAUSB_TRANSFER_TYPE_CTRL (0 << MAUSB_TRANSFER_TYPE_OFFSET)
545 #define MAUSB_TRANSFER_TYPE_ISO (1 << MAUSB_TRANSFER_TYPE_OFFSET)
546 #define MAUSB_TRANSFER_TYPE_BULK (2 << MAUSB_TRANSFER_TYPE_OFFSET)
547 #define MAUSB_TRANSFER_TYPE_INTERRUPT (3 << MAUSB_TRANSFER_TYPE_OFFSET)
549 static const value_string mausb_cancel_transfer_status_string[] = {
550 { 0, "Cancel Unsuccessful"},
551 { 1, "Canceled before any data was moved"},
552 { 2, "Canceled after some data was moved"},
553 { 3, "Transfer completed"},
554 { 4, "Transfer not yet received"},
555 { 5, "Transfer cleared without any data moved"},
556 { 0, NULL}
559 #define MAUSB_CANCEL_TRANSFER_STATUS_MASK 0x07
561 #define MAUSB_CLEAR_TRANSFERS_RESP_NUM_MASK 0x1f
562 #define MAUSB_CLEAR_TRANSFERS_STATUS_MASK 0x01
563 #define MAUSB_CLEAR_TRANSFERS_PARTIAL_MASK 0x02
564 #define MAUSB_CLEAR_TRANSFERS_RESP_BLOCK_RSVD_MASK 0xfffffffc
567 /* We need at least the first DWORD to determine the packet length (for TCP) */
568 #define MAUSB_MIN_LENGTH 4
570 #define MAUSB_MIN_MGMT_LENGTH 12
571 #define MAUSB_MIN_DATA_LENGTH 20
572 #define MAUSB_COMMON_LEN 9
575 /*** Packet parsing helper functions ***/
577 bool mausb_is_from_host(struct mausb_header *header)
579 return (MAUSB_FLAG_HOST << MAUSB_FLAG_OFFSET) & header->ver_flags;
582 static bool mausb_is_mgmt_pkt(struct mausb_header *header)
584 return MAUSB_PKT_TYPE_MGMT == (header->type & MAUSB_PKT_TYPE_MASK);
587 static bool mausb_is_data_pkt(struct mausb_header *header)
589 return MAUSB_PKT_TYPE_DATA == (header->type & MAUSB_PKT_TYPE_MASK);
592 static bool mausb_is_transfer_req(struct mausb_header *header)
594 return TransferReq == header->type;
597 static bool mausb_is_transfer_ack(struct mausb_header *header)
599 return TransferAck == header->type;
602 static int8_t mausb_tx_type(struct mausb_header *header)
604 return (header->u.s.eps_tflags >> MAUSB_TFLAG_OFFSET) & MAUSB_TFLAG_TRANSFER_TYPE;
607 static bool mausb_is_iso_pkt(struct mausb_header *header)
609 return MAUSB_TX_TYPE_ISOC == mausb_tx_type(header);
612 static bool mausb_has_timestamp(struct mausb_header *header)
614 return (MAUSB_FLAG_TIMESTAMP << MAUSB_FLAG_OFFSET) & header->ver_flags;
617 static bool mausb_has_mtd(struct mausb_header *header)
619 return (MAUSB_IFLAG_MTD << MAUSB_IFLAG_OFFSET) & header->u.s.u1.num_headers_iflags;
622 static bool mausb_has_setup_data(struct mausb_header *header)
624 if ((TransferReq == header->type ) &&
625 (mausb_is_from_host(header)) &&
626 (0 == header->u.s.seq_num) &&
627 (MAUSB_TX_TYPE_CTRL == mausb_tx_type(header))) {
629 return true;
631 return false;
634 static bool mausb_is_setup_response(struct mausb_header *header)
636 if ((TransferResp == header->type) &&
637 (!mausb_is_from_host(header)) &&
638 (MAUSB_TX_TYPE_CTRL == mausb_tx_type(header))) {
640 return true;
642 return false;
645 /*** EP Handle parsing helper functions */
647 uint8_t mausb_ep_handle_ep_d(uint16_t handle) {
648 return (handle & MAUSB_EP_HANDLE_D) >> MAUSB_EP_HANDLE_D_OFFSET;
651 uint8_t mausb_ep_handle_ep_num(uint16_t handle) {
652 return (handle & MAUSB_EP_HANDLE_EP_NUM) >> MAUSB_EP_HANDLE_EP_NUM_OFFSET;
655 uint8_t mausb_ep_handle_dev_addr(uint16_t handle) {
656 return (handle & MAUSB_EP_HANDLE_DEV_ADDR) >> MAUSB_EP_HANDLE_DEV_ADDR_OFFSET;
659 uint8_t mausb_ep_handle_bus_num(uint16_t handle) {
660 return (handle & MAUSB_EP_HANDLE_BUS_NUM) >> MAUSB_EP_HANDLE_BUS_NUM_OFFSET;
663 /* returns the length field of the MAUSB packet */
664 static unsigned mausb_get_pkt_len(packet_info *pinfo _U_, tvbuff_t *tvb,
665 int offset, void *data _U_)
667 return tvb_get_letohs(tvb, offset + 2);
670 /* Initialize the subtree pointers */
671 static int ett_mausb;
672 static int ett_mausb_flags;
673 static int ett_mausb_ep_handle;
674 static int ett_mausb_tflags;
675 static int ett_mausb_iflags;
676 static int ett_mausb_present_time;
677 static int ett_mausb_timestamp;
678 static int ett_mgmt;
679 static int ett_dev_cap;
680 static int ett_clear_transfers_block;
683 #define USB_DT_EP_SIZE 7
684 #define USB_DT_SS_EP_COMP_SIZE 6
685 #define USB_DT_ISO_SSP_EP_COMP_SIZE 8
687 /* Size of EPHandleReq Descriptors */
688 #define MAUSB_EP_DES_SIZE 8
689 #define MAUSB_SS_EP_DES_SIZE 16
690 #define MAUSB_ISO_SSP_EP_DES_SIZE 24
692 /* EPHandleReq Descriptor Padding */
693 #define MAUSB_EP_DES_PAD (MAUSB_EP_DES_SIZE - USB_DT_EP_SIZE)
695 #define MAUSB_SS_EP_DES_PAD (MAUSB_SS_EP_DES_SIZE - \
696 (USB_DT_EP_SIZE + USB_DT_SS_EP_COMP_SIZE))
698 #define MAUSB_ISO_SSP_EP_DES_PAD (MAUSB_ISO_SSP_EP_DES_SIZE - \
699 (USB_DT_EP_SIZE + USB_DT_SS_EP_COMP_SIZE + USB_DT_ISO_SSP_EP_COMP_SIZE))
702 /* Size of EPHandleResp Descriptor */
703 #define MAUSB_SIZE_MAUSB_EP_DES 16
706 /* Size of EPHandleResp Descriptor */
707 #define MAUSB_SIZE_EP_HANDLE 2
710 /* Dissects an individual Device Capability Descriptor */
711 static uint16_t dissect_mausb_dev_cap_desc(proto_tree *tree, tvbuff_t *tvb,
712 packet_info *pinfo, int16_t offset)
714 uint8_t desc_len;
715 uint8_t cap_type;
716 int16_t desc_offset;
717 proto_item *len_field;
718 proto_tree *dev_cap_tree;
720 desc_offset = offset;
721 desc_len = tvb_get_uint8(tvb, desc_offset);
722 cap_type = tvb_get_uint8(tvb, desc_offset + 1);
724 dev_cap_tree = proto_tree_add_subtree(tree, tvb, desc_offset, desc_len,
725 ett_dev_cap, NULL,
726 val_to_str_const(cap_type, mausb_dev_cap_string, "Unknown Capability"));
728 len_field = proto_tree_add_item(dev_cap_tree, hf_mausb_dev_cap_len,
729 tvb, desc_offset, 1, ENC_LITTLE_ENDIAN);
730 desc_offset += 1;
732 proto_tree_add_item(dev_cap_tree, hf_mausb_dev_cap_type,
733 tvb, desc_offset, 1, ENC_LITTLE_ENDIAN);
734 desc_offset += 1;
736 if (desc_len > 2) {
738 /* TODO: dissect individual capabilities */
739 switch (cap_type) {
740 case SpeedCap:
741 case PmanCap:
742 case IsoCap:
743 case SyncCap:
744 case ContainerIDCap:
745 case LinkSleepCap:
746 default:
747 proto_tree_add_item(dev_cap_tree, hf_mausb_dev_cap_generic,
748 tvb, desc_offset, (desc_len - 2), ENC_NA);
749 desc_offset += (desc_len - 2);
751 break;
755 /* Was this descriptor a different length than expected */
756 if (desc_offset != offset + desc_len) {
757 expert_add_info(pinfo, len_field, &ei_dev_cap_len);
760 return offset + desc_len;
764 /* Dissects a MAUSB capability response packet
765 * also dissects Capability Descriptors
767 static uint16_t dissect_mausb_mgmt_pkt_cap_resp(struct mausb_header *header,
768 proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int16_t offset)
771 unsigned desc_len;
772 uint8_t desc_count;
773 proto_item *len_field;
774 uint16_t loop_offset;
775 int i;
777 /* Fields present in all CapResp packets */
778 proto_tree_add_item(tree, hf_mausb_cap_resp_num_ep,
779 tvb, offset, 2, ENC_LITTLE_ENDIAN);
780 offset += 2;
782 proto_tree_add_item(tree, hf_mausb_cap_resp_num_dev,
783 tvb, offset, 1, ENC_LITTLE_ENDIAN);
784 offset += 1;
786 proto_tree_add_item(tree, hf_mausb_cap_resp_num_stream,
787 tvb, offset, 1, ENC_LITTLE_ENDIAN); /* really 5 bits */
788 proto_tree_add_item(tree, hf_mausb_cap_resp_dev_type,
789 tvb, offset, 1, ENC_LITTLE_ENDIAN); /* really 3 bits */
790 offset += 1;
792 proto_tree_add_item(tree, hf_mausb_cap_resp_desc_count,
793 tvb, offset, 1, ENC_LITTLE_ENDIAN);
794 desc_count = tvb_get_uint8(tvb, offset);
795 offset += 1;
797 len_field = proto_tree_add_item(tree, hf_mausb_cap_resp_desc_len,
798 tvb, offset, 3, ENC_LITTLE_ENDIAN);
799 desc_len = tvb_get_letoh24(tvb, offset);
800 offset += 3;
802 proto_tree_add_item(tree, hf_mausb_cap_resp_transfer_req,
803 tvb, offset, 2, ENC_LITTLE_ENDIAN);
804 offset += 2;
806 proto_tree_add_item(tree, hf_mausb_cap_resp_mgmt_req,
807 tvb, offset, 2, ENC_LITTLE_ENDIAN); /* really 12 bits */
808 proto_tree_add_item(tree, hf_mausb_cap_resp_rsvd,
809 tvb, offset, 2, ENC_LITTLE_ENDIAN); /* really 4 bits */
810 offset += 2;
812 /* Descriptors length longer than remainder of packet */
813 if (offset + desc_len > header->length) {
814 expert_add_info(pinfo, len_field, &ei_cap_resp_desc_len);
815 desc_len = header->length - offset; /* to avoid overflows */
818 loop_offset = offset;
820 /* dissect capability descriptors */
821 for (i = 0; i < desc_count; i++) {
822 loop_offset = dissect_mausb_dev_cap_desc(tree, tvb, pinfo, loop_offset);
825 /* were the descriptors a different length than expected */
826 if (loop_offset != offset + desc_len) {
827 expert_add_info(pinfo, len_field, &ei_dev_cap_resp_desc_len);
828 desc_len = header->length - offset; /* to avoid overflows */
831 return offset + desc_len;
834 /* Dissects a MAUSB endpoint handle */
835 static int dissect_ep_handle(proto_tree *tree, tvbuff_t *tvb, int offset)
838 proto_item *ti;
839 proto_tree *ep_handle_tree;
841 ti = proto_tree_add_item(tree, hf_mausb_ep_handle, tvb,
842 offset, MAUSB_SIZE_EP_HANDLE, ENC_LITTLE_ENDIAN);
844 ep_handle_tree = proto_item_add_subtree(ti, ett_mausb_ep_handle);
845 proto_tree_add_item(ep_handle_tree, hf_mausb_ep_handle_d, tvb,
846 offset, MAUSB_SIZE_EP_HANDLE, ENC_LITTLE_ENDIAN);
847 proto_tree_add_item(ep_handle_tree, hf_mausb_ep_handle_ep_num, tvb,
848 offset, MAUSB_SIZE_EP_HANDLE, ENC_LITTLE_ENDIAN);
849 proto_tree_add_item(ep_handle_tree, hf_mausb_ep_handle_dev_addr, tvb,
850 offset, MAUSB_SIZE_EP_HANDLE, ENC_LITTLE_ENDIAN);
851 proto_tree_add_item(ep_handle_tree, hf_mausb_ep_handle_bus_num, tvb,
852 offset, MAUSB_SIZE_EP_HANDLE, ENC_LITTLE_ENDIAN);
854 return MAUSB_SIZE_EP_HANDLE;
858 /* dissects presentation time & subfields */
859 static void dissect_mausb_present_time(proto_tree *tree, tvbuff_t *tvb,
860 int offset)
862 proto_item *ti;
863 proto_tree *present_time_tree;
865 ti = proto_tree_add_item(tree, hf_mausb_present_time, tvb,
866 offset, 4, ENC_LITTLE_ENDIAN);
868 present_time_tree = proto_item_add_subtree(ti, ett_mausb_present_time);
869 proto_tree_add_item(present_time_tree, hf_mausb_uframe, tvb,
870 offset, 4, ENC_LITTLE_ENDIAN);
871 proto_tree_add_item(present_time_tree, hf_mausb_frame, tvb,
872 offset, 4, ENC_LITTLE_ENDIAN);
876 static void dissect_mausb_timestamp(proto_tree *tree, tvbuff_t *tvb,
877 int offset)
879 proto_item *ti;
880 proto_tree *timestamp_tree;
882 ti = proto_tree_add_item(tree, hf_mausb_timestamp, tvb,
883 offset, 4, ENC_LITTLE_ENDIAN);
885 timestamp_tree = proto_item_add_subtree(ti, ett_mausb_timestamp);
886 proto_tree_add_item(timestamp_tree, hf_mausb_delta, tvb,
887 offset, 4, ENC_LITTLE_ENDIAN);
888 proto_tree_add_item(timestamp_tree, hf_mausb_nom_interval, tvb,
889 offset, 4, ENC_LITTLE_ENDIAN);
893 /* gets the size of the endpoint descriptors in a EPHandleReq packet */
894 static uint8_t mausb_get_size_ep_des(tvbuff_t *tvb, int offset)
896 uint8_t size_ep_des = 0;
897 uint16_t temp_buffer = 0; /* for storing the offset data */
899 /* grab the 2 bytes with the size field */
900 temp_buffer = tvb_get_letohs(tvb, offset);
902 /* mask & shift the size field */
903 temp_buffer = temp_buffer & MAUSB_MGMT_SIZE_EP_DES_MASK;
904 size_ep_des = (temp_buffer >> MAUSB_MGMT_SIZE_EP_DES_OFFSET);
906 return size_ep_des;
909 /* dissect an individual block for ClearTransfers */
910 static uint16_t dissect_clear_transfers_block(proto_tree *tree,
911 tvbuff_t *tvb, int16_t offset, bool req)
913 proto_item *ti;
914 proto_tree *block_tree;
916 if (req) {
917 ti = proto_tree_add_item(tree, hf_mausb_clear_transfers_info_block,
918 tvb, offset, 8, ENC_NA);
919 } else {
920 ti = proto_tree_add_item(tree, hf_mausb_clear_transfers_status_block,
921 tvb, offset, 16, ENC_NA);
924 block_tree = proto_item_add_subtree(ti, ett_clear_transfers_block);
927 /* EP Handle */
928 offset += dissect_ep_handle(block_tree, tvb, offset);
930 /* Stream ID */
931 proto_tree_add_item(block_tree, hf_mausb_stream_id, tvb, offset, 2,
932 ENC_LITTLE_ENDIAN);
933 offset += 2;
935 if (req) {
936 /* Start Request ID */
937 proto_tree_add_item(block_tree, hf_mausb_clear_transfers_start_req_id,
938 tvb, offset, 1, ENC_LITTLE_ENDIAN);
939 offset += 1;
941 /* Rsvd */
942 proto_tree_add_item(block_tree, hf_mausb_clear_transfers_req_block_rsvd,
943 tvb, offset, 3, ENC_NA);
944 offset += 3;
946 } else {
947 /* Cancel Status */
948 proto_tree_add_item(block_tree, hf_mausb_clear_transfers_status,
949 tvb, offset, 4, ENC_LITTLE_ENDIAN);
950 /* Partial Delivery */
951 proto_tree_add_item(block_tree, hf_mausb_clear_transfers_partial,
952 tvb, offset, 4, ENC_LITTLE_ENDIAN);
953 /* Rsvd */
954 proto_tree_add_item(block_tree, hf_mausb_clear_transfers_resp_block_rsvd,
955 tvb, offset, 4, ENC_LITTLE_ENDIAN);
956 offset += 4;
958 /* Last Request ID */
959 proto_tree_add_item(block_tree, hf_mausb_clear_transfers_last_req_id,
960 tvb, offset, 1, ENC_LITTLE_ENDIAN);
961 offset += 1;
963 /* Delivered Sequence Number */
964 proto_tree_add_item(block_tree, hf_mausb_cancel_transfer_seq_num, tvb,
965 offset, 3, ENC_LITTLE_ENDIAN);
966 offset += 3;
967 /* Delivered Byte Offset */
968 proto_tree_add_item(block_tree, hf_mausb_cancel_transfer_byte_offset,
969 tvb, offset, 4, ENC_LITTLE_ENDIAN);
970 offset += 4;
973 return offset;
976 /* dissects portions of a MA USB packet specific to ClearTransfers packets */
977 static uint16_t dissect_mausb_mgmt_pkt_clear_transfers(proto_tree *tree,
978 tvbuff_t *tvb, int16_t offset, bool req)
980 uint8_t num_block;
981 int i;
983 num_block = tvb_get_uint8(tvb, offset);
984 if (req) {
985 /* Number of entries */
986 proto_tree_add_item(tree, hf_mausb_clear_transfers_req_num, tvb,
987 offset, 1, ENC_LITTLE_ENDIAN);
988 offset += 1;
990 /* Rsvd */
991 proto_tree_add_item(tree, hf_mausb_clear_transfers_req_rsvd, tvb,
992 offset, 3, ENC_NA);
993 offset += 3;
995 } else {
996 num_block &= MAUSB_MGMT_CLEAR_TRANSFER_RESP_NUM_MASK;
998 /* Number of entries */
999 proto_tree_add_item(tree, hf_mausb_clear_transfers_resp_num, tvb,
1000 offset, 1, ENC_LITTLE_ENDIAN);
1001 /* Rsvd */
1002 proto_tree_add_item(tree, hf_mausb_clear_transfers_resp_rsvd, tvb,
1003 offset, 1, ENC_LITTLE_ENDIAN);
1004 offset += 4;
1007 for (i = 0; i < num_block; i++) {
1008 offset = dissect_clear_transfers_block(tree, tvb, offset, req);
1011 return offset;
1014 /* dissects portions of a MA USB packet specific to Endpoint Handle Request packets */
1015 static uint16_t dissect_mausb_mgmt_pkt_ep_handle( proto_tree *tree, tvbuff_t *tvb,
1016 packet_info *pinfo, int16_t start, bool req, bool del)
1018 urb_info_t urb;
1019 proto_item *size_field = NULL;
1020 uint16_t offset = start;
1021 uint16_t loop_offset;
1022 uint8_t num_ep;
1023 uint8_t size_ep_des;
1024 uint8_t last_ep_type = ENDPOINT_TYPE_NOT_SET;
1025 int i;
1027 memset(&urb, 0, sizeof(urb_info_t));
1029 num_ep = tvb_get_uint8(tvb, offset) & MAUSB_MGMT_NUM_EP_DES_MASK;
1031 if (!del) {
1032 proto_tree_add_item(tree, hf_mausb_mgmt_ep_des_num, tvb,
1033 offset, 1, ENC_LITTLE_ENDIAN); /* really 5 bits */
1034 } else {
1035 proto_tree_add_item(tree, hf_mausb_mgmt_ep_handle_num, tvb,
1036 offset, 1, ENC_LITTLE_ENDIAN); /* really 5 bits */
1039 if (req && !del) {
1041 size_ep_des = mausb_get_size_ep_des(tvb, offset);
1042 size_field = proto_tree_add_item(tree, hf_mausb_mgmt_ep_des_size, tvb,
1043 offset, 2, ENC_LITTLE_ENDIAN); /* really 6 bits over a byte boundary */
1044 offset += 1;
1046 /* Padding to DWORD */
1047 proto_tree_add_item(tree, hf_mausb_mgmt_ep_des_pad, tvb,
1048 offset, 3, ENC_NA);
1049 offset += 3;
1051 } else if (!req && !del) {
1052 size_ep_des = MAUSB_SIZE_MAUSB_EP_DES;
1053 proto_tree_add_item(tree, hf_mausb_mgmt_ep_handle_pad, tvb,
1054 offset, 4, ENC_NA); /* really 5 bits */
1055 /* Padding to DWORD */
1056 offset += 4;
1058 } else { /* If it is an EPHandleDelete Req or Resp */
1059 size_ep_des = MAUSB_SIZE_EP_HANDLE;
1060 /* Padding to DWORD */
1061 proto_tree_add_item(tree, hf_mausb_mgmt_ep_handle_pad, tvb,
1062 offset, 4, ENC_NA);
1063 offset += 4; /* Padding to DWORD */
1067 /* For every entry */
1068 for (i = 0; i < num_ep; ++i) {
1069 loop_offset = offset;
1071 /* If it is an EPHandleDelete Req or Resp */
1072 if (del) {
1073 loop_offset += dissect_ep_handle(tree, tvb, loop_offset);
1075 } else if (req) {
1077 /* Standard USB Endpoint Descriptor */
1078 dissect_usb_endpoint_descriptor(pinfo, tree, tvb, loop_offset,
1079 &urb, &last_ep_type, USB_SPEED_UNKNOWN);
1080 loop_offset += USB_DT_EP_SIZE;
1082 /* If there are more descriptors to read */
1083 if (MAUSB_EP_DES_SIZE < size_ep_des) {
1084 /* TODO: Dissector for SS EP Companion Descriptors */
1085 dissect_usb_unknown_descriptor(pinfo, tree,
1086 tvb, loop_offset, &urb);
1087 loop_offset += USB_DT_SS_EP_COMP_SIZE;
1089 if (MAUSB_SS_EP_DES_SIZE < size_ep_des) {
1090 /* TODO: Dissector for SSP ISO EP Companion Descriptors */
1091 loop_offset += dissect_usb_unknown_descriptor(pinfo, tree,
1092 tvb, loop_offset, &urb);
1094 /* Pad to a DWORD */
1095 proto_tree_add_item(tree, hf_mausb_ep_handle_req_pad, tvb,
1096 loop_offset, MAUSB_ISO_SSP_EP_DES_PAD, ENC_NA);
1097 loop_offset += MAUSB_ISO_SSP_EP_DES_PAD;
1099 } else {
1100 /* Pad to a DWORD */
1101 proto_tree_add_item(tree, hf_mausb_ep_handle_req_pad, tvb,
1102 loop_offset, MAUSB_SS_EP_DES_PAD, ENC_NA);
1103 loop_offset += MAUSB_SS_EP_DES_PAD;
1106 } else {
1107 /* Pad to a DWORD */
1108 proto_tree_add_item(tree, hf_mausb_ep_handle_req_pad, tvb,
1109 loop_offset, MAUSB_EP_DES_PAD, ENC_NA);
1110 loop_offset += MAUSB_EP_DES_PAD;
1113 } else { /* IE: it's a EPHandleResp */
1114 /* EP Handle */
1115 loop_offset += dissect_ep_handle(tree, tvb, loop_offset);
1117 /* direction */
1118 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_dir, tvb,
1119 loop_offset, 1, ENC_LITTLE_ENDIAN);
1121 /* isochronous */
1122 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_iso, tvb,
1123 loop_offset, 1, ENC_LITTLE_ENDIAN);
1125 /* L-managed transfers */
1126 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_lman, tvb,
1127 loop_offset, 1, ENC_LITTLE_ENDIAN);
1129 /* valid handle bit */
1130 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_valid, tvb,
1131 loop_offset, 1, ENC_LITTLE_ENDIAN);
1132 loop_offset += 2; /* 4 bit flags + 12 reserved bits */
1134 /* credit consumption unit */
1135 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_ccu, tvb,
1136 loop_offset, 2, ENC_LITTLE_ENDIAN);
1137 loop_offset += 2;
1139 loop_offset += 2; /* 2 bytes reserved */
1141 /* buffer size (in bytes) */
1142 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_buf_size, tvb,
1143 loop_offset, 4, ENC_LITTLE_ENDIAN);
1144 loop_offset += 4;
1147 /* max iso programming delay (in uSec) */
1148 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_iso_prog_dly, tvb,
1149 loop_offset, 2, ENC_LITTLE_ENDIAN);
1150 loop_offset += 2;
1152 /* max iso response delay (in uSec) */
1153 proto_tree_add_item(tree, hf_mausb_ep_handle_resp_iso_resp_dly, tvb,
1154 loop_offset, 2, ENC_LITTLE_ENDIAN);
1155 loop_offset += 2;
1159 offset += size_ep_des;
1161 if (req && !del && loop_offset != offset){
1162 expert_add_info(pinfo, size_field, &ei_ep_handle_len);
1167 return offset;
1171 /* dissects portions of a MA USB packet specific to CancelTransfer packets */
1172 static uint16_t dissect_mausb_mgmt_pkt_cancel_transfer( proto_tree *tree,
1173 tvbuff_t *tvb, int offset, bool req)
1176 uint8_t status;
1178 offset += dissect_ep_handle(tree, tvb, offset);
1180 proto_tree_add_item(tree, hf_mausb_stream_id, tvb, offset, 2,
1181 ENC_LITTLE_ENDIAN);
1182 offset += 2;
1184 proto_tree_add_item(tree, hf_mausb_req_id, tvb, offset, 1,
1185 ENC_LITTLE_ENDIAN);
1186 offset += 1;
1188 if (req) {
1189 proto_tree_add_item(tree, hf_mausb_cancel_transfer_rsvd, tvb, offset, 3,
1190 ENC_NA);
1191 offset += 3;
1193 return offset;
1194 } /* else resp */
1196 status = tvb_get_uint8(tvb, offset) |
1197 MAUSB_CANCEL_TRANSFER_STATUS_MASK;
1199 proto_tree_add_item(tree, hf_mausb_cancel_transfer_status, tvb, offset, 3,
1200 ENC_LITTLE_ENDIAN);
1202 proto_tree_add_item(tree, hf_mausb_cancel_transfer_rsvd_2, tvb, offset, 3,
1203 ENC_LITTLE_ENDIAN);
1204 /* Reserved */
1205 offset += 3;
1207 /* if some data was moved */
1208 if (2 == status) {
1209 /* TODO: sequence number reserved for INs */
1210 proto_tree_add_item(tree, hf_mausb_cancel_transfer_seq_num, tvb, offset,
1211 3, ENC_LITTLE_ENDIAN);
1212 offset += 3;
1214 proto_tree_add_item(tree, hf_mausb_cancel_transfer_rsvd, tvb, offset, 1,
1215 ENC_NA);
1216 offset += 1;
1218 proto_tree_add_item(tree, hf_mausb_cancel_transfer_byte_offset, tvb,
1219 offset, 4, ENC_LITTLE_ENDIAN);
1220 offset += 4;
1222 } else {
1223 proto_tree_add_item(tree, hf_mausb_cancel_transfer_rsvd, tvb, offset, 8,
1224 ENC_NA);
1225 offset += 8;
1228 return offset;
1232 /* dissects portions of a MA USB packet specific to particular management packets */
1233 static uint16_t dissect_mausb_mgmt_pkt_flds(struct mausb_header *header,
1234 proto_tree *tree, tvbuff_t *tvb,
1235 packet_info *pinfo, int16_t start)
1238 proto_item *ti;
1239 proto_tree *mgmt_tree;
1240 uint16_t offset = start;
1241 int type_spec_len = tvb_reported_length(tvb) - start;
1243 if (0 > type_spec_len) {
1244 expert_add_info(pinfo, tree, &ei_mgmt_type_spec_len_short);
1245 return offset;
1248 ti = proto_tree_add_item(tree, hf_mausb_mgmt_type_spec, tvb,
1249 offset, type_spec_len, ENC_NA);
1251 mgmt_tree = proto_item_add_subtree(ti, ett_mgmt);
1253 switch (header->type) {
1255 /* subtypes with variable length additional data */
1256 case CapResp:
1257 offset = dissect_mausb_mgmt_pkt_cap_resp(header, mgmt_tree, tvb, pinfo, offset);
1258 break;
1259 case EPHandleReq:
1260 offset = dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree, tvb, pinfo,
1261 offset, true, false);
1262 break;
1264 case EPHandleResp:
1265 offset = dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree, tvb, pinfo,
1266 offset, false, false);
1267 break;
1269 /* TODO: Dissect type-specific management packet fields */
1270 case EPActivateReq:
1271 case EPActivateResp:
1272 case EPInactivateReq:
1273 case EPInactivateResp:
1274 case EPResetReq:
1275 case EPResetResp:
1276 proto_tree_add_item(mgmt_tree, hf_mausb_mgmt_type_spec_generic,
1277 tvb, offset, type_spec_len, ENC_NA);
1278 offset += type_spec_len;
1279 break;
1280 case ClearTransfersReq:
1281 offset = dissect_mausb_mgmt_pkt_clear_transfers(mgmt_tree, tvb, offset, true);
1282 break;
1283 case ClearTransfersResp:
1284 offset = dissect_mausb_mgmt_pkt_clear_transfers(mgmt_tree, tvb, offset, false);
1285 break;
1286 case EPHandleDeleteReq:
1287 offset = dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree, tvb, pinfo,
1288 offset, true, true);
1289 break;
1290 case EPHandleDeleteResp:
1291 offset = dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree, tvb, pinfo,
1292 offset, false, true);
1293 break;
1294 case ModifyEP0Resp:
1295 case EPCloseStreamResp:
1296 case USBDevResetReq:
1297 case USBDevResetResp:
1298 case EPOpenStreamResp:
1299 case VendorSpecificReq:
1300 case VendorSpecificResp:
1301 /* FALLTHROUGH */
1303 /* subtypes with constant length additional data */
1304 case CapReq:
1305 case USBDevHandleReq:
1306 case USBDevHandleResp:
1307 case ModifyEP0Req:
1308 case SetUSBDevAddrReq:
1309 case SetUSBDevAddrResp:
1310 case UpdateDevReq:
1311 case SynchReq:
1312 case EPCloseStreamReq:
1313 proto_tree_add_item(mgmt_tree, hf_mausb_mgmt_type_spec_generic,
1314 tvb, offset, type_spec_len, ENC_NA);
1315 offset += type_spec_len;
1316 break;
1318 case CancelTransferReq:
1319 offset = dissect_mausb_mgmt_pkt_cancel_transfer(mgmt_tree, tvb, offset,
1320 true);
1321 break;
1322 case CancelTransferResp:
1323 offset = dissect_mausb_mgmt_pkt_cancel_transfer(mgmt_tree, tvb, offset,
1324 false);
1325 break;
1326 case EPOpenStreamReq:
1328 proto_tree_add_item(mgmt_tree, hf_mausb_mgmt_type_spec_generic,
1329 tvb, offset, type_spec_len, ENC_NA);
1330 offset += type_spec_len;
1331 break;
1334 /* Management packets with no additional data */
1335 case DevResetReq:
1336 case DevResetResp:
1337 case UpdateDevResp:
1338 case USBDevDisconnectReq:
1339 case USBDevDisconnectResp:
1340 case SleepReq:
1341 case SleepResp:
1342 case WakeReq:
1343 case WakeResp:
1344 case PingReq:
1345 case PingResp:
1346 case DevDisconnectReq:
1347 case DevDisconnectResp:
1348 case DevInitDisconnectReq:
1349 case DevInitDisconnectResp:
1350 case SynchResp:
1351 break;
1353 default:
1354 expert_add_info(pinfo, mgmt_tree, &ei_mgmt_type_undef);
1355 break;
1360 if (offset < tvb_reported_length(tvb)) {
1361 expert_add_info(pinfo, mgmt_tree, &ei_mgmt_type_spec_len_long);
1364 return offset;
1367 void mausb_set_urb_info(urb_info_t *urb, struct mausb_header *header)
1369 urb->is_request = mausb_is_transfer_req(header);
1370 urb->bus_id = mausb_ep_handle_bus_num(header->handle);
1371 urb->device_address = mausb_ep_handle_dev_addr(header->handle);
1372 urb->direction = mausb_is_from_host(header);
1373 urb->endpoint = mausb_ep_handle_ep_num(header->handle);
1374 if (mausb_ep_handle_ep_d(header->handle)) {
1375 /* IN endpoint */
1376 urb->endpoint |= 0x80;
1378 urb->is_setup = mausb_has_setup_data(header) ||
1379 mausb_is_setup_response(header);
1380 switch (mausb_tx_type(header)) {
1381 case MAUSB_TX_TYPE_CTRL:
1382 urb->transfer_type = URB_CONTROL;
1383 break;
1384 case MAUSB_TX_TYPE_ISOC:
1385 urb->transfer_type = URB_ISOCHRONOUS;
1386 break;
1387 case MAUSB_TX_TYPE_BULK:
1388 urb->transfer_type = URB_BULK;
1389 break;
1390 case MAUSB_TX_TYPE_INTR:
1391 urb->transfer_type = URB_INTERRUPT;
1392 break;
1393 default:
1394 urb->transfer_type = URB_UNKNOWN;
1395 break;
1399 /* Used to detect multiple MA Packets in a single TCP packet */
1400 /* Not used for MA Packets in SNAP Packets */
1401 static int mausb_num_pdus;
1404 /* dissect fields common to all MAUSB packet types */
1405 static int
1406 dissect_mausb_pkt_common(tvbuff_t *tvb, int offset, packet_info *pinfo,
1407 proto_tree *mausb_tree, struct mausb_header *header)
1409 proto_item *len_field;
1411 /* MAUSB Protocol Version */
1412 header->ver_flags = tvb_get_uint8(tvb, offset);
1413 proto_tree_add_item(mausb_tree, hf_mausb_version, tvb,
1414 offset, 1, ENC_LITTLE_ENDIAN);
1416 /* Flags */
1417 proto_tree_add_bitmask(mausb_tree, tvb, offset, hf_mausb_flags,
1418 ett_mausb_flags, mausb_flag_fields, ENC_LITTLE_ENDIAN);
1419 offset += 1;
1421 /* Packet Type */
1422 header->type = tvb_get_uint8(tvb, offset);
1423 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(header->type, mausb_type_string, "%d"));
1424 proto_tree_add_item(mausb_tree, hf_mausb_type, tvb,
1425 offset, 1, ENC_LITTLE_ENDIAN);
1426 offset += 1;
1428 /* Packet Length */
1429 header->length = tvb_get_letohs(tvb, offset);
1430 col_append_fstr(pinfo->cinfo, COL_INFO, " Length=%u", header->length);
1431 len_field = proto_tree_add_item(mausb_tree, hf_mausb_length, tvb,
1432 offset, 2, ENC_LITTLE_ENDIAN);
1433 offset += 2;
1435 /* Check to see if length field is valid */
1436 if (tvb_reported_length(tvb) != header->length) {
1437 expert_add_info(pinfo, len_field, &ei_len);
1440 /* Is the next field a device handle or an endpoint handle */
1441 header->handle = tvb_get_letohs(tvb, offset);
1443 if (mausb_is_mgmt_pkt(header)) {
1444 proto_tree_add_item(mausb_tree, hf_mausb_dev_handle, tvb,
1445 offset, 2, ENC_LITTLE_ENDIAN);
1446 offset += 2;
1447 } else {
1448 offset += dissect_ep_handle(mausb_tree, tvb, offset);
1451 /* MA Device Address */
1452 header->ma_dev_addr = tvb_get_uint8(tvb, offset);
1453 proto_tree_add_item(mausb_tree, hf_mausb_ma_dev_addr, tvb,
1454 offset, 1, ENC_LITTLE_ENDIAN);
1455 offset += 1;
1457 /* SSID */
1458 header->mass_id = tvb_get_uint8(tvb, offset);
1459 proto_tree_add_item(mausb_tree, hf_mausb_ssid, tvb,
1460 offset, 1, ENC_LITTLE_ENDIAN);
1461 offset += 1;
1463 /* Status */
1464 header->status = tvb_get_uint8(tvb, offset);
1465 proto_tree_add_item(mausb_tree, hf_mausb_status, tvb,
1466 offset, 1, ENC_LITTLE_ENDIAN);
1467 offset += 1;
1469 return offset;
1472 /* dissect datapacket specific values */
1473 static int
1474 dissect_mausb_pkt_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
1475 proto_tree *mausb_tree, struct mausb_header *header)
1477 /* EPS */
1478 header->u.s.eps_tflags = tvb_get_uint8(tvb, offset);
1479 if (mausb_is_from_host(header)) {
1480 proto_tree_add_item(mausb_tree, hf_mausb_eps_rsvd, tvb,
1481 offset, 1, ENC_LITTLE_ENDIAN);
1482 } else {
1483 proto_tree_add_item(mausb_tree, hf_mausb_eps, tvb,
1484 offset, 1, ENC_LITTLE_ENDIAN);
1487 /* T-Flags */
1488 proto_tree_add_bitmask(mausb_tree, tvb, offset, hf_mausb_tflags,
1489 ett_mausb_tflags, mausb_tflag_fields, ENC_LITTLE_ENDIAN);
1490 offset += 1;
1492 if (mausb_is_iso_pkt(header)) {
1493 /* Number of Headers */
1494 header->u.s.u1.num_headers_iflags = tvb_get_letohs(tvb, offset);
1495 proto_tree_add_item(mausb_tree, hf_mausb_num_iso_hdr, tvb,
1496 offset, 2, ENC_LITTLE_ENDIAN);
1498 /* I-Flags */
1499 proto_tree_add_bitmask(mausb_tree, tvb, offset, hf_mausb_iflags,
1500 ett_mausb_iflags, mausb_iflag_fields, ENC_LITTLE_ENDIAN);
1502 } else {
1503 /* Stream ID */
1504 header->u.s.u1.stream_id = tvb_get_letohs(tvb, offset);
1505 proto_tree_add_item(mausb_tree, hf_mausb_stream_id, tvb,
1506 offset, 2, ENC_LITTLE_ENDIAN);
1508 offset += 2;
1510 /* Sequence Number */
1511 header->u.s.seq_num = tvb_get_letoh24(tvb, offset);
1512 col_append_fstr(pinfo->cinfo, COL_INFO, " SeqNum=%u", header->u.s.seq_num);
1513 proto_tree_add_item(mausb_tree, hf_mausb_seq_num, tvb,
1514 offset, 3, ENC_LITTLE_ENDIAN);
1515 offset += 3;
1517 /* Request ID */
1518 header->u.s.req_id = tvb_get_uint8(tvb, offset);
1519 col_append_fstr(pinfo->cinfo, COL_INFO, " ReqID=%u", header->u.s.req_id);
1520 proto_tree_add_item(mausb_tree, hf_mausb_req_id, tvb,
1521 offset, 1, ENC_LITTLE_ENDIAN);
1522 offset += 1;
1524 if (mausb_is_iso_pkt(header)) {
1525 /* Presentation Time */
1526 header->u.s.u2.present_time_num_seg = tvb_get_letohl(tvb, offset);
1527 dissect_mausb_present_time(mausb_tree, tvb, offset);
1529 /* Number of Segments */
1530 proto_tree_add_item(mausb_tree, hf_mausb_num_segs, tvb,
1531 offset, 4, ENC_LITTLE_ENDIAN);
1532 offset += 4;
1534 /* MA USB Timestamp */
1535 if (mausb_has_timestamp(header)) {
1536 header->u.s.timestamp = tvb_get_letohl(tvb, offset);
1537 dissect_mausb_timestamp(mausb_tree, tvb, offset);
1538 offset += 4;
1541 /* Media Time/Transmission Delay */
1542 if (mausb_has_mtd(header)) {
1543 header->u.s.tx_dly = tvb_get_letohl(tvb, offset);
1544 proto_tree_add_item(mausb_tree, hf_mausb_mtd, tvb,
1545 offset, 4, ENC_LITTLE_ENDIAN);
1546 offset += 4;
1549 /* Not Iso */
1550 } else {
1551 /* Remaining Size/Credit */
1552 header->u.s.u2.credit = tvb_get_letohl(tvb, offset);
1553 proto_tree_add_item(mausb_tree, hf_mausb_rem_size_credit, tvb,
1554 offset, 4, ENC_LITTLE_ENDIAN);
1555 offset += 4;
1558 return offset;
1561 /* Code to actually dissect the packets */
1562 static int
1563 dissect_mausb_pkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1564 void *data _U_)
1566 /* Set up structures needed to add the protocol subtree and manage it */
1567 proto_item *ti;
1568 proto_tree *mausb_tree;
1569 /* Other misc. local variables. */
1570 struct mausb_header header;
1571 int offset = 0;
1573 memset(&header, 0, sizeof(struct mausb_header));
1575 /* Set the Protocol column to the constant string of mausb */
1576 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAUSB");
1578 mausb_num_pdus++;
1580 col_set_str(pinfo->cinfo, COL_INFO, "[");
1581 col_set_fence(pinfo->cinfo, COL_INFO);
1583 /*** PROTOCOL TREE ***/
1585 /* create display subtree for the protocol */
1586 ti = proto_tree_add_item(tree, proto_mausb, tvb, 0,
1587 mausb_get_pkt_len(pinfo, tvb, offset, NULL), ENC_NA);
1589 mausb_tree = proto_item_add_subtree(ti, ett_mausb);
1591 /* Add an item to the subtree, see section 1.5 of README.dissector for more
1592 * information. */
1594 offset = dissect_mausb_pkt_common(tvb, offset, pinfo, mausb_tree, &header);
1596 if (mausb_is_mgmt_pkt(&header)) {
1598 /* Dialog Token */
1599 header.u.token = tvb_get_letohs(tvb, 9) & MAUSB_TOKEN_MASK;
1600 col_append_fstr(pinfo->cinfo, COL_INFO, " Token=%u", header.u.token);
1601 proto_tree_add_item(mausb_tree, hf_mausb_token, tvb,
1602 offset, 2, ENC_LITTLE_ENDIAN); /* Really 10 bits */
1603 offset += 1; /* token */
1605 /* Padding to a DWORD */
1606 proto_tree_add_item(mausb_tree, hf_mausb_mgmt_pad, tvb,
1607 offset, 2, ENC_LITTLE_ENDIAN); /* Really 14 bits */
1609 offset += 2; /* DWORD*/
1611 /* Dissect additional management fields (when applicable) */
1612 if (offset < header.length) {
1613 dissect_mausb_mgmt_pkt_flds(&header, mausb_tree, tvb, pinfo, offset);
1617 else if (mausb_is_data_pkt(&header)) {
1618 dissect_mausb_pkt_data(tvb, offset, pinfo, mausb_tree, &header);
1620 if (!mausb_is_transfer_ack(&header)) {
1621 dissect_usb_common(tvb, pinfo, tree, USB_HEADER_MAUSB, &header);
1625 col_append_str(pinfo->cinfo, COL_INFO, "]");
1626 col_set_fence(pinfo->cinfo, COL_INFO);
1628 return header.length;
1631 /* Code to dissect the stream */
1632 static int
1633 dissect_mausb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1636 mausb_num_pdus = 0;
1638 tcp_dissect_pdus(tvb, pinfo, tree, true, MAUSB_MIN_LENGTH,
1639 mausb_get_pkt_len, dissect_mausb_pkt, data);
1641 if (1 < mausb_num_pdus) {
1642 col_clear_fence(pinfo->cinfo, COL_INFO);
1643 col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%i packets] ", mausb_num_pdus);
1646 return tvb_reported_length(tvb);
1650 /* Register the protocol with Wireshark.
1652 void
1653 proto_register_mausb(void)
1656 static hf_register_info hf[] = {
1657 { &hf_mausb_version,
1658 { "Version", "mausb.version", FT_UINT8, BASE_DEC,
1659 VALS(mausb_version_string), MAUSB_VERSION_MASK, NULL, HFILL
1662 { &hf_mausb_flags,
1663 { "Flags", "mausb.flags", FT_UINT8, BASE_HEX,
1664 NULL, MAUSB_FLAG_MASK, NULL, HFILL
1668 /* Flag Subfields */
1669 { &hf_mausb_flag_host,
1670 { "Host", "mausb.flags.host", FT_BOOLEAN, 8,
1671 TFS(&tfs_set_notset), (MAUSB_FLAG_HOST << MAUSB_FLAG_OFFSET),
1672 NULL, HFILL
1675 { &hf_mausb_flag_retry,
1676 { "Retry", "mausb.flags.retry", FT_BOOLEAN, 8,
1677 TFS(&tfs_yes_no), (MAUSB_FLAG_RETRY << MAUSB_FLAG_OFFSET),
1678 NULL, HFILL
1681 { &hf_mausb_flag_timestamp,
1682 { "Timestamp", "mausb.flags.timestamp", FT_BOOLEAN, 8,
1683 TFS(&tfs_present_not_present),
1684 (MAUSB_FLAG_TIMESTAMP << MAUSB_FLAG_OFFSET),
1685 NULL, HFILL
1688 { &hf_mausb_flag_reserved,
1689 { "Reserved", "mausb.flags.reserved", FT_BOOLEAN, 8,
1690 TFS(&tfs_set_notset), (MAUSB_FLAG_RESERVED << MAUSB_FLAG_OFFSET),
1691 NULL, HFILL
1696 { &hf_mausb_type,
1697 { "Type", "mausb.type", FT_UINT8, BASE_HEX,
1698 VALS(mausb_type_string), 0, NULL, HFILL
1701 { &hf_mausb_length,
1702 { "Length", "mausb.length", FT_UINT16, BASE_DEC,
1703 NULL, 0, NULL, HFILL
1706 { &hf_mausb_dev_handle,
1707 { "Device Handle", "mausb.dev_handle", FT_UINT16, BASE_HEX,
1708 NULL, 0, NULL, HFILL
1711 { &hf_mausb_ep_handle,
1712 { "Endpoint Handle", "mausb.ep_handle", FT_UINT16, BASE_HEX,
1713 NULL, 0, NULL, HFILL
1717 /* EP Handle Subfields */
1718 { &hf_mausb_ep_handle_d,
1719 { "Direction", "mausb.ep_handle.d", FT_BOOLEAN, 16,
1720 TFS(&tfs_endpoint_direction), MAUSB_EP_HANDLE_D, NULL, HFILL
1723 { &hf_mausb_ep_handle_ep_num,
1724 { "Endpoint Number", "mausb.ep_handle.ep_num", FT_UINT16, BASE_DEC,
1725 NULL, MAUSB_EP_HANDLE_EP_NUM, NULL, HFILL
1728 { &hf_mausb_ep_handle_dev_addr,
1729 { "USB Device Address", "mausb.ep_handle.dev_addr", FT_UINT16, BASE_DEC,
1730 NULL, MAUSB_EP_HANDLE_DEV_ADDR, NULL, HFILL
1733 { &hf_mausb_ep_handle_bus_num,
1734 { "USB Bus Number", "mausb.ep_handle.bus_num", FT_UINT16, BASE_DEC,
1735 NULL, MAUSB_EP_HANDLE_BUS_NUM, NULL, HFILL
1740 { &hf_mausb_ma_dev_addr,
1741 { "MA Device Address", "mausb.ma_dev_addr", FT_UINT8, BASE_HEX,
1742 NULL, 0, NULL, HFILL
1745 { &hf_mausb_ssid,
1746 { "Service Set ID", "mausb.ssid", FT_UINT8, BASE_HEX,
1747 NULL, 0, NULL, HFILL
1750 { &hf_mausb_status,
1751 { "Status", "mausb.status", FT_UINT8, BASE_DEC,
1752 VALS(mausb_status_string), 0, NULL, HFILL
1756 /* Management Packets Only */
1757 { &hf_mausb_token,
1758 { "Token", "mausb.token", FT_UINT16, BASE_DEC,
1759 NULL, MAUSB_TOKEN_MASK, NULL, HFILL
1762 { &hf_mausb_mgmt_pad,
1763 { "Padding to a DWORD", "mausb.mgmt_pad",
1764 FT_UINT16, BASE_HEX, NULL, MAUSB_MGMT_PAD_MASK,
1765 NULL, HFILL
1768 { &hf_mausb_mgmt_type_spec,
1769 { "Type-specific management packet fields", "mausb.mgmt_flds",
1770 FT_NONE, 0, NULL, 0, NULL, HFILL
1773 { &hf_mausb_mgmt_type_spec_generic,
1774 { "Type-specific management packet fields", "mausb.mgmt_flds.generic",
1775 FT_NONE, 0, NULL, 0, NULL, HFILL
1779 /* Data Packets Only */
1780 { &hf_mausb_eps,
1781 { "EP Status", "mausb.eps", FT_UINT8, BASE_HEX,
1782 VALS(mausb_eps_string), MAUSB_EPS_MASK, NULL, HFILL
1785 { &hf_mausb_eps_rsvd,
1786 { "EP Status", "mausb.eps.reserved", FT_UINT8, BASE_HEX,
1787 NULL, MAUSB_EPS_MASK, NULL, HFILL
1790 { &hf_mausb_tflags,
1791 { "Transfer Flags", "mausb.tflag", FT_UINT8, BASE_HEX,
1792 NULL, MAUSB_TFLAG_MASK, NULL, HFILL
1796 /* T-Flag Subfields */
1797 { &hf_mausb_tflag_arq,
1798 { "ARQ", "mausb.tflag.arq", FT_BOOLEAN, 8,
1799 TFS(&tfs_set_notset), MAUSB_TFLAG_ARQ << MAUSB_TFLAG_OFFSET,
1800 NULL, HFILL
1803 { &hf_mausb_tflag_neg,
1804 { "NEG", "mausb.tflag.neg", FT_BOOLEAN, 8,
1805 TFS(&tfs_set_notset), MAUSB_TFLAG_NEG << MAUSB_TFLAG_OFFSET,
1806 NULL, HFILL
1809 { &hf_mausb_tflag_eot,
1810 { "EoT", "mausb.tflag.eot", FT_BOOLEAN, 8,
1811 TFS(&tfs_set_notset), MAUSB_TFLAG_EOT << MAUSB_TFLAG_OFFSET,
1812 NULL, HFILL
1815 { &hf_mausb_tflag_type,
1816 { "Transfer Type", "mausb.tflag.type", FT_UINT8, BASE_HEX,
1817 VALS(mausb_transfer_type_string),
1818 MAUSB_TFLAG_TRANSFER_TYPE << MAUSB_TFLAG_OFFSET,
1819 NULL, HFILL
1822 { &hf_mausb_tflag_rsvd,
1823 { "Reserved", "mausb.tflag.rsvd", FT_BOOLEAN, 8,
1824 TFS(&tfs_set_notset), MAUSB_TFLAG_RSVD << MAUSB_TFLAG_OFFSET,
1825 NULL, HFILL
1830 { &hf_mausb_num_iso_hdr,
1831 { "Number of Iso Headers", "mausb.numisohdr", FT_UINT16, BASE_DEC,
1832 NULL, MAUSB_NUM_ISO_HDR_MASK, NULL, HFILL
1835 { &hf_mausb_iflags,
1836 { "Isochronous Flags", "mausb.iflag", FT_UINT16, BASE_HEX,
1837 NULL, MAUSB_IFLAG_MASK, NULL, HFILL
1841 /* I-Flag Subfields */
1842 { &hf_mausb_iflag_mtd,
1843 { "MTD Valid", "mausb.iflag.mtd", FT_BOOLEAN, 8,
1844 TFS(&tfs_set_notset), MAUSB_IFLAG_MTD << MAUSB_IFLAG_OFFSET,
1845 NULL, HFILL
1848 { &hf_mausb_iflag_hdr_format,
1849 { "Isochronous Header Format", "mausb.iflag.ihf", FT_UINT8, BASE_HEX,
1850 NULL, MAUSB_IFLAG_HDR_FORMAT << MAUSB_IFLAG_OFFSET, NULL, HFILL
1853 { &hf_mausb_iflag_asap,
1854 { "ASAP", "mausb.iflag.asap", FT_BOOLEAN, 8,
1855 TFS(&tfs_set_notset), MAUSB_IFLAG_ASAP << MAUSB_IFLAG_OFFSET,
1856 NULL, HFILL
1860 { &hf_mausb_stream_id,
1861 { "Stream ID", "mausb.streamid", FT_UINT16, BASE_DEC,
1862 NULL, 0, NULL, HFILL
1865 { &hf_mausb_seq_num,
1866 { "Sequence Number", "mausb.seqnum", FT_UINT24, BASE_DEC,
1867 NULL, 0, NULL, HFILL
1870 { &hf_mausb_req_id,
1871 { "Request ID", "mausb.reqid", FT_UINT8, BASE_DEC,
1872 NULL, 0, NULL, HFILL
1875 { &hf_mausb_present_time,
1876 { "Presentation Time", "mausb.presenttime", FT_UINT32, BASE_DEC,
1877 NULL, MAUSB_PRESENT_TIME_MASK, NULL, HFILL
1880 { &hf_mausb_uframe,
1881 { "Microframe Number", "mausb.uframe", FT_UINT32, BASE_DEC,
1882 NULL, MAUSB_UFRAME_MASK, NULL, HFILL
1885 { &hf_mausb_frame,
1886 { "Frame Number", "mausb.frame", FT_UINT32, BASE_DEC,
1887 NULL, MAUSB_FRAME_MASK, NULL, HFILL
1890 { &hf_mausb_num_segs,
1891 { "Number of Segments", "mausb.numseg", FT_UINT32, BASE_DEC,
1892 NULL, MAUSB_NUM_SEGS_MASK, NULL, HFILL
1895 { &hf_mausb_timestamp,
1896 { "Timestamp", "mausb.timestamp", FT_UINT32, BASE_DEC,
1897 NULL, 0, NULL, HFILL
1900 { &hf_mausb_delta,
1901 { "Delta", "mausb.delta", FT_UINT32, BASE_DEC,
1902 NULL, MAUSB_DELTA_MASK, NULL, HFILL
1905 { &hf_mausb_nom_interval,
1906 { "Nominal Bus Interval", "mausb.nomitvl", FT_UINT32, BASE_DEC,
1907 NULL, MAUSB_INTERVAL_MASK, NULL, HFILL
1910 { &hf_mausb_mtd,
1911 { "Media Time/Transmission Delay", "mausb.mtd", FT_UINT32, BASE_DEC,
1912 NULL, 0, NULL, HFILL
1915 { &hf_mausb_rem_size_credit,
1916 { "Remaining Size/Credit", "mausb.remsize_credit", FT_UINT32, BASE_DEC,
1917 NULL, 0, NULL, HFILL
1923 /* Register info for CapReq/Resp specific fields */
1924 static hf_register_info hf_cap[] = {
1926 { &hf_mausb_cap_resp_num_ep,
1927 { "Number of Endpoints", "mausb.cap_resp.num_ep",
1928 FT_UINT16, BASE_DEC, NULL, 0,
1929 "the maximum number of endpoints for this device",
1930 HFILL
1933 { &hf_mausb_cap_resp_num_dev,
1934 { "Number of Devices", "mausb.cap_resp.num_dev",
1935 FT_UINT8, BASE_DEC, NULL, 0,
1936 "the maximum number of USB devices the MA USB device can manage",
1937 HFILL
1940 { &hf_mausb_cap_resp_num_stream,
1941 { "Number of Streams", "mausb.cap_resp.num_stream",
1942 FT_UINT8, BASE_DEC, NULL, MAUSB_CAP_RESP_NUM_STREAM_MASK,
1943 "2 to the power of this value is the max number of streams supported",
1944 /* TODO: have dissector print the actual number of streams supported */
1945 HFILL
1948 { &hf_mausb_cap_resp_dev_type,
1949 { "Device Type", "mausb.cap_resp.dev_type", FT_UINT8, BASE_HEX,
1950 VALS(mausb_cap_resp_dev_type), MAUSB_CAP_RESP_DEV_TYPE_MASK,
1951 NULL, HFILL
1954 { &hf_mausb_cap_resp_desc_count,
1955 { "Descriptors Count", "mausb.cap_resp.desc_count",
1956 FT_UINT8, BASE_DEC,
1957 NULL, 0, "The total number of MA Device Capabilities descriptors",
1958 HFILL
1961 { &hf_mausb_cap_resp_desc_len,
1962 { "Descriptors Length", "mausb.cap_resp.desc_len",
1963 FT_UINT24, BASE_DEC,
1964 NULL, 0, "The total size of MA Device Capabilities descriptors",
1965 HFILL
1968 { &hf_mausb_cap_resp_transfer_req,
1969 { "Number of Outstanding Transfer Requests",
1970 "mausb.cap_resp.transfer_req",
1971 FT_UINT16, BASE_DEC, NULL, 0,
1972 "The maximum number of total outstanding transfer requests", HFILL
1975 { &hf_mausb_cap_resp_mgmt_req,
1976 { "Number of Outstanding Management Requests", "mausb.cap_resp.mgmt_req",
1977 FT_UINT16, BASE_DEC, NULL,
1978 MAUSB_CAP_RESP_MGMT_REQ_MASK,
1979 "The maximum number of host initiated outstanding management requests",
1980 HFILL
1983 { &hf_mausb_cap_resp_rsvd,
1984 { "Reserved", "mausb.cap_resp.rsvd", FT_UINT16, BASE_HEX,
1985 NULL, MAUSB_CAP_RESP_RSVD_MASK, NULL, HFILL
1989 /* Device Capability Descriptors */
1990 { &hf_mausb_dev_cap_len,
1991 { "Length", "mausb.cap_resp.dev_cap.length",
1992 FT_UINT8, BASE_DEC, NULL,
1993 0, NULL, HFILL
1996 { &hf_mausb_dev_cap_type,
1997 { "Type", "mausb.cap_resp.dev_cap.type",
1998 FT_UINT8, BASE_DEC, VALS(mausb_dev_cap_string),
1999 0, NULL, HFILL
2002 { &hf_mausb_dev_cap_generic,
2003 { "Type-specific device capability descriptor fields",
2004 "mausb.cap_resp.dev_cap.generic",
2005 FT_NONE, 0, NULL, 0, NULL, HFILL
2011 /* register info for ep_handle_* specific fields */
2012 static hf_register_info hf_ep_handle[] = {
2013 { &hf_mausb_mgmt_ep_handle_num,
2014 { "Number of Endpoint Handles", "mausb.ep_handle_num",
2015 FT_UINT8, BASE_DEC,
2016 NULL, MAUSB_MGMT_NUM_EP_DES_MASK, NULL, HFILL
2019 { &hf_mausb_mgmt_ep_handle_pad,
2020 { "Padding to a DWORD", "mausb.ep_handle_pad",
2021 FT_NONE, 0,
2022 NULL, 0x0, NULL, HFILL
2025 { &hf_mausb_mgmt_ep_des_num,
2026 { "Number of Endpoint Descriptors", "mausb.ep_des_num",
2027 FT_UINT8, BASE_DEC,
2028 NULL, MAUSB_MGMT_NUM_EP_DES_MASK, NULL, HFILL
2031 { &hf_mausb_mgmt_ep_des_size,
2032 { "Size of Endpoint Descriptors", "mausb.ep_des_size",
2033 FT_UINT16, BASE_DEC,
2034 NULL, MAUSB_MGMT_SIZE_EP_DES_MASK, NULL, HFILL
2037 { &hf_mausb_mgmt_ep_des_pad,
2038 { "Padding to a DWORD", "mausb.ep_des_pad",
2039 FT_NONE, 0, NULL,
2040 0x0,
2041 NULL, HFILL
2045 { &hf_mausb_ep_handle_req_pad,
2046 { "Padding to a DWORD", "mausb.ep_handle_req.pad",
2047 FT_NONE, 0, NULL, 0, NULL, HFILL
2050 { &hf_mausb_ep_handle_resp_dir,
2051 { "Direction", "mausb.ep_dir", FT_BOOLEAN, 6,
2052 TFS(&tfs_ep_handle_resp_dir), MAUSB_EP_HANDLE_RESP_DIR_MASK,
2053 NULL, HFILL
2056 { &hf_mausb_ep_handle_resp_iso,
2057 { "Isochronous", "mausb.ep_iso", FT_BOOLEAN, 6,
2058 TFS(&tfs_yes_no), MAUSB_EP_HANDLE_RESP_ISO_MASK, NULL, HFILL
2061 { &hf_mausb_ep_handle_resp_lman,
2062 { "L-Managed", "mausb.ep_lman", FT_BOOLEAN, 6,
2063 TFS(&tfs_supported_not_supported), MAUSB_EP_HANDLE_RESP_LMAN_MASK,
2064 NULL, HFILL
2067 { &hf_mausb_ep_handle_resp_valid,
2068 { "Valid", "mausb.ep_valid", FT_BOOLEAN, 6,
2069 TFS(&tfs_invalid_valid), MAUSB_EP_HANDLE_RESP_VALID_MASK,
2070 NULL, HFILL
2073 { &hf_mausb_ep_handle_resp_ccu,
2074 { "CCU", "mausb.ep_ccu", FT_UINT16, BASE_DEC,
2075 NULL, 0, NULL, HFILL
2078 { &hf_mausb_ep_handle_resp_buf_size,
2079 { "Buffer Size", "mausb.ep_buf_size", FT_UINT32, BASE_DEC,
2080 NULL, 0, NULL, HFILL
2083 { &hf_mausb_ep_handle_resp_iso_prog_dly,
2084 { "Iso Programming Delay", "mausb.ep_iso_prog_dly", FT_UINT16, BASE_DEC,
2085 NULL, 0, NULL, HFILL
2088 { &hf_mausb_ep_handle_resp_iso_resp_dly,
2089 { "Iso Response Delay", "mausb.ep_iso_resp_dly", FT_UINT16, BASE_DEC,
2090 NULL, 0, NULL, HFILL
2097 /* (Cancel/Clear)Transfer(Req/Resp) specific fields */
2098 static hf_register_info hf_cancel_transfer[] = {
2099 { &hf_mausb_clear_transfers_info_block,
2100 { "Clear Transfers Information Block", "mausb.clear_transfers.info", FT_NONE, 0,
2101 NULL, 0, NULL, HFILL
2104 { &hf_mausb_clear_transfers_status_block,
2105 { "Cancel Transfers Status Block", "mausb.clear_transfers.status_block", FT_NONE, 0,
2106 NULL, 0, NULL, HFILL
2109 { &hf_mausb_cancel_transfer_rsvd,
2110 { "Reserved", "mausb.cancel_transfer.rsvd", FT_NONE, 0,
2111 NULL, 0, NULL, HFILL
2114 { &hf_mausb_clear_transfers_req_num,
2115 { "Number of Blocks", "mausb.clear_transfers_req.num", FT_UINT8, BASE_DEC,
2116 NULL, 0, NULL, HFILL
2119 { &hf_mausb_clear_transfers_req_rsvd,
2120 { "Reserved", "mausb.clear_transfers_req.rsvd", FT_NONE, 0,
2121 NULL, 0, NULL, HFILL
2124 { &hf_mausb_clear_transfers_resp_num,
2125 { "Number of Blocks", "mausb.clear_transfers_resp.num", FT_UINT32, BASE_DEC,
2126 NULL, MAUSB_CLEAR_TRANSFERS_RESP_NUM_MASK , NULL, HFILL
2129 { &hf_mausb_clear_transfers_resp_rsvd,
2130 { "Reserved", "mausb.clear_transfers_resp.rsvd", FT_UINT32, BASE_HEX,
2131 NULL, ~MAUSB_CLEAR_TRANSFERS_RESP_NUM_MASK, NULL, HFILL
2134 { &hf_mausb_cancel_transfer_status,
2135 { "Status", "mausb.cancel_transfer.status", FT_UINT24, BASE_HEX,
2136 VALS(mausb_cancel_transfer_status_string),
2137 MAUSB_CANCEL_TRANSFER_STATUS_MASK, NULL, HFILL
2140 { &hf_mausb_cancel_transfer_rsvd_2,
2141 { "Reserved", "mausb.cancel_transfer.rsvd_2", FT_UINT24, BASE_HEX,
2142 NULL, ~MAUSB_CANCEL_TRANSFER_STATUS_MASK, NULL, HFILL
2145 { &hf_mausb_clear_transfers_status,
2146 { "Cancellation Status", "mausb.clear_transfers.status", FT_BOOLEAN, 6,
2147 TFS(&tfs_success_fail), MAUSB_CLEAR_TRANSFERS_STATUS_MASK,
2148 NULL, HFILL
2151 { &hf_mausb_clear_transfers_partial,
2152 { "Partial Delivery", "mausb.clear_transfers.partial", FT_BOOLEAN, 6,
2153 NULL, MAUSB_CLEAR_TRANSFERS_PARTIAL_MASK,
2154 NULL, HFILL
2157 { &hf_mausb_clear_transfers_start_req_id,
2158 { "Start Request ID", "mausb.clear_transfers.start_reqid", FT_UINT8, BASE_DEC,
2159 NULL, 0, NULL, HFILL
2162 { &hf_mausb_clear_transfers_last_req_id,
2163 { "Last Request ID", "mausb.clear_transfers.last_reqid", FT_UINT8, BASE_DEC,
2164 NULL, 0, NULL, HFILL
2167 { &hf_mausb_clear_transfers_req_block_rsvd,
2168 { "Reserved", "mausb.clear_transfers_req.block_rsvd", FT_NONE, 0,
2169 NULL, 0, NULL, HFILL
2172 { &hf_mausb_clear_transfers_resp_block_rsvd,
2173 { "Reserved", "mausb.clear_transfers_resp.block_rsvd", FT_UINT32, BASE_HEX,
2174 NULL, MAUSB_CLEAR_TRANSFERS_RESP_BLOCK_RSVD_MASK, NULL, HFILL
2178 { &hf_mausb_cancel_transfer_seq_num,
2179 { "Delivered Sequence Number", "mausb.cancel_transfer.seqnum",
2180 FT_UINT24, BASE_DEC, NULL, 0, NULL, HFILL
2183 { &hf_mausb_cancel_transfer_byte_offset,
2184 { "Delivered Byte Offset", "mausb.cancel_transfer.byte_offset",
2185 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL
2190 static hf_register_info oui_hf[] = {
2191 { &hf_llc_mausb_pid,
2192 { "PID", "mausb.pid", FT_UINT16, BASE_HEX,
2193 VALS(mausb_pid_string), 0x0, NULL, HFILL }
2197 /* Setup protocol subtree array */
2198 static int *ett[] = {
2199 &ett_mausb,
2200 &ett_mausb_flags,
2201 &ett_mausb_ep_handle,
2202 &ett_mausb_tflags,
2203 &ett_mausb_iflags,
2204 &ett_mausb_present_time,
2205 &ett_mausb_timestamp,
2206 &ett_mgmt,
2207 &ett_dev_cap,
2208 &ett_clear_transfers_block
2211 static ei_register_info ei[] = {
2212 { &ei_ep_handle_len,
2213 { "mausb.ei.ep_handle.length", PI_PROTOCOL, PI_WARN,
2214 "Invalid Endpoint handle length field", EXPFILL }
2216 { &ei_len,
2217 { "mausb.ei.length", PI_MALFORMED, PI_ERROR,
2218 "Packet length field does not match size of packet", EXPFILL }
2220 { &ei_mgmt_type_undef,
2221 { "mausb.ei.type", PI_PROTOCOL, PI_WARN,
2222 "Undefined management packet type", EXPFILL }
2224 { &ei_mgmt_type_spec_len_long,
2225 { "mausb.ei.type_spec.len", PI_PROTOCOL, PI_WARN,
2226 "Data exists after type-specific management packet field", EXPFILL }
2228 { &ei_mgmt_type_spec_len_short,
2229 { "mausb.ei.type_spec.len", PI_PROTOCOL, PI_WARN,
2230 "Expected type-specific management packet data", EXPFILL }
2232 { &ei_dev_cap_len,
2233 { "mausb.ei.cap_resp.dev_cap.length", PI_PROTOCOL, PI_WARN,
2234 "Incorrect length value for this device capability descriptor",
2235 EXPFILL }
2237 { &ei_dev_cap_resp_desc_len,
2238 { "mausb.ei.dev_cap_resp.desc_len", PI_PROTOCOL, PI_WARN,
2239 "Incorrect value in Device Descriptors Length field", EXPFILL }
2241 { &ei_cap_resp_desc_len,
2242 { "mausb.ei.cap_resp.desc_len", PI_PROTOCOL, PI_WARN,
2243 "Value in Descriptors Length field exceeds actual space in packet", EXPFILL }
2247 expert_module_t* expert_mausb;
2249 /* Register the protocol name and description */
2250 proto_mausb = proto_register_protocol("Media Agnostic USB", "MAUSB", "mausb");
2252 /* Required function calls to register the header fields and subtrees */
2253 proto_register_field_array(proto_mausb, hf, array_length(hf));
2254 proto_register_field_array(proto_mausb, hf_cap, array_length(hf_cap));
2255 proto_register_field_array(proto_mausb, hf_ep_handle, array_length(hf_ep_handle));
2256 proto_register_field_array(proto_mausb, hf_cancel_transfer, array_length(hf_cancel_transfer));
2257 proto_register_subtree_array(ett, array_length(ett));
2259 /* for Expert info */
2260 expert_mausb = expert_register_protocol(proto_mausb);
2261 expert_register_field_array(expert_mausb, ei, array_length(ei));
2263 llc_add_oui(OUI_WFA, "llc.wfa_pid", "LLC WFA OUI PID", oui_hf, proto_mausb);
2265 /* Register the dissectors */
2266 mausb_tcp_handle = register_dissector("mausb", dissect_mausb, proto_mausb);
2267 mausb_pkt_handle = register_dissector("mausb.pkt", dissect_mausb_pkt, proto_mausb);
2271 void
2272 proto_reg_handoff_mausb(void)
2274 dissector_add_uint("llc.wfa_pid", PID_MAUSB, mausb_pkt_handle);
2276 dissector_add_uint_range_with_preference("tcp.port", "", mausb_tcp_handle);
2277 dissector_add_for_decode_as_with_preference("udp.port", mausb_pkt_handle);
2281 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2283 * Local variables:
2284 * c-basic-offset: 4
2285 * tab-width: 8
2286 * indent-tabs-mode: nil
2287 * End:
2289 * vi: set shiftwidth=4 tabstop=8 expandtab:
2290 * :indentSize=4:tabSize=8:noTabs=true: