Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ftdi-ft.c
blob3c762380e10f1451563789fe38efcb271b113cee
1 /* packet-ftdi-ft.c
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
13 #include "config.h"
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 */
106 &ett_ftdi_fragment,
107 &ett_ftdi_fragments,
108 /* Fragment Fields */
109 &hf_ftdi_fragments,
110 &hf_ftdi_fragment,
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 */
122 NULL,
123 /* Tag */
124 "FTDI FT fragments"
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 {
140 uint32_t bus_id;
141 uint32_t device_address;
142 uint8_t request;
143 uint8_t hvalue;
144 uint8_t lindex;
145 } request_data_t;
147 typedef struct _bitmode_data {
148 uint32_t bus_id;
149 uint32_t device_address;
150 FTDI_INTERFACE interface;
151 uint8_t bitmode;
152 } bitmode_data_t;
154 typedef struct _desegment_data desegment_data_t;
155 struct _desegment_data {
156 uint32_t bus_id;
157 uint32_t device_address;
158 FTDI_INTERFACE interface;
159 uint8_t bitmode;
160 int p2p_dir;
161 /* First frame where the segmented data starts (reassembly key) */
162 uint32_t first_frame;
163 uint32_t last_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 {
172 uint32_t bus_id;
173 uint32_t device_address;
174 FTDI_INTERFACE interface;
175 uint8_t bitmode;
176 int p2p_dir;
177 uint32_t id;
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"},
204 {0, NULL}
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"},
210 {0x01, "Purge RX"},
211 {0x02, "Purge TX"},
212 {0, NULL}
215 static const value_string index_port_ab_vals[] = {
216 {0x00, "Port A"},
217 {0x01, "Port A"},
218 {0x02, "Port B"},
219 {0, NULL}
222 static const value_string index_port_abcd_vals[] = {
223 {0x00, "Port A"},
224 {0x01, "Port A"},
225 {0x02, "Port B"},
226 {0x03, "Port C"},
227 {0x04, "Port D"},
228 {0, NULL}
231 static const value_string data_size_vals[] = {
232 {0x07, "7 bit data"},
233 {0x08, "8 bit data"},
234 {0, NULL}
237 static const value_string parity_vals[] = {
238 {0x0, "None"},
239 {0x1, "Odd"},
240 {0x2, "Even"},
241 {0x3, "Mark"},
242 {0x4, "Space"},
243 {0, NULL}
246 static const value_string stop_bits_vals[] = {
247 {0, "1 stop bit"},
248 {1, "2 stop bits"},
249 {0, NULL}
252 static const value_string break_bit_vals[] = {
253 {0, "No Break"},
254 {1, "Set Break"},
255 {0, NULL}
258 static const value_string event_char_trigger_vals[] = {
259 {0x00, "No trigger"},
260 {0x01, "Trigger IN on Event Char"},
261 {0, NULL}
264 static const value_string error_replacement_vals[] = {
265 {0x00, "No Error Replacement"},
266 {0x01, "Error Replacement On"},
267 {0, NULL}
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"},
291 {0, NULL}
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.
305 static FTDI_CHIP
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)
315 case 0x0200:
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;
323 case 0x0400:
324 return FTDI_CHIP_FT232B;
325 case 0x0500:
326 return FTDI_CHIP_FT2232D;
327 case 0x0600:
328 return FTDI_CHIP_FT232R;
329 case 0x0700:
330 return FTDI_CHIP_FT2232H;
331 case 0x0800:
332 return FTDI_CHIP_FT4232H;
333 case 0x0900:
334 return FTDI_CHIP_FT232H;
335 case 0x1000:
336 return FTDI_CHIP_X_SERIES;
337 default:
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;
359 default:
360 return FTDI_INTERFACE_UNKNOWN;
364 static FTDI_INTERFACE
365 lindex_to_interface(uint8_t lindex)
367 switch (lindex)
369 case 0: /* ANY, default to A */
370 case 1:
371 return FTDI_INTERFACE_A;
372 case 2:
373 return FTDI_INTERFACE_B;
374 case 3:
375 return FTDI_INTERFACE_C;
376 case 4:
377 return FTDI_INTERFACE_D;
378 default:
379 return FTDI_INTERFACE_UNKNOWN;
383 static int
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);
389 offset++;
391 proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
392 offset++;
394 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
395 offset++;
397 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
398 offset++;
400 return offset - offset_start;
403 static int
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,
409 NULL
411 static int * const hvalue_bits[] = {
412 &hf_setup_hvalue_dtr,
413 &hf_setup_hvalue_rts,
414 NULL
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);
420 offset++;
422 proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hvalue,
423 ett_modem_ctrl_hvalue, hvalue_bits, ENC_LITTLE_ENDIAN);
424 offset++;
426 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
427 offset++;
429 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
430 offset++;
432 return offset - offset_start;
435 static int
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,
442 NULL
444 int offset_start = offset;
446 proto_tree_add_item(tree, hf_setup_lvalue_xon_char, tvb, offset, 1, ENC_LITTLE_ENDIAN);
447 offset++;
449 proto_tree_add_item(tree, hf_setup_hvalue_xoff_char, tvb, offset, 1, ENC_LITTLE_ENDIAN);
450 offset++;
452 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
453 offset++;
455 proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hindex,
456 ett_flow_ctrl_hindex, hindex_bits, ENC_LITTLE_ENDIAN);
457 offset++;
459 return offset - offset_start;
462 static int
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,
467 NULL
469 static int * const hindex_bits[] = {
470 &hf_setup_hindex_baud_high,
471 NULL
473 static int * const hindex_bits_hispeed[] = {
474 &hf_setup_hindex_baud_high,
475 &hf_setup_hindex_baud_clock_divide,
476 NULL
479 int offset_start = offset;
481 proto_tree_add_item(tree, hf_setup_lvalue_baud_low, tvb, offset, 1, ENC_LITTLE_ENDIAN);
482 offset++;
484 proto_tree_add_item(tree, hf_setup_hvalue_baud_mid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
485 offset++;
487 switch (chip)
489 case FTDI_CHIP_FT8U232AM:
490 proto_tree_add_item(tree, hf_setup_lindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
491 offset++;
493 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
494 offset++;
495 break;
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);
500 offset++;
502 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
503 offset++;
504 break;
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);
508 offset++;
510 proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hindex,
511 ett_baudrate_hindex, hindex_bits, ENC_LITTLE_ENDIAN);
512 offset++;
513 break;
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);
518 offset++;
520 proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hindex,
521 ett_baudrate_hindex, hindex_bits_hispeed, ENC_LITTLE_ENDIAN);
522 offset++;
523 break;
524 case FTDI_CHIP_UNKNOWN:
525 default:
526 proto_tree_add_expert(tree, pinfo, &ei_undecoded, tvb, offset, 2);
527 offset += 2;
528 break;
530 return offset - offset_start;
533 static int
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,
540 NULL
542 int offset_start = offset;
544 proto_tree_add_item(tree, hf_setup_lvalue_data_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
545 offset++;
547 proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hvalue,
548 ett_setdata_hvalue, hvalue_bits, ENC_LITTLE_ENDIAN);
549 offset++;
551 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
552 offset++;
554 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
555 offset++;
557 return offset - offset_start;
560 static int
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);
566 offset++;
568 proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
569 offset++;
571 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
572 offset++;
574 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
575 offset++;
577 return offset - offset_start;
580 static int
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);
586 offset++;
588 proto_tree_add_item(tree, hf_setup_hvalue_trigger, tvb, offset, 1, ENC_LITTLE_ENDIAN);
589 offset++;
591 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
592 offset++;
594 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
595 offset++;
597 return offset - offset_start;
600 static int
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);
606 offset++;
608 proto_tree_add_item(tree, hf_setup_hvalue_error_replacement, tvb, offset, 1, ENC_LITTLE_ENDIAN);
609 offset++;
611 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
612 offset++;
614 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
615 offset++;
618 return offset - offset_start;
621 static int
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);
627 offset++;
629 proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
630 offset++;
632 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
633 offset++;
635 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
636 offset++;
638 return offset - offset_start;
641 static int
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);
647 offset++;
649 proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
650 offset++;
652 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
653 offset++;
655 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
656 offset++;
658 return offset - offset_start;
661 static int
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);
667 offset++;
669 return offset - offset_start;
672 static int
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);
678 offset++;
680 proto_tree_add_item(tree, hf_setup_hvalue_bitmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
681 offset++;
683 proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
684 offset++;
686 proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
687 offset++;
689 return offset - offset_start;
692 static int
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,
700 &hf_modem_status_ri,
701 &hf_modem_status_dcd,
702 NULL
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,
711 NULL
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);
717 offset++;
719 proto_tree_add_bitmask(tree, tvb, offset, hf_line_status,
720 ett_line_status, line_status_bits, ENC_LITTLE_ENDIAN);
721 offset++;
723 if (out_rx_len)
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);
738 return 2;
741 static void
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[] = {
748 {1, &k_bus_id},
749 {1, &k_device_address},
750 {1, &k_interface},
751 {1, &pinfo->num},
752 {0, NULL}
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);
764 static uint8_t
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[] = {
771 {1, &k_bus_id},
772 {1, &k_device_address},
773 {1, &k_interface},
774 {1, &pinfo->num},
775 {0, NULL}
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[] = {
798 {1, &k_bus_id},
799 {1, &k_device_address},
800 {1, &k_interface},
801 {1, &k_p2p_dir},
802 {1, &pinfo->num},
803 {0, NULL}
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[] = {
832 {1, &k_bus_id},
833 {1, &k_device_address},
834 {1, &k_interface},
835 {1, &k_p2p_dir},
836 {1, &pinfo->num},
837 {0, NULL}
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;
853 return NULL;
856 static unsigned ftdi_fragment_key_hash(const void *k)
858 const ftdi_fragment_key_t *key = (const ftdi_fragment_key_t *)k;
859 return key->id;
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;
886 key->id = id;
888 return (void *)key;
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,
906 static void
907 dissect_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, urb_info_t *urb,
908 FTDI_INTERFACE interface, uint8_t bitmode)
910 uint32_t k_bus_id;
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 = {
919 .bus_id = k_bus_id,
920 .device_address = k_device_address,
921 .chip = identify_chip(urb->conv),
922 .iface = interface,
923 .mcu_mode = (bitmode == BITMODE_MCU),
925 call_dissector_with_data(ftdi_mpsse_handle, tvb, pinfo, tree, &mpsse_info);
929 static int
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;
937 uint32_t bytes;
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);
944 if (bytes > 0)
946 tvbuff_t *payload_tvb = NULL;
947 uint32_t reassembled_bytes = 0;
948 uint8_t bitmode;
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);
958 if (desegment_data)
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 */
974 fragment_item *item;
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);
987 else
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);
1006 else
1008 /* Packet is not part of reassembly sequence, simply use it without modifications */
1009 payload_tvb = tvb;
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)
1038 if (desegment_data)
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;
1046 else
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);
1065 else
1067 int fragment_length;
1068 int previous_bytes;
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;
1096 return bytes;
1099 static int
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;
1104 int offset = 0;
1105 urb_info_t *urb = (urb_info_t *)data;
1106 request_data_t *request_data = NULL;
1107 wmem_tree_key_t key[4];
1108 uint32_t k_bus_id;
1109 uint32_t k_device_address;
1111 if (!urb)
1113 return offset;
1116 if (urb->is_setup)
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))
1122 return offset;
1126 k_bus_id = urb->bus_id;
1127 k_device_address = urb->device_address;
1129 key[0].length = 1;
1130 key[0].key = &k_bus_id;
1131 key[1].length = 1;
1132 key[1].key = &k_device_address;
1133 key[2].length = 1;
1134 key[2].key = &pinfo->num;
1135 key[3].length = 0;
1136 key[3].key = NULL;
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");
1147 if (urb->is_setup)
1149 int bytes_dissected;
1150 uint8_t brequest;
1151 uint8_t hvalue;
1152 uint8_t lindex;
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);
1158 offset++;
1160 hvalue = tvb_get_uint8(tvb, offset + 1);
1161 lindex = tvb_get_uint8(tvb, offset + 2);
1163 switch (brequest)
1165 case REQUEST_RESET:
1166 bytes_dissected = dissect_request_reset(tvb, pinfo, offset, main_tree);
1167 break;
1168 case REQUEST_MODEM_CTRL:
1169 bytes_dissected = dissect_request_modem_ctrl(tvb, pinfo, offset, main_tree);
1170 break;
1171 case REQUEST_SET_FLOW_CTRL:
1172 bytes_dissected = dissect_request_set_flow_ctrl(tvb, pinfo, offset, main_tree);
1173 break;
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);
1178 break;
1180 case REQUEST_SET_DATA:
1181 bytes_dissected = dissect_request_set_data(tvb, pinfo, offset, main_tree);
1182 break;
1183 case REQUEST_GET_MODEM_STAT:
1184 bytes_dissected = dissect_request_get_modem_stat(tvb, pinfo, offset, main_tree);
1185 break;
1186 case REQUEST_SET_EVENT_CHAR:
1187 bytes_dissected = dissect_request_set_event_char(tvb, pinfo, offset, main_tree);
1188 break;
1189 case REQUEST_SET_ERROR_CHAR:
1190 bytes_dissected = dissect_request_set_error_char(tvb, pinfo, offset, main_tree);
1191 break;
1192 case REQUEST_SET_LAT_TIMER:
1193 bytes_dissected = dissect_request_set_lat_timer(tvb, pinfo, offset, main_tree);
1194 break;
1195 case REQUEST_GET_LAT_TIMER:
1196 bytes_dissected = dissect_request_get_lat_timer(tvb, pinfo, offset, main_tree);
1197 break;
1198 case REQUEST_SET_BITMODE:
1199 bytes_dissected = dissect_request_set_bitmode(tvb, pinfo, offset, main_tree);
1200 break;
1201 default:
1202 bytes_dissected = 0;
1203 break;
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);
1214 offset += 2;
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);
1225 else
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);
1238 break;
1239 case REQUEST_GET_LAT_TIMER:
1240 offset += dissect_response_get_lat_timer(tvb, pinfo, offset, main_tree);
1241 break;
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);
1245 break;
1246 default:
1247 break;
1250 else
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);
1262 else
1264 const char *interface_str;
1265 FTDI_INTERFACE interface;
1266 int rx_hf, tx_hf;
1268 interface = endpoint_to_interface(urb);
1269 switch (interface)
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;
1275 break;
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;
1280 break;
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;
1285 break;
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;
1290 break;
1291 default:
1292 return offset;
1295 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTDI FT");
1296 if (pinfo->p2p_dir == P2P_DIR_RECV)
1298 int total_rx_len = 0;
1299 int rx_len;
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;
1310 if (rx_len > 0)
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);
1315 offset += rx_len;
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);
1327 else
1329 tvb_free_chain(rx_tvb);
1332 else
1334 int bytes;
1336 col_add_fstr(pinfo->cinfo, COL_INFO, "INTERFACE %s TX", interface_str);
1337 bytes = tvb_reported_length_remaining(tvb, offset);
1339 if (bytes > 0)
1341 tvbuff_t *tx_tvb;
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);
1349 offset += bytes;
1354 return offset;
1357 void
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,
1366 NULL, HFILL }
1368 { &hf_setup_lvalue,
1369 { "lValue", "ftdi-ft.lValue",
1370 FT_UINT8, BASE_HEX, NULL, 0x0,
1371 NULL, HFILL }
1373 { &hf_setup_lvalue_purge,
1374 { "lValue", "ftdi-ft.lValue",
1375 FT_UINT8, BASE_HEX, VALS(reset_purge_vals), 0x0,
1376 NULL, HFILL }
1378 { &hf_setup_lvalue_dtr,
1379 { "DTR Active", "ftdi-ft.lValue.b0",
1380 FT_BOOLEAN, 8, NULL, (1 << 0),
1381 NULL, HFILL }
1383 { &hf_setup_lvalue_rts,
1384 { "RTS Active", "ftdi-ft.lValue.b1",
1385 FT_BOOLEAN, 8, NULL, (1 << 1),
1386 NULL, HFILL }
1388 { &hf_setup_lvalue_xon_char,
1389 { "XON Char", "ftdi-ft.lValue",
1390 FT_UINT8, BASE_HEX, NULL, 0x0,
1391 NULL, HFILL }
1393 { &hf_setup_lvalue_baud_low,
1394 { "Baud low", "ftdi-ft.lValue",
1395 FT_UINT8, BASE_HEX, NULL, 0x0,
1396 NULL, HFILL }
1398 { &hf_setup_lvalue_data_size,
1399 { "Data Size", "ftdi-ft.lValue",
1400 FT_UINT8, BASE_HEX, VALS(data_size_vals), 0x0,
1401 NULL, HFILL }
1403 { &hf_setup_lvalue_event_char,
1404 { "Event Char", "ftdi-ft.lValue",
1405 FT_UINT8, BASE_HEX, NULL, 0x0,
1406 NULL, HFILL }
1408 { &hf_setup_lvalue_error_char,
1409 { "Parity Error Char", "ftdi-ft.lValue",
1410 FT_UINT8, BASE_HEX, NULL, 0x0,
1411 NULL, HFILL }
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,
1421 NULL, HFILL }
1423 { &hf_setup_hvalue,
1424 { "hValue", "ftdi-ft.hValue",
1425 FT_UINT8, BASE_HEX, NULL, 0x0,
1426 NULL, HFILL }
1428 { &hf_setup_hvalue_dtr,
1429 { "en DTR for writing", "ftdi-ft.hValue.b0",
1430 FT_BOOLEAN, 8, NULL, (1 << 0),
1431 NULL, HFILL }
1433 { &hf_setup_hvalue_rts,
1434 { "en RTS for writing", "ftdi-ft.hValue.b1",
1435 FT_BOOLEAN, 8, NULL, (1 << 1),
1436 NULL, HFILL }
1438 { &hf_setup_hvalue_xoff_char,
1439 { "XOFF Char", "ftdi-ft.hValue",
1440 FT_UINT8, BASE_HEX, NULL, 0x0,
1441 NULL, HFILL }
1443 { &hf_setup_hvalue_baud_mid,
1444 { "Baud mid", "ftdi-ft.hValue",
1445 FT_UINT8, BASE_HEX, NULL, 0x0,
1446 NULL, HFILL }
1448 { &hf_setup_hvalue_parity,
1449 { "Parity", "ftdi-ft.hValue.parity",
1450 FT_UINT8, BASE_HEX, VALS(parity_vals), (0x7 << 0),
1451 NULL, HFILL }
1453 { &hf_setup_hvalue_stop_bits,
1454 { "Stop Bits", "ftdi-ft.hValue.b4",
1455 FT_UINT8, BASE_HEX, VALS(stop_bits_vals), (1 << 4),
1456 NULL, HFILL }
1458 { &hf_setup_hvalue_break_bit,
1459 { "Break Bit", "ftdi-ft.hValue.b6",
1460 FT_UINT8, BASE_HEX, VALS(break_bit_vals), (1 << 6),
1461 NULL, HFILL }
1463 { &hf_setup_hvalue_trigger,
1464 { "hValue", "ftdi-ft.hValue",
1465 FT_UINT8, BASE_HEX, VALS(event_char_trigger_vals), 0x0,
1466 NULL, HFILL }
1468 { &hf_setup_hvalue_error_replacement,
1469 { "hValue", "ftdi-ft.hValue",
1470 FT_UINT8, BASE_HEX, VALS(error_replacement_vals), 0x0,
1471 NULL, HFILL }
1473 { &hf_setup_hvalue_bitmode,
1474 { "Bit Mode", "ftdi-ft.hValue",
1475 FT_UINT8, BASE_HEX, VALS(bitmode_vals), 0x0,
1476 NULL, HFILL }
1478 { &hf_setup_lindex,
1479 { "lIndex", "ftdi-ft.lIndex",
1480 FT_UINT8, BASE_HEX, NULL, 0x0,
1481 NULL, HFILL }
1483 { &hf_setup_lindex_port_ab,
1484 { "lIndex", "ftdi-ft.lIndex",
1485 FT_UINT8, BASE_HEX, VALS(index_port_ab_vals), 0x0,
1486 NULL, HFILL }
1488 { &hf_setup_lindex_port_abcd,
1489 { "lIndex", "ftdi-ft.lIndex",
1490 FT_UINT8, BASE_HEX, VALS(index_port_abcd_vals), 0x0,
1491 NULL, HFILL }
1493 { &hf_setup_lindex_baud_high,
1494 { "Baud High", "ftdi-ft.lIndex.b0",
1495 FT_UINT8, BASE_HEX, NULL, (1 << 0),
1496 NULL, HFILL }
1498 { &hf_setup_hindex,
1499 { "hIndex", "ftdi-ft.hIndex",
1500 FT_UINT8, BASE_HEX, NULL, 0x0,
1501 NULL, HFILL }
1503 { &hf_setup_hindex_rts_cts,
1504 { "RTS/CTS Flow Control", "ftdi-ft.hIndex.b0",
1505 FT_BOOLEAN, 8, NULL, (1 << 0),
1506 NULL, HFILL }
1508 { &hf_setup_hindex_dtr_dsr,
1509 { "DTR/DSR Flow Control", "ftdi-ft.hIndex.b1",
1510 FT_BOOLEAN, 8, NULL, (1 << 1),
1511 NULL, HFILL }
1513 { &hf_setup_hindex_xon_xoff,
1514 { "XON/XOFF Flow Control", "ftdi-ft.hIndex.b2",
1515 FT_BOOLEAN, 8, NULL, (1 << 2),
1516 NULL, HFILL }
1518 { &hf_setup_hindex_baud_high,
1519 { "Baud High", "ftdi-ft.baud_high.b0",
1520 FT_UINT8, BASE_HEX, NULL, (1 << 0),
1521 NULL, HFILL }
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,
1531 NULL, HFILL }
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 }
1538 { &hf_modem_status,
1539 { "Modem Status", "ftdi-ft.modem_status",
1540 FT_UINT8, BASE_HEX, NULL, 0x0,
1541 NULL, HFILL }
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),
1546 NULL, HFILL }
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),
1551 NULL, HFILL }
1553 { &hf_modem_status_cts,
1554 { "CTS", "ftdi-ft.modem_status.b4",
1555 FT_BOOLEAN, 8, NULL, (1 << 4),
1556 NULL, HFILL }
1558 { &hf_modem_status_dsr,
1559 { "DSR", "ftdi-ft.modem_status.b5",
1560 FT_BOOLEAN, 8, NULL, (1 << 5),
1561 NULL, HFILL }
1563 { &hf_modem_status_ri,
1564 { "RI", "ftdi-ft.modem_status.b6",
1565 FT_BOOLEAN, 8, NULL, (1 << 6),
1566 NULL, HFILL }
1568 { &hf_modem_status_dcd,
1569 { "DCD", "ftdi-ft.modem_status.b7",
1570 FT_BOOLEAN, 8, NULL, (1 << 7),
1571 NULL, HFILL }
1573 { &hf_line_status,
1574 { "Line Status", "ftdi-ft.line_status",
1575 FT_UINT8, BASE_HEX, NULL, 0x0,
1576 NULL, HFILL }
1578 { &hf_line_status_receive_overflow,
1579 { "Receive Overflow Error", "ftdi-ft.line_status.b1",
1580 FT_BOOLEAN, 8, NULL, (1 << 1),
1581 NULL, HFILL }
1583 { &hf_line_status_parity_error,
1584 { "Parity Error", "ftdi-ft.line_status.b2",
1585 FT_BOOLEAN, 8, NULL, (1 << 2),
1586 NULL, HFILL }
1588 { &hf_line_status_framing_error,
1589 { "Framing Error", "ftdi-ft.line_status.b3",
1590 FT_BOOLEAN, 8, NULL, (1 << 3),
1591 NULL, HFILL }
1593 { &hf_line_status_break_received,
1594 { "Break Received", "ftdi-ft.line_status.b4",
1595 FT_BOOLEAN, 8, NULL, (1 << 4),
1596 NULL, HFILL }
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),
1601 NULL, HFILL }
1603 { &hf_line_status_tx_empty,
1604 { "Transmitter Empty", "ftdi-ft.line_status.b6",
1605 FT_BOOLEAN, 8, NULL, (1 << 6),
1606 NULL, HFILL }
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,
1651 NULL, HFILL }
1653 { &hf_ftdi_fragment,
1654 { "Payload fragment", "ftdi-ft.fragment",
1655 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1656 NULL, HFILL }
1658 { &hf_ftdi_fragment_overlap,
1659 { "Payload fragment overlap", "ftdi-ft.fragment.overlap",
1660 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1661 NULL, HFILL }
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,
1666 NULL, HFILL }
1668 { &hf_ftdi_fragment_multiple_tails,
1669 { "Payload has multiple tails", "ftdi-ft.fragment.multiple_tails",
1670 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1671 NULL, HFILL}
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,
1676 NULL, HFILL }
1678 { &hf_ftdi_fragment_error,
1679 { "Payload defragmentation error", "ftdi-ft.fragment.error",
1680 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1681 NULL, HFILL }
1683 { &hf_ftdi_fragment_count,
1684 { "Payload fragment count", "ftdi-ft.fragment.count",
1685 FT_UINT32, BASE_DEC, NULL, 0x0,
1686 NULL, HFILL }
1688 { &hf_ftdi_reassembled_in,
1689 { "Payload reassembled in", "ftdi-ft.reassembled.in",
1690 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1691 NULL, HFILL }
1693 { &hf_ftdi_reassembled_length,
1694 { "Payload reassembled length", "ftdi-ft.reassembled.length",
1695 FT_UINT32, BASE_DEC, NULL, 0x0,
1696 NULL, HFILL }
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[] = {
1705 &ett_ftdi_ft,
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,
1712 &ett_modem_status,
1713 &ett_line_status,
1714 &ett_ftdi_fragment,
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);
1733 void
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
1762 * Local variables:
1763 * c-basic-offset: 4
1764 * tab-width: 8
1765 * indent-tabs-mode: nil
1766 * End:
1768 * vi: set shiftwidth=4 tabstop=8 expandtab:
1769 * :indentSize=4:tabSize=8:noTabs=true: