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
17 #include <epan/packet.h>
18 #include <epan/expert.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
[] = {
47 &hf_mausb_flag_timestamp
,
48 &hf_mausb_flag_reserved
,
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
[] = {
134 &hf_mausb_tflag_type
,
135 &hf_mausb_tflag_rsvd
,
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
[] = {
147 &hf_mausb_iflag_hdr_format
,
148 &hf_mausb_iflag_asap
,
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" },
195 static const value_string mausb_version_string
[] = {
196 { MAUSB_VERSION_1_0
, "MAUSB protocol version 1.0" },
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
,
244 USBDevDisconnectReq
,
245 USBDevDisconnectResp
,
257 DevInitDisconnectReq
,
258 DevInitDisconnectResp
,
271 DevNotificationResp
,
281 /* Vendor-Specific Management Packets */
282 VendorSpecificReq
= 0x3E | MAUSB_PKT_TYPE_MGMT
,
285 /* Control Packets */
286 TransferSetupReq
= 0x00 | MAUSB_PKT_TYPE_CTRL
,
288 TransferTearDownConf
,
291 TransferReq
= 0x00 | MAUSB_PKT_TYPE_DATA
,
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" },
376 { TransferReq
, "TransferReq" },
377 { TransferResp
, "TransferResp" },
378 { TransferAck
, "TransferAck" },
379 { IsochTransferReq
, "IsochTransferReq" },
380 { IsochTransferResp
, "IsochTransferResp" },
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" },
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" },
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" },
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" },
485 enum mausb_dev_cap_type
{
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
[] = {
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
[] = {
534 { 1, "Isochronous" },
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"},
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
))) {
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
))) {
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
;
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
)
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
,
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
);
732 proto_tree_add_item(dev_cap_tree
, hf_mausb_dev_cap_type
,
733 tvb
, desc_offset
, 1, ENC_LITTLE_ENDIAN
);
738 /* TODO: dissect individual capabilities */
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);
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
)
773 proto_item
*len_field
;
774 uint16_t loop_offset
;
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
);
782 proto_tree_add_item(tree
, hf_mausb_cap_resp_num_dev
,
783 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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 */
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
);
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
);
802 proto_tree_add_item(tree
, hf_mausb_cap_resp_transfer_req
,
803 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
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 */
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
)
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
,
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
,
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
);
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
)
914 proto_tree
*block_tree
;
917 ti
= proto_tree_add_item(tree
, hf_mausb_clear_transfers_info_block
,
918 tvb
, offset
, 8, ENC_NA
);
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
);
928 offset
+= dissect_ep_handle(block_tree
, tvb
, offset
);
931 proto_tree_add_item(block_tree
, hf_mausb_stream_id
, tvb
, offset
, 2,
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
);
942 proto_tree_add_item(block_tree
, hf_mausb_clear_transfers_req_block_rsvd
,
943 tvb
, offset
, 3, ENC_NA
);
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
);
954 proto_tree_add_item(block_tree
, hf_mausb_clear_transfers_resp_block_rsvd
,
955 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
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
);
963 /* Delivered Sequence Number */
964 proto_tree_add_item(block_tree
, hf_mausb_cancel_transfer_seq_num
, tvb
,
965 offset
, 3, ENC_LITTLE_ENDIAN
);
967 /* Delivered Byte Offset */
968 proto_tree_add_item(block_tree
, hf_mausb_cancel_transfer_byte_offset
,
969 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
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
)
983 num_block
= tvb_get_uint8(tvb
, offset
);
985 /* Number of entries */
986 proto_tree_add_item(tree
, hf_mausb_clear_transfers_req_num
, tvb
,
987 offset
, 1, ENC_LITTLE_ENDIAN
);
991 proto_tree_add_item(tree
, hf_mausb_clear_transfers_req_rsvd
, tvb
,
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
);
1002 proto_tree_add_item(tree
, hf_mausb_clear_transfers_resp_rsvd
, tvb
,
1003 offset
, 1, ENC_LITTLE_ENDIAN
);
1007 for (i
= 0; i
< num_block
; i
++) {
1008 offset
= dissect_clear_transfers_block(tree
, tvb
, offset
, req
);
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
)
1019 proto_item
*size_field
= NULL
;
1020 uint16_t offset
= start
;
1021 uint16_t loop_offset
;
1023 uint8_t size_ep_des
;
1024 uint8_t last_ep_type
= ENDPOINT_TYPE_NOT_SET
;
1027 memset(&urb
, 0, sizeof(urb_info_t
));
1029 num_ep
= tvb_get_uint8(tvb
, offset
) & MAUSB_MGMT_NUM_EP_DES_MASK
;
1032 proto_tree_add_item(tree
, hf_mausb_mgmt_ep_des_num
, tvb
,
1033 offset
, 1, ENC_LITTLE_ENDIAN
); /* really 5 bits */
1035 proto_tree_add_item(tree
, hf_mausb_mgmt_ep_handle_num
, tvb
,
1036 offset
, 1, ENC_LITTLE_ENDIAN
); /* really 5 bits */
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 */
1046 /* Padding to DWORD */
1047 proto_tree_add_item(tree
, hf_mausb_mgmt_ep_des_pad
, tvb
,
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 */
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
,
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 */
1073 loop_offset
+= dissect_ep_handle(tree
, tvb
, loop_offset
);
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
;
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
;
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 */
1115 loop_offset
+= dissect_ep_handle(tree
, tvb
, loop_offset
);
1118 proto_tree_add_item(tree
, hf_mausb_ep_handle_resp_dir
, tvb
,
1119 loop_offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
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
);
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
);
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
);
1159 offset
+= size_ep_des
;
1161 if (req
&& !del
&& loop_offset
!= offset
){
1162 expert_add_info(pinfo
, size_field
, &ei_ep_handle_len
);
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
)
1178 offset
+= dissect_ep_handle(tree
, tvb
, offset
);
1180 proto_tree_add_item(tree
, hf_mausb_stream_id
, tvb
, offset
, 2,
1184 proto_tree_add_item(tree
, hf_mausb_req_id
, tvb
, offset
, 1,
1189 proto_tree_add_item(tree
, hf_mausb_cancel_transfer_rsvd
, tvb
, offset
, 3,
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,
1202 proto_tree_add_item(tree
, hf_mausb_cancel_transfer_rsvd_2
, tvb
, offset
, 3,
1207 /* if some data was moved */
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
);
1214 proto_tree_add_item(tree
, hf_mausb_cancel_transfer_rsvd
, tvb
, offset
, 1,
1218 proto_tree_add_item(tree
, hf_mausb_cancel_transfer_byte_offset
, tvb
,
1219 offset
, 4, ENC_LITTLE_ENDIAN
);
1223 proto_tree_add_item(tree
, hf_mausb_cancel_transfer_rsvd
, tvb
, offset
, 8,
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
)
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
);
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 */
1257 offset
= dissect_mausb_mgmt_pkt_cap_resp(header
, mgmt_tree
, tvb
, pinfo
, offset
);
1260 offset
= dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree
, tvb
, pinfo
,
1261 offset
, true, false);
1265 offset
= dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree
, tvb
, pinfo
,
1266 offset
, false, false);
1269 /* TODO: Dissect type-specific management packet fields */
1271 case EPActivateResp
:
1272 case EPInactivateReq
:
1273 case EPInactivateResp
:
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
;
1280 case ClearTransfersReq
:
1281 offset
= dissect_mausb_mgmt_pkt_clear_transfers(mgmt_tree
, tvb
, offset
, true);
1283 case ClearTransfersResp
:
1284 offset
= dissect_mausb_mgmt_pkt_clear_transfers(mgmt_tree
, tvb
, offset
, false);
1286 case EPHandleDeleteReq
:
1287 offset
= dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree
, tvb
, pinfo
,
1288 offset
, true, true);
1290 case EPHandleDeleteResp
:
1291 offset
= dissect_mausb_mgmt_pkt_ep_handle(mgmt_tree
, tvb
, pinfo
,
1292 offset
, false, true);
1295 case EPCloseStreamResp
:
1296 case USBDevResetReq
:
1297 case USBDevResetResp
:
1298 case EPOpenStreamResp
:
1299 case VendorSpecificReq
:
1300 case VendorSpecificResp
:
1303 /* subtypes with constant length additional data */
1305 case USBDevHandleReq
:
1306 case USBDevHandleResp
:
1308 case SetUSBDevAddrReq
:
1309 case SetUSBDevAddrResp
:
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
;
1318 case CancelTransferReq
:
1319 offset
= dissect_mausb_mgmt_pkt_cancel_transfer(mgmt_tree
, tvb
, offset
,
1322 case CancelTransferResp
:
1323 offset
= dissect_mausb_mgmt_pkt_cancel_transfer(mgmt_tree
, tvb
, offset
,
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
;
1334 /* Management packets with no additional data */
1338 case USBDevDisconnectReq
:
1339 case USBDevDisconnectResp
:
1346 case DevDisconnectReq
:
1347 case DevDisconnectResp
:
1348 case DevInitDisconnectReq
:
1349 case DevInitDisconnectResp
:
1354 expert_add_info(pinfo
, mgmt_tree
, &ei_mgmt_type_undef
);
1360 if (offset
< tvb_reported_length(tvb
)) {
1361 expert_add_info(pinfo
, mgmt_tree
, &ei_mgmt_type_spec_len_long
);
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
)) {
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
;
1384 case MAUSB_TX_TYPE_ISOC
:
1385 urb
->transfer_type
= URB_ISOCHRONOUS
;
1387 case MAUSB_TX_TYPE_BULK
:
1388 urb
->transfer_type
= URB_BULK
;
1390 case MAUSB_TX_TYPE_INTR
:
1391 urb
->transfer_type
= URB_INTERRUPT
;
1394 urb
->transfer_type
= URB_UNKNOWN
;
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 */
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
);
1417 proto_tree_add_bitmask(mausb_tree
, tvb
, offset
, hf_mausb_flags
,
1418 ett_mausb_flags
, mausb_flag_fields
, ENC_LITTLE_ENDIAN
);
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
);
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
);
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
);
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
);
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
);
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
);
1472 /* dissect datapacket specific values */
1474 dissect_mausb_pkt_data(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1475 proto_tree
*mausb_tree
, struct mausb_header
*header
)
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
);
1483 proto_tree_add_item(mausb_tree
, hf_mausb_eps
, tvb
,
1484 offset
, 1, ENC_LITTLE_ENDIAN
);
1488 proto_tree_add_bitmask(mausb_tree
, tvb
, offset
, hf_mausb_tflags
,
1489 ett_mausb_tflags
, mausb_tflag_fields
, ENC_LITTLE_ENDIAN
);
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
);
1499 proto_tree_add_bitmask(mausb_tree
, tvb
, offset
, hf_mausb_iflags
,
1500 ett_mausb_iflags
, mausb_iflag_fields
, ENC_LITTLE_ENDIAN
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1561 /* Code to actually dissect the packets */
1563 dissect_mausb_pkt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1566 /* Set up structures needed to add the protocol subtree and manage it */
1568 proto_tree
*mausb_tree
;
1569 /* Other misc. local variables. */
1570 struct mausb_header header
;
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");
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
1594 offset
= dissect_mausb_pkt_common(tvb
, offset
, pinfo
, mausb_tree
, &header
);
1596 if (mausb_is_mgmt_pkt(&header
)) {
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 */
1633 dissect_mausb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
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.
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
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
),
1675 { &hf_mausb_flag_retry
,
1676 { "Retry", "mausb.flags.retry", FT_BOOLEAN
, 8,
1677 TFS(&tfs_yes_no
), (MAUSB_FLAG_RETRY
<< MAUSB_FLAG_OFFSET
),
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
),
1688 { &hf_mausb_flag_reserved
,
1689 { "Reserved", "mausb.flags.reserved", FT_BOOLEAN
, 8,
1690 TFS(&tfs_set_notset
), (MAUSB_FLAG_RESERVED
<< MAUSB_FLAG_OFFSET
),
1697 { "Type", "mausb.type", FT_UINT8
, BASE_HEX
,
1698 VALS(mausb_type_string
), 0, NULL
, HFILL
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
1746 { "Service Set ID", "mausb.ssid", FT_UINT8
, BASE_HEX
,
1747 NULL
, 0, NULL
, HFILL
1751 { "Status", "mausb.status", FT_UINT8
, BASE_DEC
,
1752 VALS(mausb_status_string
), 0, NULL
, HFILL
1756 /* Management Packets Only */
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
,
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 */
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
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
,
1803 { &hf_mausb_tflag_neg
,
1804 { "NEG", "mausb.tflag.neg", FT_BOOLEAN
, 8,
1805 TFS(&tfs_set_notset
), MAUSB_TFLAG_NEG
<< MAUSB_TFLAG_OFFSET
,
1809 { &hf_mausb_tflag_eot
,
1810 { "EoT", "mausb.tflag.eot", FT_BOOLEAN
, 8,
1811 TFS(&tfs_set_notset
), MAUSB_TFLAG_EOT
<< MAUSB_TFLAG_OFFSET
,
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
,
1822 { &hf_mausb_tflag_rsvd
,
1823 { "Reserved", "mausb.tflag.rsvd", FT_BOOLEAN
, 8,
1824 TFS(&tfs_set_notset
), MAUSB_TFLAG_RSVD
<< MAUSB_TFLAG_OFFSET
,
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
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
,
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
,
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
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
1881 { "Microframe Number", "mausb.uframe", FT_UINT32
, BASE_DEC
,
1882 NULL
, MAUSB_UFRAME_MASK
, NULL
, HFILL
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
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
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",
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",
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 */
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
,
1954 { &hf_mausb_cap_resp_desc_count
,
1955 { "Descriptors Count", "mausb.cap_resp.desc_count",
1957 NULL
, 0, "The total number of MA Device Capabilities descriptors",
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",
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",
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
,
1996 { &hf_mausb_dev_cap_type
,
1997 { "Type", "mausb.cap_resp.dev_cap.type",
1998 FT_UINT8
, BASE_DEC
, VALS(mausb_dev_cap_string
),
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",
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",
2022 NULL
, 0x0, NULL
, HFILL
2025 { &hf_mausb_mgmt_ep_des_num
,
2026 { "Number of Endpoint Descriptors", "mausb.ep_des_num",
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",
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
,
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
,
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
,
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
,
2151 { &hf_mausb_clear_transfers_partial
,
2152 { "Partial Delivery", "mausb.clear_transfers.partial", FT_BOOLEAN
, 6,
2153 NULL
, MAUSB_CLEAR_TRANSFERS_PARTIAL_MASK
,
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
[] = {
2201 &ett_mausb_ep_handle
,
2204 &ett_mausb_present_time
,
2205 &ett_mausb_timestamp
,
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
}
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
}
2233 { "mausb.ei.cap_resp.dev_cap.length", PI_PROTOCOL
, PI_WARN
,
2234 "Incorrect length value for this device capability descriptor",
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
);
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
2286 * indent-tabs-mode: nil
2289 * vi: set shiftwidth=4 tabstop=8 expandtab:
2290 * :indentSize=4:tabSize=8:noTabs=true: