2 * Routines for FTDI FTxxxx USB converters dissection
4 * Copyright 2019 Tomasz Mon
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/reassemble.h>
19 #include "packet-usb.h"
20 #include "packet-ftdi-ft.h"
22 static int proto_ftdi_ft
;
24 static int hf_setup_brequest
;
25 static int hf_setup_lvalue
;
26 static int hf_setup_lvalue_purge
;
27 static int hf_setup_lvalue_dtr
;
28 static int hf_setup_lvalue_rts
;
29 static int hf_setup_lvalue_xon_char
;
30 static int hf_setup_lvalue_baud_low
;
31 static int hf_setup_lvalue_data_size
;
32 static int hf_setup_lvalue_event_char
;
33 static int hf_setup_lvalue_error_char
;
34 static int hf_setup_lvalue_latency_time
;
35 static int hf_setup_lvalue_bitmask
;
36 static int hf_setup_hvalue
;
37 static int hf_setup_hvalue_dtr
;
38 static int hf_setup_hvalue_rts
;
39 static int hf_setup_hvalue_xoff_char
;
40 static int hf_setup_hvalue_baud_mid
;
41 static int hf_setup_hvalue_parity
;
42 static int hf_setup_hvalue_stop_bits
;
43 static int hf_setup_hvalue_break_bit
;
44 static int hf_setup_hvalue_trigger
;
45 static int hf_setup_hvalue_error_replacement
;
46 static int hf_setup_hvalue_bitmode
;
47 static int hf_setup_lindex
;
48 static int hf_setup_lindex_port_ab
;
49 static int hf_setup_lindex_port_abcd
;
50 static int hf_setup_lindex_baud_high
;
51 static int hf_setup_hindex
;
52 static int hf_setup_hindex_rts_cts
;
53 static int hf_setup_hindex_dtr_dsr
;
54 static int hf_setup_hindex_xon_xoff
;
55 static int hf_setup_hindex_baud_high
;
56 static int hf_setup_hindex_baud_clock_divide
;
57 static int hf_setup_wlength
;
58 static int hf_response_lat_timer
;
59 static int hf_modem_status
;
60 static int hf_modem_status_fs_max_packet
;
61 static int hf_modem_status_hs_max_packet
;
62 static int hf_modem_status_cts
;
63 static int hf_modem_status_dsr
;
64 static int hf_modem_status_ri
;
65 static int hf_modem_status_dcd
;
66 static int hf_line_status
;
67 static int hf_line_status_receive_overflow
;
68 static int hf_line_status_parity_error
;
69 static int hf_line_status_framing_error
;
70 static int hf_line_status_break_received
;
71 static int hf_line_status_tx_holding_reg_empty
;
72 static int hf_line_status_tx_empty
;
73 static int hf_if_a_rx_payload
;
74 static int hf_if_a_tx_payload
;
75 static int hf_if_b_rx_payload
;
76 static int hf_if_b_tx_payload
;
77 static int hf_if_c_rx_payload
;
78 static int hf_if_c_tx_payload
;
79 static int hf_if_d_rx_payload
;
80 static int hf_if_d_tx_payload
;
81 static int hf_ftdi_fragments
;
82 static int hf_ftdi_fragment
;
83 static int hf_ftdi_fragment_overlap
;
84 static int hf_ftdi_fragment_overlap_conflicts
;
85 static int hf_ftdi_fragment_multiple_tails
;
86 static int hf_ftdi_fragment_too_long_fragment
;
87 static int hf_ftdi_fragment_error
;
88 static int hf_ftdi_fragment_count
;
89 static int hf_ftdi_reassembled_in
;
90 static int hf_ftdi_reassembled_length
;
92 static int ett_ftdi_ft
;
93 static int ett_modem_ctrl_lvalue
;
94 static int ett_modem_ctrl_hvalue
;
95 static int ett_flow_ctrl_hindex
;
96 static int ett_baudrate_lindex
;
97 static int ett_baudrate_hindex
;
98 static int ett_setdata_hvalue
;
99 static int ett_modem_status
;
100 static int ett_line_status
;
101 static int ett_ftdi_fragment
;
102 static int ett_ftdi_fragments
;
104 static const fragment_items ftdi_frag_items
= {
105 /* Fragment subtrees */
108 /* Fragment Fields */
111 &hf_ftdi_fragment_overlap
,
112 &hf_ftdi_fragment_overlap_conflicts
,
113 &hf_ftdi_fragment_multiple_tails
,
114 &hf_ftdi_fragment_too_long_fragment
,
115 &hf_ftdi_fragment_error
,
116 &hf_ftdi_fragment_count
,
117 /* Reassembled in field */
118 &hf_ftdi_reassembled_in
,
119 /* Reassembled length field */
120 &hf_ftdi_reassembled_length
,
121 /* Reassembled data field */
127 static dissector_handle_t ftdi_mpsse_handle
;
129 static expert_field ei_undecoded
;
131 static dissector_handle_t ftdi_ft_handle
;
133 static reassembly_table ftdi_reassembly_table
;
135 static wmem_tree_t
*request_info
;
136 static wmem_tree_t
*bitmode_info
;
137 static wmem_tree_t
*desegment_info
;
139 typedef struct _request_data
{
141 uint32_t device_address
;
147 typedef struct _bitmode_data
{
149 uint32_t device_address
;
150 FTDI_INTERFACE interface
;
154 typedef struct _desegment_data desegment_data_t
;
155 struct _desegment_data
{
157 uint32_t device_address
;
158 FTDI_INTERFACE interface
;
161 /* First frame where the segmented data starts (reassembly key) */
162 uint32_t first_frame
;
164 int first_frame_offset
;
165 /* Points to desegment data if the previous desegment data ends
166 * in last_frame that is equal to this desegment data first_frame.
168 desegment_data_t
*previous
;
171 typedef struct _ftdi_fragment_key
{
173 uint32_t device_address
;
174 FTDI_INTERFACE interface
;
178 } ftdi_fragment_key_t
;
180 #define REQUEST_RESET 0x00
181 #define REQUEST_MODEM_CTRL 0x01
182 #define REQUEST_SET_FLOW_CTRL 0x02
183 #define REQUEST_SET_BAUD_RATE 0x03
184 #define REQUEST_SET_DATA 0x04
185 #define REQUEST_GET_MODEM_STAT 0x05
186 #define REQUEST_SET_EVENT_CHAR 0x06
187 #define REQUEST_SET_ERROR_CHAR 0x07
188 #define REQUEST_SET_LAT_TIMER 0x09
189 #define REQUEST_GET_LAT_TIMER 0x0A
190 #define REQUEST_SET_BITMODE 0x0B
192 static const value_string request_vals
[] = {
193 {REQUEST_RESET
, "Reset"},
194 {REQUEST_MODEM_CTRL
, "ModemCtrl"},
195 {REQUEST_SET_FLOW_CTRL
, "SetFlowCtrl"},
196 {REQUEST_SET_BAUD_RATE
, "SetBaudRate"},
197 {REQUEST_SET_DATA
, "SetData"},
198 {REQUEST_GET_MODEM_STAT
, "GetModemStat"},
199 {REQUEST_SET_EVENT_CHAR
, "SetEventChar"},
200 {REQUEST_SET_ERROR_CHAR
, "SetErrorChar"},
201 {REQUEST_SET_LAT_TIMER
, "SetLatTimer"},
202 {REQUEST_GET_LAT_TIMER
, "GetLatTimer"},
203 {REQUEST_SET_BITMODE
, "SetBitMode"},
206 static value_string_ext request_vals_ext
= VALUE_STRING_EXT_INIT(request_vals
);
208 static const value_string reset_purge_vals
[] = {
209 {0x00, "Purge RX and TX"},
215 static const value_string index_port_ab_vals
[] = {
222 static const value_string index_port_abcd_vals
[] = {
231 static const value_string data_size_vals
[] = {
232 {0x07, "7 bit data"},
233 {0x08, "8 bit data"},
237 static const value_string parity_vals
[] = {
246 static const value_string stop_bits_vals
[] = {
252 static const value_string break_bit_vals
[] = {
258 static const value_string event_char_trigger_vals
[] = {
259 {0x00, "No trigger"},
260 {0x01, "Trigger IN on Event Char"},
264 static const value_string error_replacement_vals
[] = {
265 {0x00, "No Error Replacement"},
266 {0x01, "Error Replacement On"},
270 #define BITMODE_RESET 0x00
271 #define BITMODE_BITBANG 0x01
272 #define BITMODE_MPSSE 0x02
273 #define BITMODE_SYNCBB 0x04
274 #define BITMODE_MCU 0x08
275 #define BITMODE_OPTO 0x10
276 #define BITMODE_CBUS 0x20
277 #define BITMODE_SYNCFF 0x40
278 #define BITMODE_FT1284 0x80
281 static const value_string bitmode_vals
[] = {
282 {BITMODE_RESET
, "switch off bitbang mode, back to regular serial / FIFO"},
283 {BITMODE_BITBANG
, "classical asynchronous bitbang mode, introduced with B-type chips"},
284 {BITMODE_MPSSE
, "MPSSE mode, available on 2232x chips"},
285 {BITMODE_SYNCBB
, "synchronous bitbang mode, available on 2232x and R-type chips"},
286 {BITMODE_MCU
, "MCU Host Bus Emulation mode, available on 2232x chips"},
287 {BITMODE_OPTO
, "Fast Opto-Isolated Serial Interface Mode, available on 2232x chips"},
288 {BITMODE_CBUS
, "Bitbang on CBUS pins of R-type chips, configure in EEPROM before"},
289 {BITMODE_SYNCFF
, "Single Channel Synchronous FIFO mode, available on 2232H chips"},
290 {BITMODE_FT1284
, "FT1284 mode, available on 232H chips"},
294 #define MODEM_STATUS_BIT_FS_64_MAX_PACKET (1 << 0)
295 #define MODEM_STATUS_BIT_HS_512_MAX_PACKET (1 << 1)
297 void proto_register_ftdi_ft(void);
298 void proto_reg_handoff_ftdi_ft(void);
300 /* It is assumed that this function is called only when the device is known
301 * to be FTDI FT chip and thus the VID and PID is not checked here.
302 * This function determines chip based on bcdDevice version which cannot be
303 * altered by the hardware vendor.
306 identify_chip(usb_conv_info_t
*usb_conv_info
)
308 if (usb_conv_info
== NULL
)
310 return FTDI_CHIP_UNKNOWN
;
313 switch (usb_conv_info
->deviceVersion
)
316 if (usb_conv_info
->iSerialNumber
)
318 /* Serial number enabled - it is FT8U232AM */
319 return FTDI_CHIP_FT8U232AM
;
321 /* No serial number - FT232B without (or with blank) EEPROM fitted */
322 return FTDI_CHIP_FT232B
;
324 return FTDI_CHIP_FT232B
;
326 return FTDI_CHIP_FT2232D
;
328 return FTDI_CHIP_FT232R
;
330 return FTDI_CHIP_FT2232H
;
332 return FTDI_CHIP_FT4232H
;
334 return FTDI_CHIP_FT232H
;
336 return FTDI_CHIP_X_SERIES
;
338 return FTDI_CHIP_UNKNOWN
;
342 static FTDI_INTERFACE
343 endpoint_to_interface(urb_info_t
*urb
)
345 switch (urb
->endpoint
)
347 case 0x81: /* A IN */
348 case 0x02: /* A OUT */
349 return FTDI_INTERFACE_A
;
350 case 0x83: /* B IN */
351 case 0x04: /* B OUT */
352 return FTDI_INTERFACE_B
;
353 case 0x85: /* C IN */
354 case 0x06: /* C OUT */
355 return FTDI_INTERFACE_C
;
356 case 0x87: /* D IN */
357 case 0x08: /* D OUT */
358 return FTDI_INTERFACE_D
;
360 return FTDI_INTERFACE_UNKNOWN
;
364 static FTDI_INTERFACE
365 lindex_to_interface(uint8_t lindex
)
369 case 0: /* ANY, default to A */
371 return FTDI_INTERFACE_A
;
373 return FTDI_INTERFACE_B
;
375 return FTDI_INTERFACE_C
;
377 return FTDI_INTERFACE_D
;
379 return FTDI_INTERFACE_UNKNOWN
;
384 dissect_request_reset(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
386 int offset_start
= offset
;
388 proto_tree_add_item(tree
, hf_setup_lvalue_purge
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
391 proto_tree_add_item(tree
, hf_setup_hvalue
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
394 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
397 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
400 return offset
- offset_start
;
404 dissect_request_modem_ctrl(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
406 static int * const lvalue_bits
[] = {
407 &hf_setup_lvalue_dtr
,
408 &hf_setup_lvalue_rts
,
411 static int * const hvalue_bits
[] = {
412 &hf_setup_hvalue_dtr
,
413 &hf_setup_hvalue_rts
,
416 int offset_start
= offset
;
418 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_lvalue
,
419 ett_modem_ctrl_lvalue
, lvalue_bits
, ENC_LITTLE_ENDIAN
);
422 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_hvalue
,
423 ett_modem_ctrl_hvalue
, hvalue_bits
, ENC_LITTLE_ENDIAN
);
426 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
429 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
432 return offset
- offset_start
;
436 dissect_request_set_flow_ctrl(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
438 static int * const hindex_bits
[] = {
439 &hf_setup_hindex_rts_cts
,
440 &hf_setup_hindex_dtr_dsr
,
441 &hf_setup_hindex_xon_xoff
,
444 int offset_start
= offset
;
446 proto_tree_add_item(tree
, hf_setup_lvalue_xon_char
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
449 proto_tree_add_item(tree
, hf_setup_hvalue_xoff_char
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
452 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
455 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_hindex
,
456 ett_flow_ctrl_hindex
, hindex_bits
, ENC_LITTLE_ENDIAN
);
459 return offset
- offset_start
;
463 dissect_request_set_baud_rate(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
, FTDI_CHIP chip
)
465 static int * const lindex_bits
[] = {
466 &hf_setup_lindex_baud_high
,
469 static int * const hindex_bits
[] = {
470 &hf_setup_hindex_baud_high
,
473 static int * const hindex_bits_hispeed
[] = {
474 &hf_setup_hindex_baud_high
,
475 &hf_setup_hindex_baud_clock_divide
,
479 int offset_start
= offset
;
481 proto_tree_add_item(tree
, hf_setup_lvalue_baud_low
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
484 proto_tree_add_item(tree
, hf_setup_hvalue_baud_mid
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
489 case FTDI_CHIP_FT8U232AM
:
490 proto_tree_add_item(tree
, hf_setup_lindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
493 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
496 case FTDI_CHIP_FT232B
:
497 case FTDI_CHIP_FT232R
:
498 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_lindex
,
499 ett_baudrate_lindex
, lindex_bits
, ENC_LITTLE_ENDIAN
);
502 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
505 case FTDI_CHIP_FT2232D
:
506 case FTDI_CHIP_X_SERIES
:
507 proto_tree_add_item(tree
, hf_setup_lindex_port_ab
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
510 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_hindex
,
511 ett_baudrate_hindex
, hindex_bits
, ENC_LITTLE_ENDIAN
);
514 case FTDI_CHIP_FT2232H
:
515 case FTDI_CHIP_FT4232H
:
516 case FTDI_CHIP_FT232H
:
517 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
520 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_hindex
,
521 ett_baudrate_hindex
, hindex_bits_hispeed
, ENC_LITTLE_ENDIAN
);
524 case FTDI_CHIP_UNKNOWN
:
526 proto_tree_add_expert(tree
, pinfo
, &ei_undecoded
, tvb
, offset
, 2);
530 return offset
- offset_start
;
534 dissect_request_set_data(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
536 static int * const hvalue_bits
[] = {
537 &hf_setup_hvalue_parity
,
538 &hf_setup_hvalue_stop_bits
,
539 &hf_setup_hvalue_break_bit
,
542 int offset_start
= offset
;
544 proto_tree_add_item(tree
, hf_setup_lvalue_data_size
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
547 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_setup_hvalue
,
548 ett_setdata_hvalue
, hvalue_bits
, ENC_LITTLE_ENDIAN
);
551 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
554 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
557 return offset
- offset_start
;
561 dissect_request_get_modem_stat(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
563 int offset_start
= offset
;
565 proto_tree_add_item(tree
, hf_setup_lvalue
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
568 proto_tree_add_item(tree
, hf_setup_hvalue
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
571 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
574 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
577 return offset
- offset_start
;
581 dissect_request_set_event_char(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
583 int offset_start
= offset
;
585 proto_tree_add_item(tree
, hf_setup_lvalue_event_char
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
588 proto_tree_add_item(tree
, hf_setup_hvalue_trigger
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
591 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
594 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
597 return offset
- offset_start
;
601 dissect_request_set_error_char(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
603 int offset_start
= offset
;
605 proto_tree_add_item(tree
, hf_setup_lvalue_error_char
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
608 proto_tree_add_item(tree
, hf_setup_hvalue_error_replacement
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
611 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
614 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
618 return offset
- offset_start
;
622 dissect_request_set_lat_timer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
624 int offset_start
= offset
;
626 proto_tree_add_item(tree
, hf_setup_lvalue_latency_time
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
629 proto_tree_add_item(tree
, hf_setup_hvalue
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
632 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
635 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
638 return offset
- offset_start
;
642 dissect_request_get_lat_timer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
644 int offset_start
= offset
;
646 proto_tree_add_item(tree
, hf_setup_lvalue
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
649 proto_tree_add_item(tree
, hf_setup_hvalue
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
652 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
655 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
658 return offset
- offset_start
;
662 dissect_response_get_lat_timer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
664 int offset_start
= offset
;
666 proto_tree_add_item(tree
, hf_response_lat_timer
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
669 return offset
- offset_start
;
673 dissect_request_set_bitmode(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
)
675 int offset_start
= offset
;
677 proto_tree_add_item(tree
, hf_setup_lvalue_bitmask
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
680 proto_tree_add_item(tree
, hf_setup_hvalue_bitmode
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
683 proto_tree_add_item(tree
, hf_setup_lindex_port_abcd
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
686 proto_tree_add_item(tree
, hf_setup_hindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
689 return offset
- offset_start
;
693 dissect_modem_status_bytes(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
, int *out_rx_len
)
695 static int * const modem_status_bits
[] = {
696 &hf_modem_status_fs_max_packet
,
697 &hf_modem_status_hs_max_packet
,
698 &hf_modem_status_cts
,
699 &hf_modem_status_dsr
,
701 &hf_modem_status_dcd
,
704 static int * const line_status_bits
[] = {
705 &hf_line_status_receive_overflow
,
706 &hf_line_status_parity_error
,
707 &hf_line_status_framing_error
,
708 &hf_line_status_break_received
,
709 &hf_line_status_tx_holding_reg_empty
,
710 &hf_line_status_tx_empty
,
713 uint64_t modem_status
;
715 proto_tree_add_bitmask_ret_uint64(tree
, tvb
, offset
, hf_modem_status
,
716 ett_modem_status
, modem_status_bits
, ENC_LITTLE_ENDIAN
, &modem_status
);
719 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_line_status
,
720 ett_line_status
, line_status_bits
, ENC_LITTLE_ENDIAN
);
725 *out_rx_len
= tvb_reported_length_remaining(tvb
, offset
);
726 if (modem_status
& MODEM_STATUS_BIT_FS_64_MAX_PACKET
)
728 /* 2 bytes modem status, 62 bytes payload */
729 *out_rx_len
= MIN(*out_rx_len
, 62);
731 else if (modem_status
& MODEM_STATUS_BIT_HS_512_MAX_PACKET
)
733 /* 2 bytes modem status, 510 bytes payload */
734 *out_rx_len
= MIN(*out_rx_len
, 510);
742 record_interface_mode(packet_info
*pinfo
, urb_info_t
*urb
, FTDI_INTERFACE interface
, uint8_t bitmode
)
744 uint32_t k_bus_id
= urb
->bus_id
;
745 uint32_t k_device_address
= urb
->device_address
;
746 uint32_t k_interface
= (uint32_t)interface
;
747 wmem_tree_key_t key
[] = {
749 {1, &k_device_address
},
754 bitmode_data_t
*bitmode_data
= NULL
;
756 bitmode_data
= wmem_new(wmem_file_scope(), bitmode_data_t
);
757 bitmode_data
->bus_id
= urb
->bus_id
;
758 bitmode_data
->device_address
= urb
->device_address
;
759 bitmode_data
->interface
= interface
;
760 bitmode_data
->bitmode
= bitmode
;
761 wmem_tree_insert32_array(bitmode_info
, key
, bitmode_data
);
765 get_recorded_interface_mode(packet_info
*pinfo
, urb_info_t
*urb
, FTDI_INTERFACE interface
)
767 uint32_t k_bus_id
= urb
->bus_id
;
768 uint32_t k_device_address
= urb
->device_address
;
769 uint32_t k_interface
= (uint32_t)interface
;
770 wmem_tree_key_t key
[] = {
772 {1, &k_device_address
},
778 bitmode_data_t
*bitmode_data
= NULL
;
779 bitmode_data
= (bitmode_data_t
*)wmem_tree_lookup32_array_le(bitmode_info
, key
);
780 if (bitmode_data
&& bitmode_data
->bus_id
== k_bus_id
&& bitmode_data
->device_address
== k_device_address
&&
781 bitmode_data
->interface
== interface
)
783 return bitmode_data
->bitmode
;
786 return 0; /* Default to 0, which is plain serial data */
789 static desegment_data_t
*
790 record_desegment_data(packet_info
*pinfo
, urb_info_t
*urb
,
791 FTDI_INTERFACE interface
, uint8_t bitmode
)
793 uint32_t k_bus_id
= urb
->bus_id
;
794 uint32_t k_device_address
= urb
->device_address
;
795 uint32_t k_interface
= (uint32_t)interface
;
796 uint32_t k_p2p_dir
= (uint32_t)pinfo
->p2p_dir
;
797 wmem_tree_key_t key
[] = {
799 {1, &k_device_address
},
805 desegment_data_t
*desegment_data
= NULL
;
807 desegment_data
= wmem_new(wmem_file_scope(), desegment_data_t
);
808 desegment_data
->bus_id
= urb
->bus_id
;
809 desegment_data
->device_address
= urb
->device_address
;
810 desegment_data
->interface
= interface
;
811 desegment_data
->bitmode
= bitmode
;
812 desegment_data
->p2p_dir
= pinfo
->p2p_dir
;
813 desegment_data
->first_frame
= pinfo
->num
;
814 /* Last frame is currently unknown */
815 desegment_data
->last_frame
= 0;
816 desegment_data
->first_frame_offset
= 0;
817 desegment_data
->previous
= NULL
;
819 wmem_tree_insert32_array(desegment_info
, key
, desegment_data
);
820 return desegment_data
;
823 static desegment_data_t
*
824 get_recorded_desegment_data(packet_info
*pinfo
, urb_info_t
*urb
,
825 FTDI_INTERFACE interface
, uint8_t bitmode
)
827 uint32_t k_bus_id
= urb
->bus_id
;
828 uint32_t k_device_address
= urb
->device_address
;
829 uint32_t k_interface
= (uint32_t)interface
;
830 uint32_t k_p2p_dir
= (uint32_t)pinfo
->p2p_dir
;
831 wmem_tree_key_t key
[] = {
833 {1, &k_device_address
},
840 desegment_data_t
*desegment_data
= NULL
;
841 desegment_data
= (desegment_data_t
*)wmem_tree_lookup32_array_le(desegment_info
, key
);
842 if (desegment_data
&& desegment_data
->bus_id
== k_bus_id
&& desegment_data
->device_address
== k_device_address
&&
843 desegment_data
->interface
== interface
&& desegment_data
->bitmode
== bitmode
&&
844 desegment_data
->p2p_dir
== pinfo
->p2p_dir
)
846 /* Return desegment data only if it is relevant to current packet */
847 if ((desegment_data
->last_frame
== 0) || (desegment_data
->last_frame
>= pinfo
->num
))
849 return desegment_data
;
856 static unsigned ftdi_fragment_key_hash(const void *k
)
858 const ftdi_fragment_key_t
*key
= (const ftdi_fragment_key_t
*)k
;
862 static int ftdi_fragment_key_equal(const void *k1
, const void *k2
)
864 const ftdi_fragment_key_t
*key1
= (const ftdi_fragment_key_t
*)k1
;
865 const ftdi_fragment_key_t
*key2
= (const ftdi_fragment_key_t
*)k2
;
867 /* id is most likely to differ and thus should be checked first */
868 return (key1
->id
== key2
->id
) &&
869 (key1
->bus_id
== key2
->bus_id
) &&
870 (key1
->device_address
== key2
->device_address
) &&
871 (key1
->interface
== key2
->interface
) &&
872 (key1
->bitmode
== key2
->bitmode
) &&
873 (key1
->p2p_dir
== key2
->p2p_dir
);
876 static void *ftdi_fragment_key(const packet_info
*pinfo _U_
, const uint32_t id
, const void *data
)
878 desegment_data_t
*desegment_data
= (desegment_data_t
*)data
;
879 ftdi_fragment_key_t
*key
= g_slice_new(ftdi_fragment_key_t
);
881 key
->bus_id
= desegment_data
->bus_id
;
882 key
->device_address
= desegment_data
->device_address
;
883 key
->interface
= desegment_data
->interface
;
884 key
->bitmode
= desegment_data
->bitmode
;
885 key
->p2p_dir
= desegment_data
->p2p_dir
;
891 static void ftdi_fragment_free_key(void *ptr
)
893 ftdi_fragment_key_t
*key
= (ftdi_fragment_key_t
*)ptr
;
894 g_slice_free(ftdi_fragment_key_t
, key
);
897 static const reassembly_table_functions ftdi_reassembly_table_functions
= {
898 .hash_func
= ftdi_fragment_key_hash
,
899 .equal_func
= ftdi_fragment_key_equal
,
900 .temporary_key_func
= ftdi_fragment_key
,
901 .persistent_key_func
= ftdi_fragment_key
,
902 .free_temporary_key_func
= ftdi_fragment_free_key
,
903 .free_persistent_key_func
= ftdi_fragment_free_key
,
907 dissect_payload(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, urb_info_t
*urb
,
908 FTDI_INTERFACE interface
, uint8_t bitmode
)
911 uint32_t k_device_address
;
913 k_bus_id
= urb
->bus_id
;
914 k_device_address
= urb
->device_address
;
916 if (tvb
&& ((bitmode
== BITMODE_MPSSE
) || (bitmode
== BITMODE_MCU
)))
918 ftdi_mpsse_info_t mpsse_info
= {
920 .device_address
= k_device_address
,
921 .chip
= identify_chip(urb
->conv
),
923 .mcu_mode
= (bitmode
== BITMODE_MCU
),
925 call_dissector_with_data(ftdi_mpsse_handle
, tvb
, pinfo
, tree
, &mpsse_info
);
930 dissect_serial_payload(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, proto_tree
*ftdi_tree
,
931 urb_info_t
*urb
, FTDI_INTERFACE interface
)
933 uint16_t save_can_desegment
;
934 int save_desegment_offset
;
935 uint32_t save_desegment_len
;
936 desegment_data_t
*desegment_data
;
939 save_can_desegment
= pinfo
->can_desegment
;
940 save_desegment_offset
= pinfo
->desegment_offset
;
941 save_desegment_len
= pinfo
->desegment_len
;
943 bytes
= tvb_reported_length(tvb
);
946 tvbuff_t
*payload_tvb
= NULL
;
947 uint32_t reassembled_bytes
= 0;
949 uint8_t curr_layer_num
= pinfo
->curr_layer_num
;
951 bitmode
= get_recorded_interface_mode(pinfo
, urb
, interface
);
953 pinfo
->can_desegment
= 2;
954 pinfo
->desegment_offset
= 0;
955 pinfo
->desegment_len
= 0;
957 desegment_data
= get_recorded_desegment_data(pinfo
, urb
, interface
, bitmode
);
960 fragment_head
*fd_head
;
961 desegment_data_t
*next_desegment_data
= NULL
;
963 if ((desegment_data
->previous
) && (desegment_data
->first_frame
== pinfo
->num
))
965 DISSECTOR_ASSERT(desegment_data
->previous
->last_frame
== pinfo
->num
);
967 next_desegment_data
= desegment_data
;
968 desegment_data
= desegment_data
->previous
;
971 if (!PINFO_FD_VISITED(pinfo
))
973 /* Combine data reassembled so far with current tvb and check if this is last fragment or not */
975 fd_head
= fragment_get(&ftdi_reassembly_table
, pinfo
, desegment_data
->first_frame
, desegment_data
);
976 DISSECTOR_ASSERT(fd_head
&& !(fd_head
->flags
& FD_DEFRAGMENTED
) && fd_head
->next
);
977 payload_tvb
= tvb_new_composite();
978 for (item
= fd_head
->next
; item
; item
= item
->next
)
980 DISSECTOR_ASSERT(reassembled_bytes
== item
->offset
);
981 tvb_composite_append(payload_tvb
, item
->tvb_data
);
982 reassembled_bytes
+= item
->len
;
984 tvb_composite_append(payload_tvb
, tvb
);
985 tvb_composite_finalize(payload_tvb
);
989 fd_head
= fragment_get_reassembled_id(&ftdi_reassembly_table
, pinfo
, desegment_data
->first_frame
);
990 payload_tvb
= process_reassembled_data(tvb
, 0, pinfo
, "Reassembled", fd_head
,
991 &ftdi_frag_items
, NULL
, ftdi_tree
);
994 if (next_desegment_data
)
996 fragment_head
*next_head
;
997 next_head
= fragment_get_reassembled_id(&ftdi_reassembly_table
, pinfo
, next_desegment_data
->first_frame
);
998 process_reassembled_data(tvb
, 0, pinfo
, "Reassembled", next_head
, &ftdi_frag_items
, NULL
, ftdi_tree
);
1001 if ((desegment_data
->first_frame
== pinfo
->num
) && (desegment_data
->first_frame_offset
> 0))
1003 payload_tvb
= tvb_new_subset_length(tvb
, 0, desegment_data
->first_frame_offset
);
1008 /* Packet is not part of reassembly sequence, simply use it without modifications */
1012 dissect_payload(payload_tvb
, pinfo
, tree
, urb
, interface
, bitmode
);
1014 if (!PINFO_FD_VISITED(pinfo
))
1016 /* FTDI FT dissector doesn't know if the last fragment is really the last one unless it passes
1017 * the data to the next dissector. There is absolutely no metadata that could help with it as
1018 * FTDI FT is pretty much a direct replacement to UART (COM port) and is pretty much transparent
1019 * to the actual serial protocol used.
1021 * Passing the data to next dissector results in curr_layer_num being increased if it dissected
1022 * the data (when it is the last fragment). This would prevent the process_reassembled_data()
1023 * (after the first pass) from returning the reassembled tvb in FTFI FT which in turn prevents
1024 * the data from being passed to the next dissector.
1026 * Override pinfo->curr_layer_num value when the fragments are being added to reassembly table.
1027 * This is ugly hack. Is there any better approach?
1029 * There doesn't seem to be a mechanism to "back-track" just added fragments to reassembly table,
1030 * or any way to "shorten" the last added fragment. The most problematic case is when current
1031 * packet is both last packet for previous reassembly and a first packet for next reassembly.
1033 uint8_t save_curr_layer_num
= pinfo
->curr_layer_num
;
1034 pinfo
->curr_layer_num
= curr_layer_num
;
1036 if (!pinfo
->desegment_len
)
1040 /* Current tvb is really the last fragment */
1041 fragment_add_check(&ftdi_reassembly_table
, tvb
, 0, pinfo
, desegment_data
->first_frame
,
1042 desegment_data
, reassembled_bytes
, bytes
, false);
1043 desegment_data
->last_frame
= pinfo
->num
;
1048 DISSECTOR_ASSERT_HINT(pinfo
->desegment_len
== DESEGMENT_ONE_MORE_SEGMENT
,
1049 "FTDI FT supports only DESEGMENT_ONE_MORE_SEGMENT");
1050 if (!desegment_data
)
1052 /* Start desegmenting */
1053 int fragment_length
= tvb_reported_length_remaining(tvb
, pinfo
->desegment_offset
);
1054 desegment_data
= record_desegment_data(pinfo
, urb
, interface
, bitmode
);
1055 desegment_data
->first_frame_offset
= pinfo
->desegment_offset
;
1056 fragment_add_check(&ftdi_reassembly_table
, tvb
, pinfo
->desegment_offset
, pinfo
,
1057 desegment_data
->first_frame
, desegment_data
, 0, fragment_length
, true);
1059 else if (pinfo
->desegment_offset
== 0)
1061 /* Continue reassembling */
1062 fragment_add_check(&ftdi_reassembly_table
, tvb
, 0, pinfo
, desegment_data
->first_frame
,
1063 desegment_data
, reassembled_bytes
, bytes
, true);
1067 int fragment_length
;
1069 desegment_data_t
*previous_desegment_data
;
1071 /* This packet contains both an end from a previous reassembly and start of a new one */
1072 DISSECTOR_ASSERT((uint32_t)pinfo
->desegment_offset
> reassembled_bytes
);
1073 previous_bytes
= pinfo
->desegment_offset
- reassembled_bytes
;
1074 fragment_add_check(&ftdi_reassembly_table
, tvb
, 0, pinfo
, desegment_data
->first_frame
,
1075 desegment_data
, reassembled_bytes
, previous_bytes
, false);
1076 desegment_data
->last_frame
= pinfo
->num
;
1078 previous_desegment_data
= desegment_data
;
1079 fragment_length
= bytes
- previous_bytes
;
1080 desegment_data
= record_desegment_data(pinfo
, urb
, interface
, bitmode
);
1081 desegment_data
->first_frame_offset
= previous_bytes
;
1082 desegment_data
->previous
= previous_desegment_data
;
1083 fragment_add_check(&ftdi_reassembly_table
, tvb
, previous_bytes
, pinfo
, desegment_data
->first_frame
,
1084 desegment_data
, 0, fragment_length
, true);
1088 pinfo
->curr_layer_num
= save_curr_layer_num
;
1092 pinfo
->can_desegment
= save_can_desegment
;
1093 pinfo
->desegment_offset
= save_desegment_offset
;
1094 pinfo
->desegment_len
= save_desegment_len
;
1100 dissect_ftdi_ft(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
1102 proto_item
*main_item
;
1103 proto_tree
*main_tree
;
1105 urb_info_t
*urb
= (urb_info_t
*)data
;
1106 request_data_t
*request_data
= NULL
;
1107 wmem_tree_key_t key
[4];
1109 uint32_t k_device_address
;
1118 /* This dissector can only process device Vendor specific setup data */
1119 if ((USB_TYPE(urb
->setup_requesttype
) != RQT_SETUP_TYPE_VENDOR
) ||
1120 (USB_RECIPIENT(urb
->setup_requesttype
) != RQT_SETUP_RECIPIENT_DEVICE
))
1126 k_bus_id
= urb
->bus_id
;
1127 k_device_address
= urb
->device_address
;
1130 key
[0].key
= &k_bus_id
;
1132 key
[1].key
= &k_device_address
;
1134 key
[2].key
= &pinfo
->num
;
1138 main_item
= proto_tree_add_item(tree
, proto_ftdi_ft
, tvb
, offset
, -1, ENC_NA
);
1139 main_tree
= proto_item_add_subtree(main_item
, ett_ftdi_ft
);
1141 if (urb
->transfer_type
== URB_CONTROL
)
1143 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FTDI FT");
1144 col_set_str(pinfo
->cinfo
, COL_INFO
, "FTDI FT ");
1145 col_append_str(pinfo
->cinfo
, COL_INFO
, urb
->is_request
? "Request" : "Response");
1149 int bytes_dissected
;
1154 brequest
= tvb_get_uint8(tvb
, offset
);
1155 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s",
1156 val_to_str_ext_const(brequest
, &request_vals_ext
, "Unknown"));
1157 proto_tree_add_item(main_tree
, hf_setup_brequest
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1160 hvalue
= tvb_get_uint8(tvb
, offset
+ 1);
1161 lindex
= tvb_get_uint8(tvb
, offset
+ 2);
1166 bytes_dissected
= dissect_request_reset(tvb
, pinfo
, offset
, main_tree
);
1168 case REQUEST_MODEM_CTRL
:
1169 bytes_dissected
= dissect_request_modem_ctrl(tvb
, pinfo
, offset
, main_tree
);
1171 case REQUEST_SET_FLOW_CTRL
:
1172 bytes_dissected
= dissect_request_set_flow_ctrl(tvb
, pinfo
, offset
, main_tree
);
1174 case REQUEST_SET_BAUD_RATE
:
1176 FTDI_CHIP chip
= identify_chip(urb
->conv
);
1177 bytes_dissected
= dissect_request_set_baud_rate(tvb
, pinfo
, offset
, main_tree
, chip
);
1180 case REQUEST_SET_DATA
:
1181 bytes_dissected
= dissect_request_set_data(tvb
, pinfo
, offset
, main_tree
);
1183 case REQUEST_GET_MODEM_STAT
:
1184 bytes_dissected
= dissect_request_get_modem_stat(tvb
, pinfo
, offset
, main_tree
);
1186 case REQUEST_SET_EVENT_CHAR
:
1187 bytes_dissected
= dissect_request_set_event_char(tvb
, pinfo
, offset
, main_tree
);
1189 case REQUEST_SET_ERROR_CHAR
:
1190 bytes_dissected
= dissect_request_set_error_char(tvb
, pinfo
, offset
, main_tree
);
1192 case REQUEST_SET_LAT_TIMER
:
1193 bytes_dissected
= dissect_request_set_lat_timer(tvb
, pinfo
, offset
, main_tree
);
1195 case REQUEST_GET_LAT_TIMER
:
1196 bytes_dissected
= dissect_request_get_lat_timer(tvb
, pinfo
, offset
, main_tree
);
1198 case REQUEST_SET_BITMODE
:
1199 bytes_dissected
= dissect_request_set_bitmode(tvb
, pinfo
, offset
, main_tree
);
1202 bytes_dissected
= 0;
1206 offset
+= bytes_dissected
;
1207 if (bytes_dissected
< 4)
1209 proto_tree_add_expert(main_tree
, pinfo
, &ei_undecoded
, tvb
, offset
, 4 - bytes_dissected
);
1210 offset
+= 4 - bytes_dissected
;
1213 proto_tree_add_item(main_tree
, hf_setup_wlength
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1216 /* Record the request type so we can find it when dissecting response */
1217 request_data
= wmem_new(wmem_file_scope(), request_data_t
);
1218 request_data
->bus_id
= urb
->bus_id
;
1219 request_data
->device_address
= urb
->device_address
;
1220 request_data
->request
= brequest
;
1221 request_data
->hvalue
= hvalue
;
1222 request_data
->lindex
= lindex
;
1223 wmem_tree_insert32_array(request_info
, key
, request_data
);
1227 /* Retrieve request type */
1228 request_data
= (request_data_t
*)wmem_tree_lookup32_array_le(request_info
, key
);
1229 if (request_data
&& request_data
->bus_id
== k_bus_id
&& request_data
->device_address
== k_device_address
)
1231 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s",
1232 val_to_str_ext_const(request_data
->request
, &request_vals_ext
, "Unknown"));
1234 switch (request_data
->request
)
1236 case REQUEST_GET_MODEM_STAT
:
1237 offset
+= dissect_modem_status_bytes(tvb
, pinfo
, offset
, main_tree
, NULL
);
1239 case REQUEST_GET_LAT_TIMER
:
1240 offset
+= dissect_response_get_lat_timer(tvb
, pinfo
, offset
, main_tree
);
1242 case REQUEST_SET_BITMODE
:
1243 /* TODO: Record interface mode only if the control request has succeeded */
1244 record_interface_mode(pinfo
, urb
, lindex_to_interface(request_data
->lindex
), request_data
->hvalue
);
1252 col_append_str(pinfo
->cinfo
, COL_INFO
, ": Unknown");
1255 /* Report any potentially undissected response data */
1256 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
1258 proto_tree_add_expert(main_tree
, pinfo
, &ei_undecoded
, tvb
, offset
, -1);
1264 const char *interface_str
;
1265 FTDI_INTERFACE interface
;
1268 interface
= endpoint_to_interface(urb
);
1271 case FTDI_INTERFACE_A
:
1272 interface_str
= "A";
1273 rx_hf
= hf_if_a_rx_payload
;
1274 tx_hf
= hf_if_a_tx_payload
;
1276 case FTDI_INTERFACE_B
:
1277 interface_str
= "B";
1278 rx_hf
= hf_if_b_rx_payload
;
1279 tx_hf
= hf_if_b_tx_payload
;
1281 case FTDI_INTERFACE_C
:
1282 interface_str
= "C";
1283 rx_hf
= hf_if_c_rx_payload
;
1284 tx_hf
= hf_if_c_tx_payload
;
1286 case FTDI_INTERFACE_D
:
1287 interface_str
= "D";
1288 rx_hf
= hf_if_d_rx_payload
;
1289 tx_hf
= hf_if_d_tx_payload
;
1295 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FTDI FT");
1296 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
1298 int total_rx_len
= 0;
1300 tvbuff_t
*rx_tvb
= tvb_new_composite();
1302 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "INTERFACE %s RX", interface_str
);
1306 /* First two bytes are status */
1307 offset
+= dissect_modem_status_bytes(tvb
, pinfo
, offset
, main_tree
, &rx_len
);
1308 total_rx_len
+= rx_len
;
1312 tvbuff_t
*rx_tvb_fragment
= tvb_new_subset_length(tvb
, offset
, rx_len
);
1313 tvb_composite_append(rx_tvb
, rx_tvb_fragment
);
1314 proto_tree_add_item(main_tree
, rx_hf
, tvb
, offset
, rx_len
, ENC_NA
);
1318 while (tvb_reported_length_remaining(tvb
, offset
) > 0);
1320 if (total_rx_len
> 0)
1322 tvb_composite_finalize(rx_tvb
);
1323 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %d bytes", total_rx_len
);
1324 add_new_data_source(pinfo
, rx_tvb
, "RX Payload");
1325 dissect_serial_payload(rx_tvb
, pinfo
, tree
, main_tree
, urb
, interface
);
1329 tvb_free_chain(rx_tvb
);
1336 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "INTERFACE %s TX", interface_str
);
1337 bytes
= tvb_reported_length_remaining(tvb
, offset
);
1343 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %d bytes", bytes
);
1344 proto_tree_add_item(main_tree
, tx_hf
, tvb
, offset
, bytes
, ENC_NA
);
1346 tx_tvb
= tvb_new_subset_length(tvb
, offset
, bytes
);
1347 add_new_data_source(pinfo
, tx_tvb
, "TX Payload");
1348 dissect_serial_payload(tx_tvb
, pinfo
, tree
, main_tree
, urb
, interface
);
1358 proto_register_ftdi_ft(void)
1360 expert_module_t
*expert_module
;
1362 static hf_register_info hf
[] = {
1363 { &hf_setup_brequest
,
1364 { "Request", "ftdi-ft.bRequest",
1365 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
, &request_vals_ext
, 0x0,
1369 { "lValue", "ftdi-ft.lValue",
1370 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1373 { &hf_setup_lvalue_purge
,
1374 { "lValue", "ftdi-ft.lValue",
1375 FT_UINT8
, BASE_HEX
, VALS(reset_purge_vals
), 0x0,
1378 { &hf_setup_lvalue_dtr
,
1379 { "DTR Active", "ftdi-ft.lValue.b0",
1380 FT_BOOLEAN
, 8, NULL
, (1 << 0),
1383 { &hf_setup_lvalue_rts
,
1384 { "RTS Active", "ftdi-ft.lValue.b1",
1385 FT_BOOLEAN
, 8, NULL
, (1 << 1),
1388 { &hf_setup_lvalue_xon_char
,
1389 { "XON Char", "ftdi-ft.lValue",
1390 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1393 { &hf_setup_lvalue_baud_low
,
1394 { "Baud low", "ftdi-ft.lValue",
1395 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1398 { &hf_setup_lvalue_data_size
,
1399 { "Data Size", "ftdi-ft.lValue",
1400 FT_UINT8
, BASE_HEX
, VALS(data_size_vals
), 0x0,
1403 { &hf_setup_lvalue_event_char
,
1404 { "Event Char", "ftdi-ft.lValue",
1405 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1408 { &hf_setup_lvalue_error_char
,
1409 { "Parity Error Char", "ftdi-ft.lValue",
1410 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1413 { &hf_setup_lvalue_latency_time
,
1414 { "Latency Time", "ftdi-ft.lValue",
1415 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1416 "Latency time in milliseconds", HFILL
}
1418 { &hf_setup_lvalue_bitmask
,
1419 { "Bit Mask", "ftdi-ft.lValue",
1420 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1424 { "hValue", "ftdi-ft.hValue",
1425 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1428 { &hf_setup_hvalue_dtr
,
1429 { "en DTR for writing", "ftdi-ft.hValue.b0",
1430 FT_BOOLEAN
, 8, NULL
, (1 << 0),
1433 { &hf_setup_hvalue_rts
,
1434 { "en RTS for writing", "ftdi-ft.hValue.b1",
1435 FT_BOOLEAN
, 8, NULL
, (1 << 1),
1438 { &hf_setup_hvalue_xoff_char
,
1439 { "XOFF Char", "ftdi-ft.hValue",
1440 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1443 { &hf_setup_hvalue_baud_mid
,
1444 { "Baud mid", "ftdi-ft.hValue",
1445 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1448 { &hf_setup_hvalue_parity
,
1449 { "Parity", "ftdi-ft.hValue.parity",
1450 FT_UINT8
, BASE_HEX
, VALS(parity_vals
), (0x7 << 0),
1453 { &hf_setup_hvalue_stop_bits
,
1454 { "Stop Bits", "ftdi-ft.hValue.b4",
1455 FT_UINT8
, BASE_HEX
, VALS(stop_bits_vals
), (1 << 4),
1458 { &hf_setup_hvalue_break_bit
,
1459 { "Break Bit", "ftdi-ft.hValue.b6",
1460 FT_UINT8
, BASE_HEX
, VALS(break_bit_vals
), (1 << 6),
1463 { &hf_setup_hvalue_trigger
,
1464 { "hValue", "ftdi-ft.hValue",
1465 FT_UINT8
, BASE_HEX
, VALS(event_char_trigger_vals
), 0x0,
1468 { &hf_setup_hvalue_error_replacement
,
1469 { "hValue", "ftdi-ft.hValue",
1470 FT_UINT8
, BASE_HEX
, VALS(error_replacement_vals
), 0x0,
1473 { &hf_setup_hvalue_bitmode
,
1474 { "Bit Mode", "ftdi-ft.hValue",
1475 FT_UINT8
, BASE_HEX
, VALS(bitmode_vals
), 0x0,
1479 { "lIndex", "ftdi-ft.lIndex",
1480 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1483 { &hf_setup_lindex_port_ab
,
1484 { "lIndex", "ftdi-ft.lIndex",
1485 FT_UINT8
, BASE_HEX
, VALS(index_port_ab_vals
), 0x0,
1488 { &hf_setup_lindex_port_abcd
,
1489 { "lIndex", "ftdi-ft.lIndex",
1490 FT_UINT8
, BASE_HEX
, VALS(index_port_abcd_vals
), 0x0,
1493 { &hf_setup_lindex_baud_high
,
1494 { "Baud High", "ftdi-ft.lIndex.b0",
1495 FT_UINT8
, BASE_HEX
, NULL
, (1 << 0),
1499 { "hIndex", "ftdi-ft.hIndex",
1500 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1503 { &hf_setup_hindex_rts_cts
,
1504 { "RTS/CTS Flow Control", "ftdi-ft.hIndex.b0",
1505 FT_BOOLEAN
, 8, NULL
, (1 << 0),
1508 { &hf_setup_hindex_dtr_dsr
,
1509 { "DTR/DSR Flow Control", "ftdi-ft.hIndex.b1",
1510 FT_BOOLEAN
, 8, NULL
, (1 << 1),
1513 { &hf_setup_hindex_xon_xoff
,
1514 { "XON/XOFF Flow Control", "ftdi-ft.hIndex.b2",
1515 FT_BOOLEAN
, 8, NULL
, (1 << 2),
1518 { &hf_setup_hindex_baud_high
,
1519 { "Baud High", "ftdi-ft.baud_high.b0",
1520 FT_UINT8
, BASE_HEX
, NULL
, (1 << 0),
1523 { &hf_setup_hindex_baud_clock_divide
,
1524 { "Baud Clock Divide off", "ftdi-ft.baud_clock_divide.b1",
1525 FT_BOOLEAN
, 8, NULL
, (1 << 1),
1526 "When active 120 MHz is max frequency instead of 48 MHz", HFILL
}
1528 { &hf_setup_wlength
,
1529 { "wLength", "ftdi-ft.wLength",
1530 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1533 { &hf_response_lat_timer
,
1534 { "Latency Time", "ftdi-ft.latency_time",
1535 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1536 "Latency time in milliseconds", HFILL
}
1539 { "Modem Status", "ftdi-ft.modem_status",
1540 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1543 { &hf_modem_status_fs_max_packet
,
1544 { "Full Speed 64 byte MAX packet", "ftdi-ft.modem_status.b0",
1545 FT_BOOLEAN
, 8, NULL
, (1 << 0),
1548 { &hf_modem_status_hs_max_packet
,
1549 { "High Speed 512 byte MAX packet", "ftdi-ft.modem_status.b1",
1550 FT_BOOLEAN
, 8, NULL
, (1 << 1),
1553 { &hf_modem_status_cts
,
1554 { "CTS", "ftdi-ft.modem_status.b4",
1555 FT_BOOLEAN
, 8, NULL
, (1 << 4),
1558 { &hf_modem_status_dsr
,
1559 { "DSR", "ftdi-ft.modem_status.b5",
1560 FT_BOOLEAN
, 8, NULL
, (1 << 5),
1563 { &hf_modem_status_ri
,
1564 { "RI", "ftdi-ft.modem_status.b6",
1565 FT_BOOLEAN
, 8, NULL
, (1 << 6),
1568 { &hf_modem_status_dcd
,
1569 { "DCD", "ftdi-ft.modem_status.b7",
1570 FT_BOOLEAN
, 8, NULL
, (1 << 7),
1574 { "Line Status", "ftdi-ft.line_status",
1575 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1578 { &hf_line_status_receive_overflow
,
1579 { "Receive Overflow Error", "ftdi-ft.line_status.b1",
1580 FT_BOOLEAN
, 8, NULL
, (1 << 1),
1583 { &hf_line_status_parity_error
,
1584 { "Parity Error", "ftdi-ft.line_status.b2",
1585 FT_BOOLEAN
, 8, NULL
, (1 << 2),
1588 { &hf_line_status_framing_error
,
1589 { "Framing Error", "ftdi-ft.line_status.b3",
1590 FT_BOOLEAN
, 8, NULL
, (1 << 3),
1593 { &hf_line_status_break_received
,
1594 { "Break Received", "ftdi-ft.line_status.b4",
1595 FT_BOOLEAN
, 8, NULL
, (1 << 4),
1598 { &hf_line_status_tx_holding_reg_empty
,
1599 { "Transmitter Holding Register Empty", "ftdi-ft.line_status.b5",
1600 FT_BOOLEAN
, 8, NULL
, (1 << 5),
1603 { &hf_line_status_tx_empty
,
1604 { "Transmitter Empty", "ftdi-ft.line_status.b6",
1605 FT_BOOLEAN
, 8, NULL
, (1 << 6),
1608 { &hf_if_a_rx_payload
,
1609 { "A RX payload", "ftdi-ft.if_a_rx_payload",
1610 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1611 "Data received on interface A", HFILL
}
1613 { &hf_if_a_tx_payload
,
1614 { "A TX payload", "ftdi-ft.if_a_tx_payload",
1615 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1616 "Data to transmit on interface A", HFILL
}
1618 { &hf_if_b_rx_payload
,
1619 { "B RX payload", "ftdi-ft.if_b_rx_payload",
1620 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1621 "Data received on interface B", HFILL
}
1623 { &hf_if_b_tx_payload
,
1624 { "B TX payload", "ftdi-ft.if_b_tx_payload",
1625 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1626 "Data to transmit on interface B", HFILL
}
1628 { &hf_if_c_rx_payload
,
1629 { "C RX payload", "ftdi-ft.if_c_rx_payload",
1630 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1631 "Data received on interface C", HFILL
}
1633 { &hf_if_c_tx_payload
,
1634 { "C TX payload", "ftdi-ft.if_c_tx_payload",
1635 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1636 "Data to transmit on interface C", HFILL
}
1638 { &hf_if_d_rx_payload
,
1639 { "D RX payload", "ftdi-ft.if_d_rx_payload",
1640 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1641 "Data received on interface D", HFILL
}
1643 { &hf_if_d_tx_payload
,
1644 { "D TX payload", "ftdi-ft.if_d_tx_payload",
1645 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1646 "Data to transmit on interface D", HFILL
}
1648 { &hf_ftdi_fragments
,
1649 { "Payload fragments", "ftdi-ft.fragments",
1650 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1653 { &hf_ftdi_fragment
,
1654 { "Payload fragment", "ftdi-ft.fragment",
1655 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1658 { &hf_ftdi_fragment_overlap
,
1659 { "Payload fragment overlap", "ftdi-ft.fragment.overlap",
1660 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1663 { &hf_ftdi_fragment_overlap_conflicts
,
1664 { "Payload fragment overlapping with conflicting data", "ftdi-ft.fragment.overlap.conflicts",
1665 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1668 { &hf_ftdi_fragment_multiple_tails
,
1669 { "Payload has multiple tails", "ftdi-ft.fragment.multiple_tails",
1670 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1673 { &hf_ftdi_fragment_too_long_fragment
,
1674 { "Payload fragment too long", "ftdi-ft.fragment.too_long_fragment",
1675 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1678 { &hf_ftdi_fragment_error
,
1679 { "Payload defragmentation error", "ftdi-ft.fragment.error",
1680 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1683 { &hf_ftdi_fragment_count
,
1684 { "Payload fragment count", "ftdi-ft.fragment.count",
1685 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1688 { &hf_ftdi_reassembled_in
,
1689 { "Payload reassembled in", "ftdi-ft.reassembled.in",
1690 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1693 { &hf_ftdi_reassembled_length
,
1694 { "Payload reassembled length", "ftdi-ft.reassembled.length",
1695 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1700 static ei_register_info ei
[] = {
1701 { &ei_undecoded
, { "ftdi-ft.undecoded", PI_UNDECODED
, PI_WARN
, "Not dissected yet (report to wireshark.org)", EXPFILL
}},
1704 static int *ett
[] = {
1706 &ett_modem_ctrl_lvalue
,
1707 &ett_modem_ctrl_hvalue
,
1708 &ett_flow_ctrl_hindex
,
1709 &ett_baudrate_lindex
,
1710 &ett_baudrate_hindex
,
1711 &ett_setdata_hvalue
,
1715 &ett_ftdi_fragments
,
1718 request_info
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1719 bitmode_info
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1720 desegment_info
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1722 proto_ftdi_ft
= proto_register_protocol("FTDI FT USB", "FTDI FT", "ftdi-ft");
1723 proto_register_field_array(proto_ftdi_ft
, hf
, array_length(hf
));
1724 proto_register_subtree_array(ett
, array_length(ett
));
1725 ftdi_ft_handle
= register_dissector("ftdi-ft", dissect_ftdi_ft
, proto_ftdi_ft
);
1727 expert_module
= expert_register_protocol(proto_ftdi_ft
);
1728 expert_register_field_array(expert_module
, ei
, array_length(ei
));
1730 reassembly_table_register(&ftdi_reassembly_table
, &ftdi_reassembly_table_functions
);
1734 proto_reg_handoff_ftdi_ft(void)
1736 /* TODO: Add configuration option to specify VID and PID.
1737 * The values below denote default VID/PID of FT converters (as of 2019)
1738 * The VID and PID can be changed by hardware vendor.
1740 dissector_add_uint("usb.product", (0x0403 << 16) | 0x6001, ftdi_ft_handle
);
1741 dissector_add_uint("usb.product", (0x0403 << 16) | 0x6010, ftdi_ft_handle
);
1742 dissector_add_uint("usb.product", (0x0403 << 16) | 0x6011, ftdi_ft_handle
);
1743 dissector_add_uint("usb.product", (0x0403 << 16) | 0x6014, ftdi_ft_handle
);
1744 dissector_add_uint("usb.product", (0x0403 << 16) | 0x6015, ftdi_ft_handle
);
1746 /* Devices that use FTDI FT converter with changed Vendor ID and/or Product ID */
1747 dissector_add_uint("usb.product", (0x0403 << 16) | 0xcff8, ftdi_ft_handle
); /* Amontec JTAGkey */
1748 dissector_add_uint("usb.product", (0x15ba << 16) | 0x0003, ftdi_ft_handle
); /* Olimex ARM-USB-OCD */
1749 dissector_add_uint("usb.product", (0x15ba << 16) | 0x0004, ftdi_ft_handle
); /* Olimex ARM-USB-TINY */
1750 dissector_add_uint("usb.product", (0x15ba << 16) | 0x002a, ftdi_ft_handle
); /* Olimex ARM-USB-TINY-H */
1751 dissector_add_uint("usb.product", (0x15ba << 16) | 0x002b, ftdi_ft_handle
); /* Olimex ARM-USB-OCD-H */
1752 dissector_add_uint("usb.product", (0x1d50 << 16) | 0x607c, ftdi_ft_handle
); /* OpenVizsla USB sniffer/analyzer */
1754 dissector_add_for_decode_as("usb.device", ftdi_ft_handle
);
1756 ftdi_mpsse_handle
= find_dissector_add_dependency("ftdi-mpsse", proto_ftdi_ft
);
1760 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1765 * indent-tabs-mode: nil
1768 * vi: set shiftwidth=4 tabstop=8 expandtab:
1769 * :indentSize=4:tabSize=8:noTabs=true: