aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-ftdi-ft.c3
-rw-r--r--epan/dissectors/packet-ftdi-ft.h1
-rw-r--r--epan/dissectors/packet-ftdi-mpsse.c67
3 files changed, 64 insertions, 7 deletions
diff --git a/epan/dissectors/packet-ftdi-ft.c b/epan/dissectors/packet-ftdi-ft.c
index 58e3da422c..05939d2b64 100644
--- a/epan/dissectors/packet-ftdi-ft.c
+++ b/epan/dissectors/packet-ftdi-ft.c
@@ -732,13 +732,14 @@ dissect_serial_payload(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tre
guint8 bitmode;
bitmode = get_recorded_interface_mode(pinfo, usb_conv_info, interface);
- if (bitmode == BITMODE_MPSSE)
+ if ((bitmode == BITMODE_MPSSE) || (bitmode == BITMODE_MCU))
{
ftdi_mpsse_info_t mpsse_info = {
.bus_id = k_bus_id,
.device_address = k_device_address,
.chip = identify_chip(usb_conv_info),
.iface = interface,
+ .mcu_mode = (bitmode == BITMODE_MCU),
};
tvbuff_t *mpsse_payload_tvb = tvb_new_subset_remaining(tvb, offset);
call_dissector_with_data(ftdi_mpsse_handle, mpsse_payload_tvb, pinfo, tree, &mpsse_info);
diff --git a/epan/dissectors/packet-ftdi-ft.h b/epan/dissectors/packet-ftdi-ft.h
index 79d83cc540..f5830c117e 100644
--- a/epan/dissectors/packet-ftdi-ft.h
+++ b/epan/dissectors/packet-ftdi-ft.h
@@ -40,6 +40,7 @@ typedef struct _ftdi_mpsse_info_t {
guint32 device_address;
FTDI_CHIP chip;
FTDI_INTERFACE iface;
+ gboolean mcu_mode;
} ftdi_mpsse_info_t;
#endif /* __PACKET_FTDI_FT_H__ */
diff --git a/epan/dissectors/packet-ftdi-mpsse.c b/epan/dissectors/packet-ftdi-mpsse.c
index c8e48b1da0..8f96243d8e 100644
--- a/epan/dissectors/packet-ftdi-mpsse.c
+++ b/epan/dissectors/packet-ftdi-mpsse.c
@@ -30,6 +30,8 @@ static gint hf_mpsse_command_b5 = -1;
static gint hf_mpsse_command_b6 = -1;
static gint hf_mpsse_command_b7 = -1;
static gint hf_mpsse_command_with_parameters = -1;
+static gint hf_mpsse_bad_command_error = -1;
+static gint hf_mpsse_bad_command_code = -1;
static gint hf_mpsse_response = -1;
static gint hf_mpsse_command_in = -1;
static gint hf_mpsse_response_in = -1;
@@ -144,13 +146,18 @@ static const value_string command_vals[] = {
{0x87, "Send Immediate (flush buffer back to the PC)"},
{0x88, "Wait On I/O High (wait until GPIOL1 (JTAG) or I/O1 (CPU) is high)"},
{0x89, "Wait On I/O Low (wait until GPIOL1 (JTAG) or I/O1 (CPU) is low)"},
+ {0, NULL}
+};
+static value_string_ext command_vals_ext = VALUE_STRING_EXT_INIT(command_vals);
+
+static const value_string cpumode_command_vals[] = {
{CMD_CPUMODE_READ_SHORT_ADDR, "CPUMode Read Short Address"},
{CMD_CPUMODE_READ_EXT_ADDR, "CPUMode Read Extended Address"},
{CMD_CPUMODE_WRITE_SHORT_ADDR, "CPUMode Write Short Address"},
{CMD_CPUMODE_WRITE_EXT_ADDR, "CPUMode Write Extended Address"},
{0, NULL}
};
-static value_string_ext command_vals_ext = VALUE_STRING_EXT_INIT(command_vals);
+static value_string_ext cpumode_command_vals_ext = VALUE_STRING_EXT_INIT(cpumode_command_vals);
static const value_string ft2232d_only_command_vals[] = {
{CMD_CLOCK_SET_DIVISOR, "Set TCK/SK Divisor"},
@@ -201,6 +208,7 @@ static const value_string command_b7_vals[] = {
#define IS_DATA_SHIFTING_COMMAND_BIT_ACTIVE(cmd) ((cmd & (1u << 7)) == 0)
#define IS_DATA_SHIFTING_BYTE_MODE(cmd) ((cmd & (1u << 1)) == 0)
+#define IS_DATA_SHIFTING_MSB_FIRST(cmd) ((cmd & (1u << 3)) == 0)
#define IS_DATA_SHIFTING_WRITING_TDI(cmd) (cmd & (1u << 4))
#define IS_DATA_SHIFTING_READING_TDO(cmd) (cmd & (1u << 5))
#define IS_DATA_SHIFTING_WRITING_TMS(cmd) (cmd & (1u << 6))
@@ -272,6 +280,11 @@ get_command_string(guint8 cmd, ftdi_mpsse_info_t *mpsse_info)
break;
}
+ if (!str && mpsse_info->mcu_mode)
+ {
+ str = try_val_to_str_ext(cmd, &cpumode_command_vals_ext);
+ }
+
return str;
}
@@ -285,7 +298,8 @@ static gboolean is_same_mpsse_instance(ftdi_mpsse_info_t *info1, ftdi_mpsse_info
return (info1->bus_id == info2->bus_id) &&
(info1->device_address == info2->device_address) &&
(info1->chip == info2->chip) &&
- (info1->iface == info2->iface);
+ (info1->iface == info2->iface) &&
+ (info1->mcu_mode == info2->mcu_mode);
}
static command_data_t *
@@ -295,11 +309,13 @@ get_recorded_command_data(packet_info *pinfo, ftdi_mpsse_info_t *mpsse_info)
guint32 k_device_address = mpsse_info->device_address;
guint32 k_chip = (guint32)mpsse_info->chip;
guint32 k_interface = (guint32)mpsse_info->iface;
+ guint32 k_mcu_mode = mpsse_info->mcu_mode;
wmem_tree_key_t key[] = {
{1, &k_bus_id},
{1, &k_device_address},
{1, &k_chip},
{1, &k_interface},
+ {1, &k_mcu_mode},
{1, &pinfo->num},
{0, NULL}
};
@@ -320,11 +336,13 @@ static void insert_command_data_pointer(packet_info *pinfo, ftdi_mpsse_info_t *m
guint32 k_device_address = mpsse_info->device_address;
guint32 k_chip = (guint32)mpsse_info->chip;
guint32 k_interface = (guint32)mpsse_info->iface;
+ guint32 k_mcu_mode = mpsse_info->mcu_mode;
wmem_tree_key_t key[] = {
{1, &k_bus_id},
{1, &k_device_address},
{1, &k_chip},
{1, &k_interface},
+ {1, &k_mcu_mode},
{1, &pinfo->num},
{0, NULL}
};
@@ -398,7 +416,11 @@ dissect_data_shifting_command_parameters(guint8 cmd, tvbuff_t *tvb, packet_info
proto_tree_add_uint_format(tree, hf_mpsse_length_uint8, tvb, offset, 1, length, "Length: %d bit%s", length + 1, plurality(length + 1, "", "s"));
offset += 1;
- if (IS_DATA_SHIFTING_WRITING_TDI(cmd) || IS_DATA_SHIFTING_WRITING_TMS(cmd))
+ if (IS_DATA_SHIFTING_WRITING_TMS(cmd) && IS_DATA_SHIFTING_READING_TDO(cmd) && IS_DATA_SHIFTING_MSB_FIRST(cmd))
+ {
+ /* These undocumented commands do not seem to consume the data byte, only the length */
+ }
+ else if (IS_DATA_SHIFTING_WRITING_TDI(cmd) || IS_DATA_SHIFTING_WRITING_TMS(cmd))
{
proto_tree_add_item(tree, hf_mpsse_bits_out, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset += 1;
@@ -407,7 +429,11 @@ dissect_data_shifting_command_parameters(guint8 cmd, tvbuff_t *tvb, packet_info
if (!pinfo->fd->visited)
{
- if (IS_DATA_SHIFTING_READING_TDO(cmd))
+ if (mpsse_info->mcu_mode)
+ {
+ /* MCU mode seems to consume data shifting payloads but do not actually return any response data */
+ }
+ else if (IS_DATA_SHIFTING_READING_TDO(cmd))
{
record_command_data(cmd_data, pinfo, mpsse_info, cmd, IS_DATA_SHIFTING_BYTE_MODE(cmd) ? length + 1 : 1);
}
@@ -682,6 +708,11 @@ static gint estimated_command_parameters_length(guint8 cmd, tvbuff_t *tvb, gint
else /* bit mode */
{
parameters_length = (IS_DATA_SHIFTING_WRITING_TDI(cmd) || IS_DATA_SHIFTING_WRITING_TMS(cmd)) ? 2 : 1;
+ if (IS_DATA_SHIFTING_WRITING_TMS(cmd) && IS_DATA_SHIFTING_READING_TDO(cmd) && IS_DATA_SHIFTING_MSB_FIRST(cmd))
+ {
+ /* These undocumented commands do not seem to consume the data byte, only the length */
+ parameters_length = 1;
+ }
}
}
else
@@ -814,15 +845,29 @@ dissect_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset
static gint
dissect_response_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, command_data_t *cmd_data)
{
+ gint offset_start = offset;
+
if (!cmd_data->is_response_set)
{
cmd_data->response_in_packet = pinfo->num;
cmd_data->is_response_set = TRUE;
}
- proto_tree_add_expert(tree, pinfo, &ei_undecoded, tvb, offset, cmd_data->response_length);
+ if (is_valid_command(cmd_data->cmd, &cmd_data->mpsse_info))
+ {
+ proto_tree_add_expert(tree, pinfo, &ei_undecoded, tvb, offset, cmd_data->response_length);
+ offset += cmd_data->response_length;
+ }
+ else
+ {
+ proto_tree_add_item(tree, hf_mpsse_bad_command_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
- return cmd_data->response_length;
+ proto_tree_add_item(tree, hf_mpsse_bad_command_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ }
+
+ return offset - offset_start;
}
static gint
@@ -1034,6 +1079,16 @@ proto_register_ftdi_mpsse(void)
FT_BYTES, BASE_NONE, NULL, 0x0,
"Command including optional parameter bytes", HFILL }
},
+ { &hf_mpsse_bad_command_error,
+ { "Error code", "ftdi-mpsse.bad_command.error",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Bad Command error code 0xFA", HFILL }
+ },
+ { &hf_mpsse_bad_command_code,
+ { "Received invalid command", "ftdi-mpsse.bad_command.command",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Byte which caused the bad command", HFILL }
+ },
{ &hf_mpsse_response,
{ "Command response data", "ftdi-mpsse.response",
FT_BYTES, BASE_NONE, NULL, 0x0,