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