Move parsing of specific tokens to separate functions

One giant switch starts being very hard to read so let's move its
parts to dedicated functions to improve the readability.

Change-Id: I12861f110a0df862667f59a96710f6d3371c8fa7
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
Reviewed-on: https://code.wireshark.org/review/34275
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
Krzysztof Opasiak 2019-08-13 23:03:21 +02:00 committed by Peter Wu
parent fb42c24a2c
commit 981071806d
1 changed files with 133 additions and 101 deletions

View File

@ -127,6 +127,7 @@ static const value_string usb_endpoint_type_vals[] = {
{0, NULL}
};
#define TOKEN_BITS_GET_ADDRESS(bits) (bits & 0x007F)
#define TOKEN_BITS_GET_ENDPOINT(bits) ((bits & 0x0780) >> 7)
@ -134,6 +135,127 @@ static const value_string usb_endpoint_type_vals[] = {
#define SPLIT_BITS_GET_ENDPOINT_TYPE(bits) ((bits & 0x060000) >> 17)
#define SPLIT_BIT_START_COMPLETE 0x0080
static gint
dissect_usbll_sof(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
{
guint32 frame;
/* TODO: How to mark that it is sent by host to all devices on the bus? */
proto_tree_add_item_ret_uint(tree, hf_usbll_sof_framenum, tvb, offset, 2, ENC_LITTLE_ENDIAN, &frame);
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_crc5, hf_usbll_crc5_status, &ei_wrong_crc5, pinfo,
crc5_usb_11bit_input(frame),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 2;
return offset;
}
static gint
dissect_usbll_token(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
{
/* USB address has bus id as when capturing at URB level there are usually multiple root hubs
* to select from. Until someone has specific need to connect multiple hardware sniffers at
* the same time and analyze that in Wireshark, this code simply sets the bus id to 0.
*/
const guint16 bus_id = 0;
guint16 device_address;
int endpoint;
guint16 address_bits;
static const int *address_fields[] = {
&hf_usbll_addr,
&hf_usbll_endp,
NULL
};
address_bits = tvb_get_letohs(tvb, offset);
device_address = TOKEN_BITS_GET_ADDRESS(address_bits);
endpoint = TOKEN_BITS_GET_ENDPOINT(address_bits);
usb_set_addr(tree, tvb, pinfo, bus_id, device_address, endpoint, TRUE);
proto_tree_add_bitmask_list_value(tree, tvb, offset, 2, address_fields, address_bits);
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_crc5, hf_usbll_crc5_status, &ei_wrong_crc5, pinfo,
crc5_usb_11bit_input(address_bits),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 2;
return offset;
}
static gint
dissect_usbll_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
{
/* TODO: How to determine the expected DATA size? */
gint data_size = tvb_reported_length_remaining(tvb, offset) - 2;
if (data_size > 0) {
proto_tree_add_item(tree, hf_usbll_data, tvb, offset, data_size, ENC_NA);
offset += data_size;
}
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_data_crc, hf_usbll_data_crc_status, &ei_wrong_crc16, pinfo,
crc16_usb_tvb_offset(tvb, 1, offset - 1),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 2;
return offset;
}
static gint
dissect_usbll_split(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
{
/* USB address has bus id as when capturing at URB level there are usually multiple root hubs
* to select from. Until someone has specific need to connect multiple hardware sniffers at
* the same time and analyze that in Wireshark, this code simply sets the bus id to 0.
*/
const guint16 bus_id = 0;
guint16 device_address;
int endpoint;
/* S/E fields have special meaning for Isochronous transfers */
gint32 tmp = tvb_get_gint24(tvb, offset, ENC_LITTLE_ENDIAN);
static const int *split_fields[] = {
&hf_usbll_split_hub_addr,
&hf_usbll_split_sc,
&hf_usbll_split_port,
&hf_usbll_split_s,
&hf_usbll_split_e,
&hf_usbll_split_et,
NULL
};
static const int *split_iso_fields[] = {
&hf_usbll_split_hub_addr,
&hf_usbll_split_sc,
&hf_usbll_split_port,
&hf_usbll_split_iso_se,
&hf_usbll_split_et,
NULL
};
device_address = SPLIT_BITS_GET_HUB_ADDRESS(tmp);
/* There is no endpoint information in the packet, show it as endpoint 0 */
endpoint = 0;
usb_set_addr(tree, tvb, pinfo, bus_id, device_address, endpoint, TRUE);
col_append_str(pinfo->cinfo, COL_INFO, (tmp & SPLIT_BIT_START_COMPLETE) ? " Complete" : " Start");
if (SPLIT_BITS_GET_ENDPOINT_TYPE(tmp) == USB_EP_TYPE_ISOCHRONOUS)
proto_tree_add_bitmask_list(tree, tvb, offset, 3, split_iso_fields, ENC_LITTLE_ENDIAN);
else
proto_tree_add_bitmask_list(tree, tvb, offset, 3, split_fields, ENC_LITTLE_ENDIAN);
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_split_crc5, hf_usbll_split_crc5_status, &ei_wrong_split_crc5, pinfo,
crc5_usb_19bit_input(tmp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 3;
return offset;
}
static int
dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
@ -142,13 +264,6 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
gint offset = 0;
guint32 pid;
const gchar *str;
/* USB address has bus id as when capturing at URB level there are usually multiple root hubs
* to select from. Until someone has specific need to connect multiple hardware sniffers at
* the same time and analyze that in Wireshark, this code simply sets the bus id to 0.
*/
const guint16 bus_id = 0;
guint16 device_address;
int endpoint;
tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_usbll, &item, "USB Packet");
@ -157,12 +272,9 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBLL");
str = try_val_to_str(pid, usb_packetid_vals);
if (str)
{
if (str) {
col_set_str(pinfo->cinfo, COL_INFO, str);
}
else
{
} else {
col_add_fstr(pinfo->cinfo, COL_INFO, "Invalid Packet ID (0x%02x)", pid);
expert_add_info(pinfo, item, &ei_invalid_pid);
}
@ -173,108 +285,29 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
case USB_PID_TOKEN_OUT:
case USB_PID_TOKEN_IN:
case USB_PID_SPECIAL_PING:
{
guint16 address_bits;
static const int *address_fields[] = {
&hf_usbll_addr,
&hf_usbll_endp,
NULL
};
address_bits = tvb_get_letohs(tvb, offset);
device_address = TOKEN_BITS_GET_ADDRESS(address_bits);
endpoint = TOKEN_BITS_GET_ENDPOINT(address_bits);
usb_set_addr(tree, tvb, pinfo, bus_id, device_address, endpoint, TRUE);
proto_tree_add_bitmask_list_value(tree, tvb, offset, 2, address_fields, address_bits);
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_crc5, hf_usbll_crc5_status, &ei_wrong_crc5, pinfo,
crc5_usb_11bit_input(address_bits),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 2;
offset = dissect_usbll_token(tvb, pinfo, tree, offset);
break;
}
case USB_PID_DATA_DATA0:
case USB_PID_DATA_DATA1:
case USB_PID_DATA_DATA2:
case USB_PID_DATA_MDATA:
{
/* TODO: How to determine the expected DATA size? */
gint data_size = tvb_reported_length_remaining(tvb, offset) - 2;
if (data_size > 0)
{
proto_tree_add_item(tree, hf_usbll_data, tvb, offset, data_size, ENC_NA);
offset += data_size;
}
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_data_crc, hf_usbll_data_crc_status, &ei_wrong_crc16, pinfo,
crc16_usb_tvb_offset(tvb, 1, offset - 1),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 2;
offset = dissect_usbll_data(tvb, pinfo, tree, offset);
break;
}
case USB_PID_HANDSHAKE_ACK:
case USB_PID_HANDSHAKE_NAK:
case USB_PID_HANDSHAKE_NYET:
case USB_PID_HANDSHAKE_STALL:
break;
case USB_PID_TOKEN_SOF:
{
guint32 frame;
/* TODO: How to mark that it is sent by host to all devices on the bus? */
proto_tree_add_item_ret_uint(tree, hf_usbll_sof_framenum, tvb, offset, 2, ENC_LITTLE_ENDIAN, &frame);
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_crc5, hf_usbll_crc5_status, &ei_wrong_crc5, pinfo,
crc5_usb_11bit_input(frame),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 2;
offset = dissect_usbll_sof(tvb, pinfo, tree, offset);
break;
}
case USB_PID_SPECIAL_SPLIT:
{
/* S/E fields have special meaning for Isochronous transfers */
gint32 tmp = tvb_get_gint24(tvb, offset, ENC_LITTLE_ENDIAN);
static const int *split_fields[] = {
&hf_usbll_split_hub_addr,
&hf_usbll_split_sc,
&hf_usbll_split_port,
&hf_usbll_split_s,
&hf_usbll_split_e,
&hf_usbll_split_et,
NULL
};
static const int *split_iso_fields[] = {
&hf_usbll_split_hub_addr,
&hf_usbll_split_sc,
&hf_usbll_split_port,
&hf_usbll_split_iso_se,
&hf_usbll_split_et,
NULL
};
device_address = SPLIT_BITS_GET_HUB_ADDRESS(tmp);
/* There is no endpoint information in the packet, show it as endpoint 0 */
endpoint = 0;
usb_set_addr(tree, tvb, pinfo, bus_id, device_address, endpoint, TRUE);
col_append_str(pinfo->cinfo, COL_INFO, (tmp & SPLIT_BIT_START_COMPLETE) ? " Complete" : " Start");
if (SPLIT_BITS_GET_ENDPOINT_TYPE(tmp) == USB_EP_TYPE_ISOCHRONOUS)
{
proto_tree_add_bitmask_list(tree, tvb, offset, 3, split_iso_fields, ENC_LITTLE_ENDIAN);
}
else
{
proto_tree_add_bitmask_list(tree, tvb, offset, 3, split_fields, ENC_LITTLE_ENDIAN);
}
proto_tree_add_checksum(tree, tvb, offset,
hf_usbll_split_crc5, hf_usbll_split_crc5_status, &ei_wrong_split_crc5, pinfo,
crc5_usb_19bit_input(tmp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
offset += 3;
offset = dissect_usbll_split(tvb, pinfo, tree, offset);
break;
}
case USB_PID_SPECIAL_PRE_OR_ERR:
break;
case USB_PID_SPECIAL_RESERVED:
@ -283,8 +316,7 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
break;
}
if (tvb_reported_length_remaining(tvb, offset) > 0)
{
if (tvb_reported_length_remaining(tvb, offset) > 0) {
proto_tree_add_expert(tree, pinfo, &ei_undecoded, tvb, offset, -1);
offset += tvb_captured_length_remaining(tvb, offset);
}