1 /* packet-ftdi-ft.c
2  * Routines for FTDI FTxxxx USB converters dissection
3  *
4  * Copyright 2019 Tomasz Mon
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "config.h"
14 
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"
21 
22 static int proto_ftdi_ft = -1;
23 
24 static gint hf_setup_brequest = -1;
25 static gint hf_setup_lvalue = -1;
26 static gint hf_setup_lvalue_purge = -1;
27 static gint hf_setup_lvalue_dtr = -1;
28 static gint hf_setup_lvalue_rts = -1;
29 static gint hf_setup_lvalue_xon_char = -1;
30 static gint hf_setup_lvalue_baud_low = -1;
31 static gint hf_setup_lvalue_data_size = -1;
32 static gint hf_setup_lvalue_event_char = -1;
33 static gint hf_setup_lvalue_error_char = -1;
34 static gint hf_setup_lvalue_latency_time = -1;
35 static gint hf_setup_lvalue_bitmask = -1;
36 static gint hf_setup_hvalue = -1;
37 static gint hf_setup_hvalue_dtr = -1;
38 static gint hf_setup_hvalue_rts = -1;
39 static gint hf_setup_hvalue_xoff_char = -1;
40 static gint hf_setup_hvalue_baud_mid = -1;
41 static gint hf_setup_hvalue_parity = -1;
42 static gint hf_setup_hvalue_stop_bits = -1;
43 static gint hf_setup_hvalue_break_bit = -1;
44 static gint hf_setup_hvalue_trigger = -1;
45 static gint hf_setup_hvalue_error_replacement = -1;
46 static gint hf_setup_hvalue_bitmode = -1;
47 static gint hf_setup_lindex = -1;
48 static gint hf_setup_lindex_port_ab = -1;
49 static gint hf_setup_lindex_port_abcd = -1;
50 static gint hf_setup_lindex_baud_high = -1;
51 static gint hf_setup_hindex = -1;
52 static gint hf_setup_hindex_rts_cts = -1;
53 static gint hf_setup_hindex_dtr_dsr = -1;
54 static gint hf_setup_hindex_xon_xoff = -1;
55 static gint hf_setup_hindex_baud_high = -1;
56 static gint hf_setup_hindex_baud_clock_divide = -1;
57 static gint hf_setup_wlength = -1;
58 static gint hf_response_lat_timer = -1;
59 static gint hf_modem_status = -1;
60 static gint hf_modem_status_fs_max_packet = -1;
61 static gint hf_modem_status_hs_max_packet = -1;
62 static gint hf_modem_status_cts = -1;
63 static gint hf_modem_status_dsr = -1;
64 static gint hf_modem_status_ri = -1;
65 static gint hf_modem_status_dcd = -1;
66 static gint hf_line_status = -1;
67 static gint hf_line_status_receive_overflow = -1;
68 static gint hf_line_status_parity_error = -1;
69 static gint hf_line_status_framing_error = -1;
70 static gint hf_line_status_break_received = -1;
71 static gint hf_line_status_tx_holding_reg_empty = -1;
72 static gint hf_line_status_tx_empty = -1;
73 static gint hf_if_a_rx_payload = -1;
74 static gint hf_if_a_tx_payload = -1;
75 static gint hf_if_b_rx_payload = -1;
76 static gint hf_if_b_tx_payload = -1;
77 static gint hf_if_c_rx_payload = -1;
78 static gint hf_if_c_tx_payload = -1;
79 static gint hf_if_d_rx_payload = -1;
80 static gint hf_if_d_tx_payload = -1;
81 static gint hf_ftdi_fragments = -1;
82 static gint hf_ftdi_fragment = -1;
83 static gint hf_ftdi_fragment_overlap = -1;
84 static gint hf_ftdi_fragment_overlap_conflicts = -1;
85 static gint hf_ftdi_fragment_multiple_tails = -1;
86 static gint hf_ftdi_fragment_too_long_fragment = -1;
87 static gint hf_ftdi_fragment_error = -1;
88 static gint hf_ftdi_fragment_count = -1;
89 static gint hf_ftdi_reassembled_in = -1;
90 static gint hf_ftdi_reassembled_length = -1;
91 
92 static gint ett_ftdi_ft = -1;
93 static gint ett_modem_ctrl_lvalue = -1;
94 static gint ett_modem_ctrl_hvalue = -1;
95 static gint ett_flow_ctrl_hindex = -1;
96 static gint ett_baudrate_lindex = -1;
97 static gint ett_baudrate_hindex = -1;
98 static gint ett_setdata_hvalue = -1;
99 static gint ett_modem_status = -1;
100 static gint ett_line_status = -1;
101 static gint ett_ftdi_fragment = -1;
102 static gint ett_ftdi_fragments = -1;
103 
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"
125 };
126 
127 static dissector_handle_t ftdi_mpsse_handle;
128 
129 static expert_field ei_undecoded = EI_INIT;
130 
131 static dissector_handle_t ftdi_ft_handle;
132 
133 static reassembly_table ftdi_reassembly_table;
134 
135 static wmem_tree_t *request_info = NULL;
136 static wmem_tree_t *bitmode_info = NULL;
137 static wmem_tree_t *desegment_info = NULL;
138 
139 typedef struct _request_data {
140     guint32  bus_id;
141     guint32  device_address;
142     guint8   request;
143     guint8   hvalue;
144     guint8   lindex;
145 } request_data_t;
146 
147 typedef struct _bitmode_data {
148     guint32        bus_id;
149     guint32        device_address;
150     FTDI_INTERFACE interface;
151     guint8         bitmode;
152 } bitmode_data_t;
153 
154 typedef struct _desegment_data desegment_data_t;
155 struct _desegment_data {
156     guint32           bus_id;
157     guint32           device_address;
158     FTDI_INTERFACE    interface;
159     guint8            bitmode;
160     gint              p2p_dir;
161     /* First frame where the segmented data starts (reassembly key) */
162     guint32           first_frame;
163     guint32           last_frame;
164     gint              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.
167      */
168     desegment_data_t *previous;
169 };
170 
171 typedef struct _ftdi_fragment_key {
172     guint32           bus_id;
173     guint32           device_address;
174     FTDI_INTERFACE    interface;
175     guint8            bitmode;
176     gint              p2p_dir;
177     guint32           id;
178 } ftdi_fragment_key_t;
179 
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
191 
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}
205 };
206 static value_string_ext request_vals_ext  = VALUE_STRING_EXT_INIT(request_vals);
207 
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}
213 };
214 
215 static const value_string index_port_ab_vals[] = {
216     {0x00, "Port A"},
217     {0x01, "Port A"},
218     {0x02, "Port B"},
219     {0, NULL}
220 };
221 
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}
229 };
230 
231 static const value_string data_size_vals[] = {
232     {0x07, "7 bit data"},
233     {0x08, "8 bit data"},
234     {0, NULL}
235 };
236 
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}
244 };
245 
246 static const value_string stop_bits_vals[] = {
247     {0, "1 stop bit"},
248     {1, "2 stop bits"},
249     {0, NULL}
250 };
251 
252 static const value_string break_bit_vals[] = {
253     {0, "No Break"},
254     {1, "Set Break"},
255     {0, NULL}
256 };
257 
258 static const value_string event_char_trigger_vals[] = {
259     {0x00, "No trigger"},
260     {0x01, "Trigger IN on Event Char"},
261     {0, NULL}
262 };
263 
264 static const value_string error_replacement_vals[] = {
265     {0x00, "No Error Replacement"},
266     {0x01, "Error Replacement On"},
267     {0, NULL}
268 };
269 
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
279 
280 
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}
292 };
293 
294 #define MODEM_STATUS_BIT_FS_64_MAX_PACKET  (1 << 0)
295 #define MODEM_STATUS_BIT_HS_512_MAX_PACKET (1 << 1)
296 
297 void proto_register_ftdi_ft(void);
298 void proto_reg_handoff_ftdi_ft(void);
299 
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.
304  */
305 static FTDI_CHIP
identify_chip(usb_conv_info_t * usb_conv_info)306 identify_chip(usb_conv_info_t *usb_conv_info)
307 {
308     switch (usb_conv_info->deviceVersion)
309     {
310     case 0x0200:
311         if (usb_conv_info->iSerialNumber)
312         {
313             /* Serial number enabled - it is FT8U232AM */
314             return FTDI_CHIP_FT8U232AM;
315         }
316         /* No serial number - FT232B without (or with blank) EEPROM fitted */
317         return FTDI_CHIP_FT232B;
318     case 0x0400:
319         return FTDI_CHIP_FT232B;
320     case 0x0500:
321         return FTDI_CHIP_FT2232D;
322     case 0x0600:
323         return FTDI_CHIP_FT232R;
324     case 0x0700:
325         return FTDI_CHIP_FT2232H;
326     case 0x0800:
327         return FTDI_CHIP_FT4232H;
328     case 0x0900:
329         return FTDI_CHIP_FT232H;
330     case 0x1000:
331         return FTDI_CHIP_X_SERIES;
332     default:
333         return FTDI_CHIP_UNKNOWN;
334     }
335 }
336 
337 static FTDI_INTERFACE
endpoint_to_interface(usb_conv_info_t * usb_conv_info)338 endpoint_to_interface(usb_conv_info_t *usb_conv_info)
339 {
340     switch (usb_conv_info->endpoint)
341     {
342     case 0x01: /* A OUT */
343     case 0x02: /* A IN */
344         return FTDI_INTERFACE_A;
345     case 0x03: /* B OUT */
346     case 0x04: /* B IN */
347         return FTDI_INTERFACE_B;
348     case 0x05: /* C OUT */
349     case 0x06: /* C IN */
350         return FTDI_INTERFACE_C;
351     case 0x07: /* D OUT */
352     case 0x08: /* D IN */
353         return FTDI_INTERFACE_D;
354     default:
355         return FTDI_INTERFACE_UNKNOWN;
356     }
357 }
358 
359 static FTDI_INTERFACE
lindex_to_interface(guint8 lindex)360 lindex_to_interface(guint8 lindex)
361 {
362     switch (lindex)
363     {
364     case 0: /* ANY, default to A */
365     case 1:
366         return FTDI_INTERFACE_A;
367     case 2:
368         return FTDI_INTERFACE_B;
369     case 3:
370         return FTDI_INTERFACE_C;
371     case 4:
372         return FTDI_INTERFACE_D;
373     default:
374         return FTDI_INTERFACE_UNKNOWN;
375     }
376 }
377 
378 static gint
dissect_request_reset(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)379 dissect_request_reset(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
380 {
381     gint offset_start = offset;
382 
383     proto_tree_add_item(tree, hf_setup_lvalue_purge, tvb, offset, 1, ENC_LITTLE_ENDIAN);
384     offset++;
385 
386     proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387     offset++;
388 
389     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
390     offset++;
391 
392     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
393     offset++;
394 
395     return offset - offset_start;
396 }
397 
398 static gint
dissect_request_modem_ctrl(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)399 dissect_request_modem_ctrl(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
400 {
401     static int * const lvalue_bits[] = {
402         &hf_setup_lvalue_dtr,
403         &hf_setup_lvalue_rts,
404         NULL
405     };
406     static int * const hvalue_bits[] = {
407         &hf_setup_hvalue_dtr,
408         &hf_setup_hvalue_rts,
409         NULL
410     };
411     gint offset_start = offset;
412 
413     proto_tree_add_bitmask(tree, tvb, offset, hf_setup_lvalue,
414         ett_modem_ctrl_lvalue, lvalue_bits, ENC_LITTLE_ENDIAN);
415     offset++;
416 
417     proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hvalue,
418         ett_modem_ctrl_hvalue, hvalue_bits, ENC_LITTLE_ENDIAN);
419     offset++;
420 
421     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
422     offset++;
423 
424     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
425     offset++;
426 
427     return offset - offset_start;
428 }
429 
430 static gint
dissect_request_set_flow_ctrl(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)431 dissect_request_set_flow_ctrl(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
432 {
433     static int * const hindex_bits[] = {
434         &hf_setup_hindex_rts_cts,
435         &hf_setup_hindex_dtr_dsr,
436         &hf_setup_hindex_xon_xoff,
437         NULL
438     };
439     gint offset_start = offset;
440 
441     proto_tree_add_item(tree, hf_setup_lvalue_xon_char, tvb, offset, 1, ENC_LITTLE_ENDIAN);
442     offset++;
443 
444     proto_tree_add_item(tree, hf_setup_hvalue_xoff_char, tvb, offset, 1, ENC_LITTLE_ENDIAN);
445     offset++;
446 
447     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
448     offset++;
449 
450     proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hindex,
451         ett_flow_ctrl_hindex, hindex_bits, ENC_LITTLE_ENDIAN);
452     offset++;
453 
454     return offset - offset_start;
455 }
456 
457 static gint
dissect_request_set_baud_rate(tvbuff_t * tvb,packet_info * pinfo,gint offset,proto_tree * tree,FTDI_CHIP chip)458 dissect_request_set_baud_rate(tvbuff_t *tvb, packet_info *pinfo, gint offset, proto_tree *tree, FTDI_CHIP chip)
459 {
460     static int * const lindex_bits[] = {
461         &hf_setup_lindex_baud_high,
462         NULL
463     };
464     static int * const hindex_bits[] = {
465         &hf_setup_hindex_baud_high,
466         NULL
467     };
468     static int * const hindex_bits_hispeed[] = {
469         &hf_setup_hindex_baud_high,
470         &hf_setup_hindex_baud_clock_divide,
471         NULL
472     };
473 
474     gint offset_start = offset;
475 
476     proto_tree_add_item(tree, hf_setup_lvalue_baud_low, tvb, offset, 1, ENC_LITTLE_ENDIAN);
477     offset++;
478 
479     proto_tree_add_item(tree, hf_setup_hvalue_baud_mid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
480     offset++;
481 
482     switch (chip)
483     {
484     case FTDI_CHIP_FT8U232AM:
485         proto_tree_add_item(tree, hf_setup_lindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
486         offset++;
487 
488         proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
489         offset++;
490         break;
491     case FTDI_CHIP_FT232B:
492     case FTDI_CHIP_FT232R:
493         proto_tree_add_bitmask(tree, tvb, offset, hf_setup_lindex,
494             ett_baudrate_lindex, lindex_bits, ENC_LITTLE_ENDIAN);
495         offset++;
496 
497         proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
498         offset++;
499         break;
500     case FTDI_CHIP_FT2232D:
501     case FTDI_CHIP_X_SERIES:
502         proto_tree_add_item(tree, hf_setup_lindex_port_ab, tvb, offset, 1, ENC_LITTLE_ENDIAN);
503         offset++;
504 
505         proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hindex,
506             ett_baudrate_hindex, hindex_bits, ENC_LITTLE_ENDIAN);
507         offset++;
508         break;
509     case FTDI_CHIP_FT2232H:
510     case FTDI_CHIP_FT4232H:
511     case FTDI_CHIP_FT232H:
512         proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
513         offset++;
514 
515         proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hindex,
516             ett_baudrate_hindex, hindex_bits_hispeed, ENC_LITTLE_ENDIAN);
517         offset++;
518         break;
519     case FTDI_CHIP_UNKNOWN:
520     default:
521         proto_tree_add_expert(tree, pinfo, &ei_undecoded, tvb, offset, 2);
522         offset += 2;
523         break;
524     }
525     return offset - offset_start;
526 }
527 
528 static gint
dissect_request_set_data(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)529 dissect_request_set_data(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
530 {
531     static int * const hvalue_bits[] = {
532         &hf_setup_hvalue_parity,
533         &hf_setup_hvalue_stop_bits,
534         &hf_setup_hvalue_break_bit,
535         NULL
536     };
537     gint offset_start = offset;
538 
539     proto_tree_add_item(tree, hf_setup_lvalue_data_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
540     offset++;
541 
542     proto_tree_add_bitmask(tree, tvb, offset, hf_setup_hvalue,
543         ett_setdata_hvalue, hvalue_bits, ENC_LITTLE_ENDIAN);
544     offset++;
545 
546     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
547     offset++;
548 
549     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
550     offset++;
551 
552     return offset - offset_start;
553 }
554 
555 static gint
dissect_request_get_modem_stat(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)556 dissect_request_get_modem_stat(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
557 {
558     gint offset_start = offset;
559 
560     proto_tree_add_item(tree, hf_setup_lvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
561     offset++;
562 
563     proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
564     offset++;
565 
566     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
567     offset++;
568 
569     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
570     offset++;
571 
572     return offset - offset_start;
573 }
574 
575 static gint
dissect_request_set_event_char(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)576 dissect_request_set_event_char(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
577 {
578     gint offset_start = offset;
579 
580     proto_tree_add_item(tree, hf_setup_lvalue_event_char, tvb, offset, 1, ENC_LITTLE_ENDIAN);
581     offset++;
582 
583     proto_tree_add_item(tree, hf_setup_hvalue_trigger, tvb, offset, 1, ENC_LITTLE_ENDIAN);
584     offset++;
585 
586     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
587     offset++;
588 
589     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
590     offset++;
591 
592     return offset - offset_start;
593 }
594 
595 static gint
dissect_request_set_error_char(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)596 dissect_request_set_error_char(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
597 {
598     gint offset_start = offset;
599 
600     proto_tree_add_item(tree, hf_setup_lvalue_error_char, tvb, offset, 1, ENC_LITTLE_ENDIAN);
601     offset++;
602 
603     proto_tree_add_item(tree, hf_setup_hvalue_error_replacement, tvb, offset, 1, ENC_LITTLE_ENDIAN);
604     offset++;
605 
606     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
607     offset++;
608 
609     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
610     offset++;
611 
612 
613     return offset - offset_start;
614 }
615 
616 static gint
dissect_request_set_lat_timer(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)617 dissect_request_set_lat_timer(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
618 {
619     gint offset_start = offset;
620 
621     proto_tree_add_item(tree, hf_setup_lvalue_latency_time, tvb, offset, 1, ENC_LITTLE_ENDIAN);
622     offset++;
623 
624     proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
625     offset++;
626 
627     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
628     offset++;
629 
630     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
631     offset++;
632 
633     return offset - offset_start;
634 }
635 
636 static gint
dissect_request_get_lat_timer(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)637 dissect_request_get_lat_timer(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
638 {
639     gint offset_start = offset;
640 
641     proto_tree_add_item(tree, hf_setup_lvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
642     offset++;
643 
644     proto_tree_add_item(tree, hf_setup_hvalue, tvb, offset, 1, ENC_LITTLE_ENDIAN);
645     offset++;
646 
647     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
648     offset++;
649 
650     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
651     offset++;
652 
653     return offset - offset_start;
654 }
655 
656 static gint
dissect_response_get_lat_timer(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)657 dissect_response_get_lat_timer(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
658 {
659     gint offset_start = offset;
660 
661     proto_tree_add_item(tree, hf_response_lat_timer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
662     offset++;
663 
664     return offset - offset_start;
665 }
666 
667 static gint
dissect_request_set_bitmode(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree)668 dissect_request_set_bitmode(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree)
669 {
670     gint offset_start = offset;
671 
672     proto_tree_add_item(tree, hf_setup_lvalue_bitmask, tvb, offset, 1, ENC_LITTLE_ENDIAN);
673     offset++;
674 
675     proto_tree_add_item(tree, hf_setup_hvalue_bitmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
676     offset++;
677 
678     proto_tree_add_item(tree, hf_setup_lindex_port_abcd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
679     offset++;
680 
681     proto_tree_add_item(tree, hf_setup_hindex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
682     offset++;
683 
684     return offset - offset_start;
685 }
686 
687 static gint
dissect_modem_status_bytes(tvbuff_t * tvb,packet_info * pinfo _U_,gint offset,proto_tree * tree,gint * out_rx_len)688 dissect_modem_status_bytes(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, proto_tree *tree, gint *out_rx_len)
689 {
690     static int * const modem_status_bits[] = {
691         &hf_modem_status_fs_max_packet,
692         &hf_modem_status_hs_max_packet,
693         &hf_modem_status_cts,
694         &hf_modem_status_dsr,
695         &hf_modem_status_ri,
696         &hf_modem_status_dcd,
697         NULL
698     };
699     static int * const line_status_bits[] = {
700         &hf_line_status_receive_overflow,
701         &hf_line_status_parity_error,
702         &hf_line_status_framing_error,
703         &hf_line_status_break_received,
704         &hf_line_status_tx_holding_reg_empty,
705         &hf_line_status_tx_empty,
706         NULL
707     };
708     guint64 modem_status;
709 
710     proto_tree_add_bitmask_ret_uint64(tree, tvb, offset, hf_modem_status,
711         ett_modem_status, modem_status_bits, ENC_LITTLE_ENDIAN, &modem_status);
712     offset++;
713 
714     proto_tree_add_bitmask(tree, tvb, offset, hf_line_status,
715         ett_line_status, line_status_bits, ENC_LITTLE_ENDIAN);
716     offset++;
717 
718     if (out_rx_len)
719     {
720         *out_rx_len = tvb_reported_length_remaining(tvb, offset);
721         if (modem_status & MODEM_STATUS_BIT_FS_64_MAX_PACKET)
722         {
723             /* 2 bytes modem status, 62 bytes payload */
724             *out_rx_len = MIN(*out_rx_len, 62);
725         }
726         else if (modem_status & MODEM_STATUS_BIT_HS_512_MAX_PACKET)
727         {
728             /* 2 bytes modem status, 510 bytes payload */
729             *out_rx_len = MIN(*out_rx_len, 510);
730         }
731     }
732 
733     return 2;
734 }
735 
736 static void
record_interface_mode(packet_info * pinfo,usb_conv_info_t * usb_conv_info,FTDI_INTERFACE interface,guint8 bitmode)737 record_interface_mode(packet_info *pinfo, usb_conv_info_t *usb_conv_info, FTDI_INTERFACE interface, guint8 bitmode)
738 {
739     guint32         k_bus_id = usb_conv_info->bus_id;
740     guint32         k_device_address = usb_conv_info->device_address;
741     guint32         k_interface = (guint32)interface;
742     wmem_tree_key_t key[] = {
743         {1, &k_bus_id},
744         {1, &k_device_address},
745         {1, &k_interface},
746         {1, &pinfo->num},
747         {0, NULL}
748     };
749     bitmode_data_t *bitmode_data = NULL;
750 
751     bitmode_data = wmem_new(wmem_file_scope(), bitmode_data_t);
752     bitmode_data->bus_id = usb_conv_info->bus_id;
753     bitmode_data->device_address = usb_conv_info->device_address;
754     bitmode_data->interface = interface;
755     bitmode_data->bitmode = bitmode;
756     wmem_tree_insert32_array(bitmode_info, key, bitmode_data);
757 }
758 
759 static guint8
get_recorded_interface_mode(packet_info * pinfo,usb_conv_info_t * usb_conv_info,FTDI_INTERFACE interface)760 get_recorded_interface_mode(packet_info *pinfo, usb_conv_info_t *usb_conv_info, FTDI_INTERFACE interface)
761 {
762     guint32         k_bus_id = usb_conv_info->bus_id;
763     guint32         k_device_address = usb_conv_info->device_address;
764     guint32         k_interface = (guint32)interface;
765     wmem_tree_key_t key[] = {
766         {1, &k_bus_id},
767         {1, &k_device_address},
768         {1, &k_interface},
769         {1, &pinfo->num},
770         {0, NULL}
771     };
772 
773     bitmode_data_t *bitmode_data = NULL;
774     bitmode_data = (bitmode_data_t *)wmem_tree_lookup32_array_le(bitmode_info, key);
775     if (bitmode_data && bitmode_data->bus_id == k_bus_id && bitmode_data->device_address == k_device_address &&
776         bitmode_data->interface == interface)
777     {
778         return bitmode_data->bitmode;
779     }
780 
781     return 0; /* Default to 0, which is plain serial data */
782 }
783 
784 static desegment_data_t *
record_desegment_data(packet_info * pinfo,usb_conv_info_t * usb_conv_info,FTDI_INTERFACE interface,guint8 bitmode)785 record_desegment_data(packet_info *pinfo, usb_conv_info_t *usb_conv_info,
786                       FTDI_INTERFACE interface, guint8 bitmode)
787 {
788     guint32         k_bus_id = usb_conv_info->bus_id;
789     guint32         k_device_address = usb_conv_info->device_address;
790     guint32         k_interface = (guint32)interface;
791     guint32         k_p2p_dir = (guint32)pinfo->p2p_dir;
792     wmem_tree_key_t key[] = {
793         {1, &k_bus_id},
794         {1, &k_device_address},
795         {1, &k_interface},
796         {1, &k_p2p_dir},
797         {1, &pinfo->num},
798         {0, NULL}
799     };
800     desegment_data_t *desegment_data = NULL;
801 
802     desegment_data = wmem_new(wmem_file_scope(), desegment_data_t);
803     desegment_data->bus_id = usb_conv_info->bus_id;
804     desegment_data->device_address = usb_conv_info->device_address;
805     desegment_data->interface = interface;
806     desegment_data->bitmode = bitmode;
807     desegment_data->p2p_dir = pinfo->p2p_dir;
808     desegment_data->first_frame = pinfo->num;
809     /* Last frame is currently unknown */
810     desegment_data->last_frame = 0;
811     desegment_data->first_frame_offset = 0;
812     desegment_data->previous = NULL;
813 
814     wmem_tree_insert32_array(desegment_info, key, desegment_data);
815     return desegment_data;
816 }
817 
818 static desegment_data_t *
get_recorded_desegment_data(packet_info * pinfo,usb_conv_info_t * usb_conv_info,FTDI_INTERFACE interface,guint8 bitmode)819 get_recorded_desegment_data(packet_info *pinfo, usb_conv_info_t *usb_conv_info,
820                             FTDI_INTERFACE interface, guint8 bitmode)
821 {
822     guint32         k_bus_id = usb_conv_info->bus_id;
823     guint32         k_device_address = usb_conv_info->device_address;
824     guint32         k_interface = (guint32)interface;
825     guint32         k_p2p_dir = (guint32)pinfo->p2p_dir;
826     wmem_tree_key_t key[] = {
827         {1, &k_bus_id},
828         {1, &k_device_address},
829         {1, &k_interface},
830         {1, &k_p2p_dir},
831         {1, &pinfo->num},
832         {0, NULL}
833     };
834 
835     desegment_data_t *desegment_data = NULL;
836     desegment_data = (desegment_data_t*)wmem_tree_lookup32_array_le(desegment_info, key);
837     if (desegment_data && desegment_data->bus_id == k_bus_id && desegment_data->device_address == k_device_address &&
838         desegment_data->interface == interface && desegment_data->bitmode == bitmode &&
839         desegment_data->p2p_dir == pinfo->p2p_dir)
840     {
841         /* Return desegment data only if it is relevant to current packet */
842         if ((desegment_data->last_frame == 0) || (desegment_data->last_frame >= pinfo->num))
843         {
844             return desegment_data;
845         }
846     }
847 
848     return NULL;
849 }
850 
ftdi_fragment_key_hash(gconstpointer k)851 static guint ftdi_fragment_key_hash(gconstpointer k)
852 {
853     const ftdi_fragment_key_t *key = (const ftdi_fragment_key_t *)k;
854     return key->id;
855 }
856 
ftdi_fragment_key_equal(gconstpointer k1,gconstpointer k2)857 static gint ftdi_fragment_key_equal(gconstpointer k1, gconstpointer k2)
858 {
859     const ftdi_fragment_key_t *key1 = (const ftdi_fragment_key_t *)k1;
860     const ftdi_fragment_key_t *key2 = (const ftdi_fragment_key_t *)k2;
861 
862     /* id is most likely to differ and thus should be checked first */
863     return (key1->id == key2->id) &&
864            (key1->bus_id == key2->bus_id) &&
865            (key1->device_address == key2->device_address) &&
866            (key1->interface == key2->interface) &&
867            (key1->bitmode == key2->bitmode) &&
868            (key1->p2p_dir == key2->p2p_dir);
869 }
870 
ftdi_fragment_key(const packet_info * pinfo _U_,const guint32 id,const void * data)871 static gpointer ftdi_fragment_key(const packet_info *pinfo _U_, const guint32 id, const void *data)
872 {
873     desegment_data_t *desegment_data = (desegment_data_t *)data;
874     ftdi_fragment_key_t *key = g_slice_new(ftdi_fragment_key_t);
875 
876     key->bus_id = desegment_data->bus_id;
877     key->device_address = desegment_data->device_address;
878     key->interface = desegment_data->interface;
879     key->bitmode = desegment_data->bitmode;
880     key->p2p_dir = desegment_data->p2p_dir;
881     key->id = id;
882 
883     return (gpointer)key;
884 }
885 
ftdi_fragment_free_key(gpointer ptr)886 static void ftdi_fragment_free_key(gpointer ptr)
887 {
888     ftdi_fragment_key_t *key = (ftdi_fragment_key_t *)ptr;
889     g_slice_free(ftdi_fragment_key_t, key);
890 }
891 
892 static const reassembly_table_functions ftdi_reassembly_table_functions = {
893     .hash_func = ftdi_fragment_key_hash,
894     .equal_func = ftdi_fragment_key_equal,
895     .temporary_key_func = ftdi_fragment_key,
896     .persistent_key_func = ftdi_fragment_key,
897     .free_temporary_key_func = ftdi_fragment_free_key,
898     .free_persistent_key_func = ftdi_fragment_free_key,
899 };
900 
901 static void
dissect_payload(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,usb_conv_info_t * usb_conv_info,FTDI_INTERFACE interface,guint8 bitmode)902 dissect_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, usb_conv_info_t *usb_conv_info,
903                 FTDI_INTERFACE interface, guint8 bitmode)
904 {
905     guint32           k_bus_id;
906     guint32           k_device_address;
907 
908     k_bus_id = usb_conv_info->bus_id;
909     k_device_address = usb_conv_info->device_address;
910 
911     if (tvb && ((bitmode == BITMODE_MPSSE) || (bitmode == BITMODE_MCU)))
912     {
913         ftdi_mpsse_info_t mpsse_info = {
914             .bus_id = k_bus_id,
915             .device_address = k_device_address,
916             .chip = identify_chip(usb_conv_info),
917             .iface = interface,
918             .mcu_mode = (bitmode == BITMODE_MCU),
919         };
920         call_dissector_with_data(ftdi_mpsse_handle, tvb, pinfo, tree, &mpsse_info);
921     }
922 }
923 
924 static gint
dissect_serial_payload(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * ftdi_tree,usb_conv_info_t * usb_conv_info,FTDI_INTERFACE interface)925 dissect_serial_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ftdi_tree,
926                        usb_conv_info_t *usb_conv_info, FTDI_INTERFACE interface)
927 {
928     guint16           save_can_desegment;
929     int               save_desegment_offset;
930     guint32           save_desegment_len;
931     desegment_data_t *desegment_data;
932     guint32           bytes;
933 
934     save_can_desegment = pinfo->can_desegment;
935     save_desegment_offset = pinfo->desegment_offset;
936     save_desegment_len = pinfo->desegment_len;
937 
938     bytes = tvb_reported_length(tvb);
939     if (bytes > 0)
940     {
941         tvbuff_t *payload_tvb = NULL;
942         guint32   reassembled_bytes = 0;
943         guint8    bitmode;
944         guint8    curr_layer_num = pinfo->curr_layer_num;
945 
946         bitmode = get_recorded_interface_mode(pinfo, usb_conv_info, interface);
947 
948         pinfo->can_desegment = 2;
949         pinfo->desegment_offset = 0;
950         pinfo->desegment_len = 0;
951 
952         desegment_data = get_recorded_desegment_data(pinfo, usb_conv_info, interface, bitmode);
953         if (desegment_data)
954         {
955             fragment_head    *fd_head;
956             desegment_data_t *next_desegment_data = NULL;
957 
958             if ((desegment_data->previous) && (desegment_data->first_frame == pinfo->num))
959             {
960                 DISSECTOR_ASSERT(desegment_data->previous->last_frame == pinfo->num);
961 
962                 next_desegment_data = desegment_data;
963                 desegment_data = desegment_data->previous;
964             }
965 
966             if (!PINFO_FD_VISITED(pinfo))
967             {
968                 /* Combine data reassembled so far with current tvb and check if this is last fragment or not */
969                 fragment_item *item;
970                 fd_head = fragment_get(&ftdi_reassembly_table, pinfo, desegment_data->first_frame, desegment_data);
971                 DISSECTOR_ASSERT(fd_head && !(fd_head->flags & FD_DEFRAGMENTED) && fd_head->next);
972                 payload_tvb = tvb_new_composite();
973                 for (item = fd_head->next; item; item = item->next)
974                 {
975                     DISSECTOR_ASSERT(reassembled_bytes == item->offset);
976                     tvb_composite_append(payload_tvb, item->tvb_data);
977                     reassembled_bytes += item->len;
978                 }
979                 tvb_composite_append(payload_tvb, tvb);
980                 tvb_composite_finalize(payload_tvb);
981             }
982             else
983             {
984                 fd_head = fragment_get_reassembled(&ftdi_reassembly_table, desegment_data->first_frame);
985                 payload_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled", fd_head,
986                                                        &ftdi_frag_items, NULL, ftdi_tree);
987             }
988 
989             if (next_desegment_data)
990             {
991                 fragment_head *next_head;
992                 next_head = fragment_get_reassembled(&ftdi_reassembly_table, next_desegment_data->first_frame);
993                 process_reassembled_data(tvb, 0, pinfo, "Reassembled", next_head, &ftdi_frag_items, NULL, ftdi_tree);
994             }
995 
996             if ((desegment_data->first_frame == pinfo->num) && (desegment_data->first_frame_offset > 0))
997             {
998                 payload_tvb = tvb_new_subset_length(tvb, 0, desegment_data->first_frame_offset);
999             }
1000         }
1001         else
1002         {
1003             /* Packet is not part of reassembly sequence, simply use it without modifications */
1004             payload_tvb = tvb;
1005         }
1006 
1007         dissect_payload(payload_tvb, pinfo, tree, usb_conv_info, interface, bitmode);
1008 
1009         if (!PINFO_FD_VISITED(pinfo))
1010         {
1011             /* FTDI FT dissector doesn't know if the last fragment is really the last one unless it passes
1012              * the data to the next dissector. There is absolutely no metadata that could help with it as
1013              * FTDI FT is pretty much a direct replacement to UART (COM port) and is pretty much transparent
1014              * to the actual serial protocol used.
1015              *
1016              * Passing the data to next dissector results in curr_layer_num being increased if it dissected
1017              * the data (when it is the last fragment). This would prevent the process_reassembled_data()
1018              * (after the first pass) from returning the reassembled tvb in FTFI FT which in turn prevents
1019              * the data from being passed to the next dissector.
1020              *
1021              * Override pinfo->curr_layer_num value when the fragments are being added to reassembly table.
1022              * This is ugly hack. Is there any better approach?
1023              *
1024              * There doesn't seem to be a mechanism to "back-track" just added fragments to reassembly table,
1025              * or any way to "shorten" the last added fragment. The most problematic case is when current
1026              * packet is both last packet for previous reassembly and a first packet for next reassembly.
1027              */
1028             guint8 save_curr_layer_num = pinfo->curr_layer_num;
1029             pinfo->curr_layer_num = curr_layer_num;
1030 
1031             if (!pinfo->desegment_len)
1032             {
1033                 if (desegment_data)
1034                 {
1035                     /* Current tvb is really the last fragment */
1036                     fragment_add_check(&ftdi_reassembly_table, tvb, 0, pinfo, desegment_data->first_frame,
1037                                        desegment_data, reassembled_bytes, bytes, FALSE);
1038                     desegment_data->last_frame = pinfo->num;
1039                 }
1040             }
1041             else
1042             {
1043                 DISSECTOR_ASSERT_HINT(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT,
1044                                       "FTDI FT supports only DESEGMENT_ONE_MORE_SEGMENT");
1045                 if (!desegment_data)
1046                 {
1047                     /* Start desegmenting */
1048                     gint fragment_length = tvb_reported_length_remaining(tvb, pinfo->desegment_offset);
1049                     desegment_data = record_desegment_data(pinfo, usb_conv_info, interface, bitmode);
1050                     desegment_data->first_frame_offset = pinfo->desegment_offset;
1051                     fragment_add_check(&ftdi_reassembly_table, tvb, pinfo->desegment_offset, pinfo,
1052                                        desegment_data->first_frame, desegment_data, 0, fragment_length, TRUE);
1053                 }
1054                 else if (pinfo->desegment_offset == 0)
1055                 {
1056                     /* Continue reassembling */
1057                     fragment_add_check(&ftdi_reassembly_table, tvb, 0, pinfo, desegment_data->first_frame,
1058                                        desegment_data, reassembled_bytes, bytes, TRUE);
1059                 }
1060                 else
1061                 {
1062                     gint fragment_length;
1063                     gint previous_bytes;
1064                     desegment_data_t *previous_desegment_data;
1065 
1066                     /* This packet contains both an end from a previous reassembly and start of a new one */
1067                     DISSECTOR_ASSERT((guint32)pinfo->desegment_offset > reassembled_bytes);
1068                     previous_bytes = pinfo->desegment_offset - reassembled_bytes;
1069                     fragment_add_check(&ftdi_reassembly_table, tvb, 0, pinfo, desegment_data->first_frame,
1070                                        desegment_data, reassembled_bytes, previous_bytes, FALSE);
1071                     desegment_data->last_frame = pinfo->num;
1072 
1073                     previous_desegment_data = desegment_data;
1074                     fragment_length = bytes - previous_bytes;
1075                     desegment_data = record_desegment_data(pinfo, usb_conv_info, interface, bitmode);
1076                     desegment_data->first_frame_offset = previous_bytes;
1077                     desegment_data->previous = previous_desegment_data;
1078                     fragment_add_check(&ftdi_reassembly_table, tvb, previous_bytes, pinfo, desegment_data->first_frame,
1079                                        desegment_data, 0, fragment_length, TRUE);
1080                 }
1081             }
1082 
1083             pinfo->curr_layer_num = save_curr_layer_num;
1084         }
1085     }
1086 
1087     pinfo->can_desegment = save_can_desegment;
1088     pinfo->desegment_offset = save_desegment_offset;
1089     pinfo->desegment_len = save_desegment_len;
1090 
1091     return bytes;
1092 }
1093 
1094 static gint
dissect_ftdi_ft(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1095 dissect_ftdi_ft(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1096 {
1097     proto_item       *main_item;
1098     proto_tree       *main_tree;
1099     gint              offset = 0;
1100     usb_conv_info_t  *usb_conv_info = (usb_conv_info_t *)data;
1101     request_data_t   *request_data = NULL;
1102     wmem_tree_key_t   key[4];
1103     guint32           k_bus_id;
1104     guint32           k_device_address;
1105 
1106     if (!usb_conv_info)
1107     {
1108         return offset;
1109     }
1110 
1111     if (usb_conv_info->is_setup)
1112     {
1113         /* This dissector can only process device Vendor specific setup data */
1114         if ((USB_TYPE(usb_conv_info->setup_requesttype) != RQT_SETUP_TYPE_VENDOR) ||
1115             (USB_RECIPIENT(usb_conv_info->setup_requesttype) != RQT_SETUP_RECIPIENT_DEVICE))
1116         {
1117             return offset;
1118         }
1119     }
1120 
1121     k_bus_id = usb_conv_info->bus_id;
1122     k_device_address = usb_conv_info->device_address;
1123 
1124     key[0].length = 1;
1125     key[0].key = &k_bus_id;
1126     key[1].length = 1;
1127     key[1].key = &k_device_address;
1128     key[2].length = 1;
1129     key[2].key = &pinfo->num;
1130     key[3].length = 0;
1131     key[3].key = NULL;
1132 
1133     main_item = proto_tree_add_item(tree, proto_ftdi_ft, tvb, offset, -1, ENC_NA);
1134     main_tree = proto_item_add_subtree(main_item, ett_ftdi_ft);
1135 
1136     if (usb_conv_info->transfer_type == URB_CONTROL)
1137     {
1138         col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTDI FT");
1139         col_set_str(pinfo->cinfo, COL_INFO, "FTDI FT ");
1140         col_append_str(pinfo->cinfo, COL_INFO, usb_conv_info->is_request ? "Request" : "Response");
1141 
1142         if (usb_conv_info->is_setup)
1143         {
1144             gint         bytes_dissected;
1145             guint8       brequest;
1146             guint8       hvalue;
1147             guint8       lindex;
1148 
1149             brequest = tvb_get_guint8(tvb, offset);
1150             col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
1151                 val_to_str_ext_const(brequest, &request_vals_ext, "Unknown"));
1152             proto_tree_add_item(main_tree, hf_setup_brequest, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1153             offset++;
1154 
1155             hvalue = tvb_get_guint8(tvb, offset + 1);
1156             lindex = tvb_get_guint8(tvb, offset + 2);
1157 
1158             switch (brequest)
1159             {
1160             case REQUEST_RESET:
1161                 bytes_dissected = dissect_request_reset(tvb, pinfo, offset, main_tree);
1162                 break;
1163             case REQUEST_MODEM_CTRL:
1164                 bytes_dissected = dissect_request_modem_ctrl(tvb, pinfo, offset, main_tree);
1165                 break;
1166             case REQUEST_SET_FLOW_CTRL:
1167                 bytes_dissected = dissect_request_set_flow_ctrl(tvb, pinfo, offset, main_tree);
1168                 break;
1169             case REQUEST_SET_BAUD_RATE:
1170             {
1171                 FTDI_CHIP chip = identify_chip(usb_conv_info);
1172                 bytes_dissected = dissect_request_set_baud_rate(tvb, pinfo, offset, main_tree, chip);
1173                 break;
1174             }
1175             case REQUEST_SET_DATA:
1176                 bytes_dissected = dissect_request_set_data(tvb, pinfo, offset, main_tree);
1177                 break;
1178             case REQUEST_GET_MODEM_STAT:
1179                 bytes_dissected = dissect_request_get_modem_stat(tvb, pinfo, offset, main_tree);
1180                 break;
1181             case REQUEST_SET_EVENT_CHAR:
1182                 bytes_dissected = dissect_request_set_event_char(tvb, pinfo, offset, main_tree);
1183                 break;
1184             case REQUEST_SET_ERROR_CHAR:
1185                 bytes_dissected = dissect_request_set_error_char(tvb, pinfo, offset, main_tree);
1186                 break;
1187             case REQUEST_SET_LAT_TIMER:
1188                 bytes_dissected = dissect_request_set_lat_timer(tvb, pinfo, offset, main_tree);
1189                 break;
1190             case REQUEST_GET_LAT_TIMER:
1191                 bytes_dissected = dissect_request_get_lat_timer(tvb, pinfo, offset, main_tree);
1192                 break;
1193             case REQUEST_SET_BITMODE:
1194                 bytes_dissected = dissect_request_set_bitmode(tvb, pinfo, offset, main_tree);
1195                 break;
1196             default:
1197                 bytes_dissected = 0;
1198                 break;
1199             }
1200 
1201             offset += bytes_dissected;
1202             if (bytes_dissected < 4)
1203             {
1204                 proto_tree_add_expert(main_tree, pinfo, &ei_undecoded, tvb, offset, 4 - bytes_dissected);
1205                 offset += 4 - bytes_dissected;
1206             }
1207 
1208             proto_tree_add_item(main_tree, hf_setup_wlength, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1209             offset += 2;
1210 
1211             /* Record the request type so we can find it when dissecting response */
1212             request_data = wmem_new(wmem_file_scope(), request_data_t);
1213             request_data->bus_id = usb_conv_info->bus_id;
1214             request_data->device_address = usb_conv_info->device_address;
1215             request_data->request = brequest;
1216             request_data->hvalue = hvalue;
1217             request_data->lindex = lindex;
1218             wmem_tree_insert32_array(request_info, key, request_data);
1219         }
1220         else
1221         {
1222             /* Retrieve request type */
1223             request_data = (request_data_t *)wmem_tree_lookup32_array_le(request_info, key);
1224             if (request_data && request_data->bus_id == k_bus_id && request_data->device_address == k_device_address)
1225             {
1226                 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
1227                     val_to_str_ext_const(request_data->request, &request_vals_ext, "Unknown"));
1228 
1229                 switch (request_data->request)
1230                 {
1231                 case REQUEST_GET_MODEM_STAT:
1232                     offset += dissect_modem_status_bytes(tvb, pinfo, offset, main_tree, NULL);
1233                     break;
1234                 case REQUEST_GET_LAT_TIMER:
1235                     offset += dissect_response_get_lat_timer(tvb, pinfo, offset, main_tree);
1236                     break;
1237                 case REQUEST_SET_BITMODE:
1238                     /* TODO: Record interface mode only if the control request has succeeded */
1239                     record_interface_mode(pinfo, usb_conv_info, lindex_to_interface(request_data->lindex), request_data->hvalue);
1240                     break;
1241                 default:
1242                     break;
1243                 }
1244             }
1245             else
1246             {
1247                 col_append_str(pinfo->cinfo, COL_INFO, ": Unknown");
1248             }
1249 
1250             /* Report any potentially undissected response data */
1251             if (tvb_reported_length_remaining(tvb, offset) > 0)
1252             {
1253                 proto_tree_add_expert(main_tree, pinfo, &ei_undecoded, tvb, offset, -1);
1254             }
1255         }
1256     }
1257     else
1258     {
1259         const char *interface_str;
1260         FTDI_INTERFACE interface;
1261         gint rx_hf, tx_hf;
1262 
1263         interface = endpoint_to_interface(usb_conv_info);
1264         switch (interface)
1265         {
1266         case FTDI_INTERFACE_A:
1267             interface_str = "A";
1268             rx_hf = hf_if_a_rx_payload;
1269             tx_hf = hf_if_a_tx_payload;
1270             break;
1271         case FTDI_INTERFACE_B:
1272             interface_str = "B";
1273             rx_hf = hf_if_b_rx_payload;
1274             tx_hf = hf_if_b_tx_payload;
1275             break;
1276         case FTDI_INTERFACE_C:
1277             interface_str = "C";
1278             rx_hf = hf_if_c_rx_payload;
1279             tx_hf = hf_if_c_tx_payload;
1280             break;
1281         case FTDI_INTERFACE_D:
1282             interface_str = "D";
1283             rx_hf = hf_if_d_rx_payload;
1284             tx_hf = hf_if_d_tx_payload;
1285             break;
1286         default:
1287             return offset;
1288         }
1289 
1290         col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTDI FT");
1291         if (pinfo->p2p_dir == P2P_DIR_RECV)
1292         {
1293             gint total_rx_len = 0;
1294             gint rx_len;
1295             tvbuff_t *rx_tvb = tvb_new_composite();
1296 
1297             col_add_fstr(pinfo->cinfo, COL_INFO, "INTERFACE %s RX", interface_str);
1298 
1299             do
1300             {
1301                 /* First two bytes are status */
1302                 offset += dissect_modem_status_bytes(tvb, pinfo, offset, main_tree, &rx_len);
1303                 total_rx_len += rx_len;
1304 
1305                 if (rx_len > 0)
1306                 {
1307                     tvbuff_t *rx_tvb_fragment = tvb_new_subset_length(tvb, offset, rx_len);
1308                     tvb_composite_append(rx_tvb, rx_tvb_fragment);
1309                     proto_tree_add_item(main_tree, rx_hf, tvb, offset, rx_len, ENC_NA);
1310                     offset += rx_len;
1311                 }
1312             }
1313             while (tvb_reported_length_remaining(tvb, offset) > 0);
1314 
1315             if (total_rx_len > 0)
1316             {
1317                 tvb_composite_finalize(rx_tvb);
1318                 col_append_fstr(pinfo->cinfo, COL_INFO, " %d bytes", total_rx_len);
1319                 add_new_data_source(pinfo, rx_tvb, "RX Payload");
1320                 dissect_serial_payload(rx_tvb, pinfo, tree, main_tree, usb_conv_info, interface);
1321             }
1322             else
1323             {
1324                 tvb_free_chain(rx_tvb);
1325             }
1326         }
1327         else
1328         {
1329             gint bytes;
1330 
1331             col_add_fstr(pinfo->cinfo, COL_INFO, "INTERFACE %s TX", interface_str);
1332             bytes = tvb_reported_length_remaining(tvb, offset);
1333 
1334             if (bytes > 0)
1335             {
1336                 tvbuff_t *tx_tvb;
1337 
1338                 col_append_fstr(pinfo->cinfo, COL_INFO, " %d bytes", bytes);
1339                 proto_tree_add_item(main_tree, tx_hf, tvb, offset, bytes, ENC_NA);
1340 
1341                 tx_tvb = tvb_new_subset_length(tvb, offset, bytes);
1342                 add_new_data_source(pinfo, tx_tvb, "TX Payload");
1343                 dissect_serial_payload(tx_tvb, pinfo, tree, main_tree, usb_conv_info, interface);
1344                 offset += bytes;
1345             }
1346         }
1347     }
1348 
1349     return offset;
1350 }
1351 
1352 void
proto_register_ftdi_ft(void)1353 proto_register_ftdi_ft(void)
1354 {
1355     expert_module_t  *expert_module;
1356 
1357     static hf_register_info hf[] = {
1358         { &hf_setup_brequest,
1359           { "Request", "ftdi-ft.bRequest",
1360             FT_UINT8, BASE_DEC | BASE_EXT_STRING, &request_vals_ext, 0x0,
1361             NULL, HFILL }
1362         },
1363         { &hf_setup_lvalue,
1364           { "lValue", "ftdi-ft.lValue",
1365             FT_UINT8, BASE_HEX, NULL, 0x0,
1366             NULL, HFILL }
1367         },
1368         { &hf_setup_lvalue_purge,
1369           { "lValue", "ftdi-ft.lValue",
1370             FT_UINT8, BASE_HEX, VALS(reset_purge_vals), 0x0,
1371             NULL, HFILL }
1372         },
1373         { &hf_setup_lvalue_dtr,
1374           { "DTR Active", "ftdi-ft.lValue.b0",
1375             FT_BOOLEAN, 8, NULL, (1 << 0),
1376             NULL, HFILL }
1377         },
1378         { &hf_setup_lvalue_rts,
1379           { "RTS Active", "ftdi-ft.lValue.b1",
1380             FT_BOOLEAN, 8, NULL, (1 << 1),
1381             NULL, HFILL }
1382         },
1383         { &hf_setup_lvalue_xon_char,
1384           { "XON Char", "ftdi-ft.lValue",
1385             FT_UINT8, BASE_HEX, NULL, 0x0,
1386             NULL, HFILL }
1387         },
1388         { &hf_setup_lvalue_baud_low,
1389           { "Baud low", "ftdi-ft.lValue",
1390             FT_UINT8, BASE_HEX, NULL, 0x0,
1391             NULL, HFILL }
1392         },
1393         { &hf_setup_lvalue_data_size,
1394           { "Data Size", "ftdi-ft.lValue",
1395             FT_UINT8, BASE_HEX, VALS(data_size_vals), 0x0,
1396             NULL, HFILL }
1397         },
1398         { &hf_setup_lvalue_event_char,
1399           { "Event Char", "ftdi-ft.lValue",
1400             FT_UINT8, BASE_HEX, NULL, 0x0,
1401             NULL, HFILL }
1402         },
1403         { &hf_setup_lvalue_error_char,
1404           { "Parity Error Char", "ftdi-ft.lValue",
1405             FT_UINT8, BASE_HEX, NULL, 0x0,
1406             NULL, HFILL }
1407         },
1408         { &hf_setup_lvalue_latency_time,
1409           { "Latency Time", "ftdi-ft.lValue",
1410             FT_UINT8, BASE_DEC, NULL, 0x0,
1411             "Latency time in milliseconds", HFILL }
1412         },
1413         { &hf_setup_lvalue_bitmask,
1414           { "Bit Mask", "ftdi-ft.lValue",
1415             FT_UINT8, BASE_HEX, NULL, 0x0,
1416             NULL, HFILL }
1417         },
1418         { &hf_setup_hvalue,
1419           { "hValue", "ftdi-ft.hValue",
1420             FT_UINT8, BASE_HEX, NULL, 0x0,
1421             NULL, HFILL }
1422         },
1423         { &hf_setup_hvalue_dtr,
1424           { "en DTR for writing", "ftdi-ft.hValue.b0",
1425             FT_BOOLEAN, 8, NULL, (1 << 0),
1426             NULL, HFILL }
1427         },
1428         { &hf_setup_hvalue_rts,
1429           { "en RTS for writing", "ftdi-ft.hValue.b1",
1430             FT_BOOLEAN, 8, NULL, (1 << 1),
1431             NULL, HFILL }
1432         },
1433         { &hf_setup_hvalue_xoff_char,
1434           { "XOFF Char", "ftdi-ft.hValue",
1435             FT_UINT8, BASE_HEX, NULL, 0x0,
1436             NULL, HFILL }
1437         },
1438         { &hf_setup_hvalue_baud_mid,
1439           { "Baud mid", "ftdi-ft.hValue",
1440             FT_UINT8, BASE_HEX, NULL, 0x0,
1441             NULL, HFILL }
1442         },
1443         { &hf_setup_hvalue_parity,
1444           { "Parity", "ftdi-ft.hValue.parity",
1445             FT_UINT8, BASE_HEX, VALS(parity_vals), (0x7 << 0),
1446             NULL, HFILL }
1447         },
1448         { &hf_setup_hvalue_stop_bits,
1449           { "Stop Bits", "ftdi-ft.hValue.b4",
1450             FT_UINT8, BASE_HEX, VALS(stop_bits_vals), (1 << 4),
1451             NULL, HFILL }
1452         },
1453         { &hf_setup_hvalue_break_bit,
1454           { "Break Bit", "ftdi-ft.hValue.b6",
1455             FT_UINT8, BASE_HEX, VALS(break_bit_vals), (1 << 6),
1456             NULL, HFILL }
1457         },
1458         { &hf_setup_hvalue_trigger,
1459           { "hValue", "ftdi-ft.hValue",
1460             FT_UINT8, BASE_HEX, VALS(event_char_trigger_vals), 0x0,
1461             NULL, HFILL }
1462         },
1463         { &hf_setup_hvalue_error_replacement,
1464           { "hValue", "ftdi-ft.hValue",
1465             FT_UINT8, BASE_HEX, VALS(error_replacement_vals), 0x0,
1466             NULL, HFILL }
1467         },
1468         { &hf_setup_hvalue_bitmode,
1469           { "Bit Mode", "ftdi-ft.hValue",
1470             FT_UINT8, BASE_HEX, VALS(bitmode_vals), 0x0,
1471             NULL, HFILL }
1472         },
1473         { &hf_setup_lindex,
1474           { "lIndex", "ftdi-ft.lIndex",
1475             FT_UINT8, BASE_HEX, NULL, 0x0,
1476             NULL, HFILL }
1477         },
1478         { &hf_setup_lindex_port_ab,
1479           { "lIndex", "ftdi-ft.lIndex",
1480             FT_UINT8, BASE_HEX, VALS(index_port_ab_vals), 0x0,
1481             NULL, HFILL }
1482         },
1483         { &hf_setup_lindex_port_abcd,
1484           { "lIndex", "ftdi-ft.lIndex",
1485             FT_UINT8, BASE_HEX, VALS(index_port_abcd_vals), 0x0,
1486             NULL, HFILL }
1487         },
1488         { &hf_setup_lindex_baud_high,
1489           { "Baud High", "ftdi-ft.lIndex.b0",
1490             FT_UINT8, BASE_HEX, NULL, (1 << 0),
1491             NULL, HFILL }
1492         },
1493         { &hf_setup_hindex,
1494           { "hIndex", "ftdi-ft.hIndex",
1495             FT_UINT8, BASE_HEX, NULL, 0x0,
1496             NULL, HFILL }
1497         },
1498         { &hf_setup_hindex_rts_cts,
1499           { "RTS/CTS Flow Control", "ftdi-ft.hIndex.b0",
1500             FT_BOOLEAN, 8, NULL, (1 << 0),
1501             NULL, HFILL }
1502         },
1503         { &hf_setup_hindex_dtr_dsr,
1504           { "DTR/DSR Flow Control", "ftdi-ft.hIndex.b1",
1505             FT_BOOLEAN, 8, NULL, (1 << 1),
1506             NULL, HFILL }
1507         },
1508         { &hf_setup_hindex_xon_xoff,
1509           { "XON/XOFF Flow Control", "ftdi-ft.hIndex.b2",
1510             FT_BOOLEAN, 8, NULL, (1 << 2),
1511             NULL, HFILL }
1512         },
1513         { &hf_setup_hindex_baud_high,
1514           { "Baud High", "ftdi-ft.baud_high.b0",
1515             FT_UINT8, BASE_HEX, NULL, (1 << 0),
1516             NULL, HFILL }
1517         },
1518         { &hf_setup_hindex_baud_clock_divide,
1519           { "Baud Clock Divide off", "ftdi-ft.baud_clock_divide.b1",
1520             FT_BOOLEAN, 8, NULL, (1 << 1),
1521             "When active 120 MHz is max frequency instead of 48 MHz", HFILL }
1522         },
1523         { &hf_setup_wlength,
1524           { "wLength", "ftdi-ft.wLength",
1525             FT_UINT16, BASE_DEC, NULL, 0x0,
1526             NULL, HFILL }
1527         },
1528         { &hf_response_lat_timer,
1529           { "Latency Time", "ftdi-ft.latency_time",
1530             FT_UINT8, BASE_DEC, NULL, 0x0,
1531             "Latency time in milliseconds", HFILL }
1532         },
1533         { &hf_modem_status,
1534           { "Modem Status", "ftdi-ft.modem_status",
1535             FT_UINT8, BASE_HEX, NULL, 0x0,
1536             NULL, HFILL }
1537         },
1538         { &hf_modem_status_fs_max_packet,
1539           { "Full Speed 64 byte MAX packet", "ftdi-ft.modem_status.b0",
1540             FT_BOOLEAN, 8, NULL, (1 << 0),
1541             NULL, HFILL }
1542         },
1543         { &hf_modem_status_hs_max_packet,
1544           { "High Speed 512 byte MAX packet", "ftdi-ft.modem_status.b1",
1545             FT_BOOLEAN, 8, NULL, (1 << 1),
1546             NULL, HFILL }
1547         },
1548         { &hf_modem_status_cts,
1549           { "CTS", "ftdi-ft.modem_status.b4",
1550             FT_BOOLEAN, 8, NULL, (1 << 4),
1551             NULL, HFILL }
1552         },
1553         { &hf_modem_status_dsr,
1554           { "DSR", "ftdi-ft.modem_status.b5",
1555             FT_BOOLEAN, 8, NULL, (1 << 5),
1556             NULL, HFILL }
1557         },
1558         { &hf_modem_status_ri,
1559           { "RI", "ftdi-ft.modem_status.b6",
1560             FT_BOOLEAN, 8, NULL, (1 << 6),
1561             NULL, HFILL }
1562         },
1563         { &hf_modem_status_dcd,
1564           { "DCD", "ftdi-ft.modem_status.b7",
1565             FT_BOOLEAN, 8, NULL, (1 << 7),
1566             NULL, HFILL }
1567         },
1568         { &hf_line_status,
1569           { "Line Status", "ftdi-ft.line_status",
1570             FT_UINT8, BASE_HEX, NULL, 0x0,
1571             NULL, HFILL }
1572         },
1573         { &hf_line_status_receive_overflow,
1574           { "Receive Overflow Error", "ftdi-ft.line_status.b1",
1575             FT_BOOLEAN, 8, NULL, (1 << 1),
1576             NULL, HFILL }
1577         },
1578         { &hf_line_status_parity_error,
1579           { "Parity Error", "ftdi-ft.line_status.b2",
1580             FT_BOOLEAN, 8, NULL, (1 << 2),
1581             NULL, HFILL }
1582         },
1583         { &hf_line_status_framing_error,
1584           { "Framing Error", "ftdi-ft.line_status.b3",
1585             FT_BOOLEAN, 8, NULL, (1 << 3),
1586             NULL, HFILL }
1587         },
1588         { &hf_line_status_break_received,
1589           { "Break Received", "ftdi-ft.line_status.b4",
1590             FT_BOOLEAN, 8, NULL, (1 << 4),
1591             NULL, HFILL }
1592         },
1593         { &hf_line_status_tx_holding_reg_empty,
1594           { "Transmitter Holding Register Empty", "ftdi-ft.line_status.b5",
1595             FT_BOOLEAN, 8, NULL, (1 << 5),
1596             NULL, HFILL }
1597         },
1598         { &hf_line_status_tx_empty,
1599           { "Transmitter Empty", "ftdi-ft.line_status.b6",
1600             FT_BOOLEAN, 8, NULL, (1 << 6),
1601             NULL, HFILL }
1602         },
1603         { &hf_if_a_rx_payload,
1604           { "A RX payload", "ftdi-ft.if_a_rx_payload",
1605             FT_BYTES, BASE_NONE, NULL, 0x0,
1606             "Data received on interface A", HFILL }
1607         },
1608         { &hf_if_a_tx_payload,
1609           { "A TX payload", "ftdi-ft.if_a_tx_payload",
1610             FT_BYTES, BASE_NONE, NULL, 0x0,
1611             "Data to transmit on interface A", HFILL }
1612         },
1613         { &hf_if_b_rx_payload,
1614           { "B RX payload", "ftdi-ft.if_b_rx_payload",
1615             FT_BYTES, BASE_NONE, NULL, 0x0,
1616             "Data received on interface B", HFILL }
1617         },
1618         { &hf_if_b_tx_payload,
1619           { "B TX payload", "ftdi-ft.if_b_tx_payload",
1620             FT_BYTES, BASE_NONE, NULL, 0x0,
1621             "Data to transmit on interface B", HFILL }
1622         },
1623         { &hf_if_c_rx_payload,
1624           { "C RX payload", "ftdi-ft.if_c_rx_payload",
1625             FT_BYTES, BASE_NONE, NULL, 0x0,
1626             "Data received on interface C", HFILL }
1627         },
1628         { &hf_if_c_tx_payload,
1629           { "C TX payload", "ftdi-ft.if_c_tx_payload",
1630             FT_BYTES, BASE_NONE, NULL, 0x0,
1631             "Data to transmit on interface C", HFILL }
1632         },
1633         { &hf_if_d_rx_payload,
1634           { "D RX payload", "ftdi-ft.if_d_rx_payload",
1635             FT_BYTES, BASE_NONE, NULL, 0x0,
1636             "Data received on interface D", HFILL }
1637         },
1638         { &hf_if_d_tx_payload,
1639           { "D TX payload", "ftdi-ft.if_d_tx_payload",
1640             FT_BYTES, BASE_NONE, NULL, 0x0,
1641             "Data to transmit on interface D", HFILL }
1642         },
1643         { &hf_ftdi_fragments,
1644           { "Payload fragments", "ftdi-ft.fragments",
1645             FT_NONE, BASE_NONE, NULL, 0x0,
1646             NULL, HFILL }
1647         },
1648         { &hf_ftdi_fragment,
1649           { "Payload fragment", "ftdi-ft.fragment",
1650             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1651             NULL, HFILL }
1652         },
1653         { &hf_ftdi_fragment_overlap,
1654           { "Payload fragment overlap", "ftdi-ft.fragment.overlap",
1655             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1656             NULL, HFILL }
1657         },
1658         { &hf_ftdi_fragment_overlap_conflicts,
1659           { "Payload fragment overlapping with conflicting data", "ftdi-ft.fragment.overlap.conflicts",
1660             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1661             NULL, HFILL }
1662         },
1663         { &hf_ftdi_fragment_multiple_tails,
1664           { "Payload has multiple tails", "ftdi-ft.fragment.multiple_tails",
1665             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1666             NULL, HFILL}
1667         },
1668         { &hf_ftdi_fragment_too_long_fragment,
1669           { "Payload fragment too long", "ftdi-ft.fragment.too_long_fragment",
1670             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1671             NULL, HFILL }
1672         },
1673         { &hf_ftdi_fragment_error,
1674           { "Payload defragmentation error", "ftdi-ft.fragment.error",
1675             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1676             NULL, HFILL }
1677         },
1678         { &hf_ftdi_fragment_count,
1679           { "Payload fragment count", "ftdi-ft.fragment.count",
1680             FT_UINT32, BASE_DEC, NULL, 0x0,
1681             NULL, HFILL }
1682         },
1683         { &hf_ftdi_reassembled_in,
1684           { "Payload reassembled in", "ftdi-ft.reassembled.in",
1685             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1686             NULL, HFILL }
1687         },
1688         { &hf_ftdi_reassembled_length,
1689           { "Payload reassembled length", "ftdi-ft.reassembled.length",
1690             FT_UINT32, BASE_DEC, NULL, 0x0,
1691             NULL, HFILL }
1692         },
1693     };
1694 
1695     static ei_register_info ei[] = {
1696         { &ei_undecoded, { "ftdi-ft.undecoded", PI_UNDECODED, PI_WARN, "Not dissected yet (report to wireshark.org)", EXPFILL }},
1697     };
1698 
1699     static gint *ett[] = {
1700         &ett_ftdi_ft,
1701         &ett_modem_ctrl_lvalue,
1702         &ett_modem_ctrl_hvalue,
1703         &ett_flow_ctrl_hindex,
1704         &ett_baudrate_lindex,
1705         &ett_baudrate_hindex,
1706         &ett_setdata_hvalue,
1707         &ett_modem_status,
1708         &ett_line_status,
1709         &ett_ftdi_fragment,
1710         &ett_ftdi_fragments,
1711     };
1712 
1713     request_info = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1714     bitmode_info = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1715     desegment_info = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1716 
1717     proto_ftdi_ft = proto_register_protocol("FTDI FT USB", "FTDI FT", "ftdi-ft");
1718     proto_register_field_array(proto_ftdi_ft, hf, array_length(hf));
1719     proto_register_subtree_array(ett, array_length(ett));
1720     ftdi_ft_handle = register_dissector("ftdi-ft", dissect_ftdi_ft, proto_ftdi_ft);
1721 
1722     expert_module = expert_register_protocol(proto_ftdi_ft);
1723     expert_register_field_array(expert_module, ei, array_length(ei));
1724 
1725     reassembly_table_register(&ftdi_reassembly_table, &ftdi_reassembly_table_functions);
1726 }
1727 
1728 void
proto_reg_handoff_ftdi_ft(void)1729 proto_reg_handoff_ftdi_ft(void)
1730 {
1731     /* TODO: Add configuration option to specify VID and PID.
1732      * The values below denote default VID/PID of FT converters (as of 2019)
1733      * The VID and PID can be changed by hardware vendor.
1734      */
1735     dissector_add_uint("usb.product", (0x0403 << 16) | 0x6001, ftdi_ft_handle);
1736     dissector_add_uint("usb.product", (0x0403 << 16) | 0x6010, ftdi_ft_handle);
1737     dissector_add_uint("usb.product", (0x0403 << 16) | 0x6011, ftdi_ft_handle);
1738     dissector_add_uint("usb.product", (0x0403 << 16) | 0x6014, ftdi_ft_handle);
1739     dissector_add_uint("usb.product", (0x0403 << 16) | 0x6015, ftdi_ft_handle);
1740 
1741     /* Devices that use FTDI FT converter with changed Vendor ID and/or Product ID */
1742     dissector_add_uint("usb.product", (0x0403 << 16) | 0xcff8, ftdi_ft_handle); /* Amontec JTAGkey */
1743     dissector_add_uint("usb.product", (0x15ba << 16) | 0x0003, ftdi_ft_handle); /* Olimex ARM-USB-OCD */
1744     dissector_add_uint("usb.product", (0x15ba << 16) | 0x0004, ftdi_ft_handle); /* Olimex ARM-USB-TINY */
1745     dissector_add_uint("usb.product", (0x15ba << 16) | 0x002a, ftdi_ft_handle); /* Olimex ARM-USB-TINY-H */
1746     dissector_add_uint("usb.product", (0x15ba << 16) | 0x002b, ftdi_ft_handle); /* Olimex ARM-USB-OCD-H */
1747     dissector_add_uint("usb.product", (0x1d50 << 16) | 0x607c, ftdi_ft_handle); /* OpenVizsla USB sniffer/analyzer */
1748 
1749     dissector_add_for_decode_as("usb.device", ftdi_ft_handle);
1750 
1751     ftdi_mpsse_handle = find_dissector_add_dependency("ftdi-mpsse", proto_ftdi_ft);
1752 }
1753 
1754 /*
1755  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1756  *
1757  * Local variables:
1758  * c-basic-offset: 4
1759  * tab-width: 8
1760  * indent-tabs-mode: nil
1761  * End:
1762  *
1763  * vi: set shiftwidth=4 tabstop=8 expandtab:
1764  * :indentSize=4:tabSize=8:noTabs=true:
1765  */
1766