aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Labedzki <michal.labedzki@tieto.com>2015-09-16 15:25:13 +0200
committerAnders Broman <a.broman58@gmail.com>2015-10-16 06:29:37 +0000
commitf306038ef434da89dc17489c9ab0f8a7c03a829a (patch)
tree96fa3869cbeb3c2f45cc17a9e1ebc3daf747262e
parent5e8c6291f4f3e4f237eed5a92afb5d320c66544d (diff)
Bluetooth: GATT: Add support for Nordic's vendor UUIDs
Add DFU and UART services support. Change-Id: I028fab3aa826c1d944ccfa0624cf33ce566a5099 Reviewed-on: https://code.wireshark.org/review/11015 Petri-Dish: Michal Labedzki <michal.labedzki@tieto.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--epan/dissectors/packet-bluetooth.c11
-rw-r--r--epan/dissectors/packet-btatt.c280
2 files changed, 278 insertions, 13 deletions
diff --git a/epan/dissectors/packet-bluetooth.c b/epan/dissectors/packet-bluetooth.c
index d20484f612..bff8e8d73b 100644
--- a/epan/dissectors/packet-bluetooth.c
+++ b/epan/dissectors/packet-bluetooth.c
@@ -579,8 +579,15 @@ const value_string bluetooth_uuid_vals[] = {
value_string_ext bluetooth_uuid_vals_ext = VALUE_STRING_EXT_INIT(bluetooth_uuid_vals);
const bluetooth_uuid_custom_t bluetooth_uuid_custom[] = {
- { {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Server" },
- { {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Client" },
+ { {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Server" },
+ { {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Client" },
+ { {0x6E, 0x40, 0x00, 0x01, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E}, 16, "Nordic UART Service" },
+ { {0x6E, 0x40, 0x00, 0x02, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E}, 16, "Nordic UART Tx" },
+ { {0x6E, 0x40, 0x00, 0x03, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E}, 16, "Nordic UART Rx" },
+ { {0x00, 0x00, 0x15, 0x30, 0x12, 0x12, 0xEF, 0xDE, 0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23}, 16, "Nordic DFU Service" },
+ { {0x00, 0x00, 0x15, 0x31, 0x12, 0x12, 0xEF, 0xDE, 0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23}, 16, "Nordic DFU Control Point" },
+ { {0x00, 0x00, 0x15, 0x32, 0x12, 0x12, 0xEF, 0xDE, 0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23}, 16, "Nordic DFU Packet" },
+
{ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, NULL},
};
diff --git a/epan/dissectors/packet-btatt.c b/epan/dissectors/packet-btatt.c
index 5875b6923e..ee1f892d60 100644
--- a/epan/dissectors/packet-btatt.c
+++ b/epan/dissectors/packet-btatt.c
@@ -44,6 +44,7 @@
/* Initialize the protocol and registered fields */
static int proto_btatt = -1;
+static int proto_btgatt = -1;
static int hf_btatt_opcode = -1;
static int hf_btatt_handle = -1;
@@ -823,6 +824,16 @@ static int hf_btatt_cgm_specific_ops_control_point_operand_alert_level = -1;
static int hf_btatt_cgm_specific_ops_control_point_operand_alert_level_rate = -1;
static int hf_btatt_cgm_specific_ops_control_point_request_opcode = -1;
static int hf_btatt_cgm_specific_ops_control_point_response_code = -1;
+static int hf_gatt_nordic_uart_tx = -1;
+static int hf_gatt_nordic_uart_rx = -1;
+static int hf_gatt_nordic_dfu_packet = -1;
+static int hf_gatt_nordic_dfu_control_point_opcode = -1;
+static int hf_gatt_nordic_dfu_control_point_init_packet = -1;
+static int hf_gatt_nordic_dfu_control_point_number_of_bytes = -1;
+static int hf_gatt_nordic_dfu_control_point_image_type = -1;
+static int hf_gatt_nordic_dfu_control_point_number_of_packets = -1;
+static int hf_gatt_nordic_dfu_control_point_request_opcode = -1;
+static int hf_gatt_nordic_dfu_control_point_response_value = -1;
static int hf_request_in_frame = -1;
static int hf_response_in_frame = -1;
@@ -1488,6 +1499,7 @@ static expert_field ei_btatt_consent_out_of_bounds = EI_INIT;
static expert_field ei_btatt_cgm_size_too_small = EI_INIT;
static expert_field ei_btatt_opcode_invalid_request = EI_INIT;
static expert_field ei_btatt_opcode_invalid_response = EI_INIT;
+static expert_field ei_btatt_unexpected_data = EI_INIT;
static expert_field ei_btatt_undecoded = EI_INIT;
static wmem_tree_t *mtus = NULL;
@@ -1496,6 +1508,7 @@ static wmem_tree_t *fragments = NULL;
static wmem_tree_t *handle_to_uuid = NULL;
static dissector_handle_t btatt_handle;
+static dissector_handle_t btgatt_handle;
static dissector_handle_t usb_hid_boot_keyboard_input_report_handle;
static dissector_handle_t usb_hid_boot_keyboard_output_report_handle;
static dissector_handle_t usb_hid_boot_mouse_input_report_handle;
@@ -2780,6 +2793,48 @@ static const value_string cgm_specific_ops_control_point_response_code_vals[] =
{0x0, NULL}
};
+static const value_string nordic_dfu_control_point_opcode_vals[] = {
+ { 0x01, "Start DFU"},
+ { 0x02, "Initialize DFU Parameters"},
+ { 0x03, "Receive Firmware Image"},
+ { 0x04, "Validate Firmware"},
+ { 0x05, "Activate Image and Reset"},
+ { 0x06, "Reset System"},
+ { 0x07, "Report Received Image Size"},
+ { 0x08, "Packet Receipt Notification Request"},
+ { 0x10, "Response Code"},
+ { 0x11, "Packet Receipt Notification"},
+ {0x0, NULL}
+};
+
+static const value_string nordic_dfu_control_point_image_type_vals[] = {
+ { 0x00, "No Image"},
+ { 0x01, "SoftDevice"},
+ { 0x02, "Bootloader"},
+ { 0x03, "Bootloader+SoftDevice"},
+ { 0x04, "Application"},
+ { 0x05, "Other Image Combination - currently not supported"},
+ { 0x06, "Other Image Combination - currently not supported"},
+ { 0x07, "Other Image Combination - currently not supported"},
+ {0x0, NULL}
+};
+
+static const value_string nordic_dfu_control_point_init_packet_vals[] = {
+ { 0x00, "Receive Init Packet"},
+ { 0x01, "Init Packet Complete"},
+ {0x0, NULL}
+};
+
+static const value_string nordic_dfu_control_point_response_value_vals[] = {
+ { 0x01, "Success"},
+ { 0x02, "Invalid State"},
+ { 0x03, "Not Supported"},
+ { 0x04, "Data Size Exceeds Limit"},
+ { 0x05, "CRC Error"},
+ { 0x06, "Operation Failed"},
+ {0x0, NULL}
+};
+
static const true_false_string control_point_mask_value_tfs = {
"Leave as Default",
"Turn Off" };
@@ -2857,6 +2912,9 @@ typedef struct _fragment_data_t {
void proto_register_btatt(void);
void proto_reg_handoff_btatt(void);
+void proto_register_btgatt(void);
+void proto_reg_handoff_btgatt(void);
+
#define PROTO_DATA_BTATT_HANDLE 0x00
#define PROTO_DATA_BTATT_UUID16 0x01
#define PROTO_DATA_BTATT_UUID128 0x02
@@ -3263,18 +3321,16 @@ dissect_attribute_value(proto_tree *tree, proto_item *patron_item, packet_info *
}
}
- if (!uuid.bt_uuid) {
+ if (dissector_try_string(att_uuid128_dissector_table, print_numeric_uuid(&uuid), tvb, pinfo, tree, bluetooth_data))
+ return old_offset + length;
+ else if (dissector_try_uint_new(att_uuid16_dissector_table, uuid.bt_uuid, tvb, pinfo, tree, TRUE, bluetooth_data))
+ return old_offset + length;
+ else if (!uuid.bt_uuid) {
proto_tree_add_item(tree, hf_btatt_value, tvb, offset, -1, ENC_NA);
return old_offset + tvb_captured_length(tvb);
}
- if (dissector_try_string(att_uuid128_dissector_table, print_uuid(&uuid), tvb, pinfo, tree, bluetooth_data))
- return old_offset + length;
-
- if (dissector_try_uint_new(att_uuid16_dissector_table, uuid.bt_uuid, tvb, pinfo, tree, TRUE, bluetooth_data))
- return old_offset + length;
-
switch (uuid.bt_uuid) {
case 0x2800: /* GATT Primary Service Declaration */
case 0x2801: /* GATT Secondary Service Declaration */
@@ -6553,6 +6609,98 @@ dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
return offset;
}
+static int
+dissect_btgatt_nordic_uart_tx(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+{
+ proto_tree_add_item(tree, hf_gatt_nordic_uart_tx, tvb, 0, tvb_captured_length(tvb), ENC_ASCII | ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_btgatt_nordic_uart_rx(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+{
+ proto_tree_add_item(tree, hf_gatt_nordic_uart_rx, tvb, 0, tvb_captured_length(tvb), ENC_ASCII | ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_btgatt_nordic_dfu_control_point(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint offset = 0;
+ guint8 opcode;
+ guint8 request_opcode;
+ guint8 status;
+
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_opcode, tvb, offset, 1, ENC_NA);
+ opcode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ switch (opcode) {
+ case 0x01: /* Start DFU */
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_image_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ break;
+ case 0x02: /* Initialize DFU Parameters */
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_init_packet, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ }
+
+ break;
+ case 0x03: /* Receive Firmware Image */
+ case 0x04: /* Validate Firmware */
+ case 0x05: /* Activate Image and Reset */
+ case 0x06: /* Reset System */
+ case 0x07: /* Report Received Image Size */
+ /* nop */
+
+ break;
+ case 0x08: /* Packet Receipt Notification Request */
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_number_of_packets, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ break;
+ case 0x10: /* Response Code */
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_request_opcode, tvb, offset, 1, ENC_NA);
+ request_opcode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_response_value, tvb, offset, 1, ENC_NA);
+ status = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (request_opcode == 0x07 && status == 0x01) { /* Report Received Image Size && Success */
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_number_of_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+
+ break;
+ case 0x11: /* Packet Receipt Notification */
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_control_point_number_of_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ break;
+ }
+
+ if (tvb_captured_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_expert(tree, pinfo, &ei_btatt_unexpected_data, tvb, offset, -1);
+ offset = tvb_captured_length(tvb);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_btgatt_nordic_dfu_packet(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+{
+ proto_tree_add_item(tree, hf_gatt_nordic_dfu_packet, tvb, 0, tvb_captured_length(tvb), ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
void
proto_register_btatt(void)
{
@@ -10493,8 +10641,7 @@ proto_register_btatt(void)
&ett_btatt_value,
&ett_btatt_opcode,
&ett_btatt_handle,
- &ett_btatt_characteristic_properties,
- &ett_btgatt
+ &ett_btatt_characteristic_properties
};
static ei_register_info ei[] = {
@@ -10506,6 +10653,7 @@ proto_register_btatt(void)
{ &ei_btatt_cgm_size_too_small, { "btatt.cgm_measurement.size.too_small", PI_PROTOCOL, PI_WARN, "Size too small (6 or geater)", EXPFILL }},
{ &ei_btatt_opcode_invalid_request, { "btatt.opcode.invalid_request" , PI_PROTOCOL, PI_WARN, "Invalid request", EXPFILL }},
{ &ei_btatt_opcode_invalid_response,{ "btatt.opcode.invalid_response", PI_PROTOCOL, PI_WARN, "Invalid response", EXPFILL }},
+ { &ei_btatt_unexpected_data, { "btatt.unexpected_data", PI_PROTOCOL, PI_WARN, "Unexpected Data", EXPFILL }},
{ &ei_btatt_undecoded, { "btatt.undecoded", PI_PROTOCOL, PI_UNDECODED, "Undecoded", EXPFILL }},
};
@@ -10560,7 +10708,23 @@ proto_register_btatt(void)
void
proto_reg_handoff_btatt(void)
{
- gint i_array;
+ gint i_array;
+ struct uuid_dissectors_t {
+ const gchar *uuid;
+
+ const gchar *name;
+ const gchar *short_name;
+ const gchar *abbrev_name;
+
+ int (*dissect_func)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
+ } uuid_dissectors[] = {
+ { "6e400002-b5a3-f393-e0a9-e50e24dcca9e", "Bluetooth GATT Nordic UART Tx", "Nordic UART Tx", "btgatt.nordic.uart_tx", dissect_btgatt_nordic_uart_tx},
+ { "6e400003-b5a3-f393-e0a9-e50e24dcca9e", "Bluetooth GATT Nordic UART Rx", "Nordic UART Rx", "btgatt.nordic.uart_rx", dissect_btgatt_nordic_uart_rx},
+ { "00001531-1212-efde-1523-785feabcd123", "Bluetooth GATT Nordic DFU Control Point", "Nordic DFU Control Point", "btgatt.nordic.dfu.control_point", dissect_btgatt_nordic_dfu_control_point},
+ { "00001532-1212-efde-1523-785feabcd123", "Bluetooth GATT Nordic DFU Packet", "Nordic DFU Packet", "btgatt.nordic.dfu.packet", dissect_btgatt_nordic_dfu_packet},
+
+ { NULL, NULL, NULL, NULL, NULL},
+ };
usb_hid_boot_keyboard_input_report_handle = find_dissector("usbhid.boot_report.keyboard.input");
usb_hid_boot_keyboard_output_report_handle = find_dissector("usbhid.boot_report.keyboard.output");
@@ -10576,7 +10740,7 @@ proto_reg_handoff_btatt(void)
gchar *short_name;
gchar *abbrev;
dissector_handle_t handle_tmp;
- gint proto_tmp = -1;
+ gint proto_tmp;
if (bluetooth_uuid_vals[i_array].value < 0x1800) {
continue;
@@ -10598,8 +10762,102 @@ proto_reg_handoff_btatt(void)
dissector_add_for_decode_as("btatt.handle", handle_tmp);
}
+
+ i_array = 0;
+
+ while (uuid_dissectors[i_array].uuid) {
+ dissector_handle_t handle_tmp;
+ gint proto_tmp;
+
+ if (!uuid_dissectors[i_array].dissect_func) {
+ i_array += 1;
+ continue;
+ }
+
+ proto_tmp = proto_register_protocol(uuid_dissectors[i_array].name, uuid_dissectors[i_array].short_name, uuid_dissectors[i_array].abbrev_name);
+ handle_tmp = new_register_dissector(uuid_dissectors[i_array].abbrev_name, uuid_dissectors[i_array].dissect_func, proto_tmp);
+
+ dissector_add_string("btatt.uuid128", uuid_dissectors[i_array].uuid, handle_tmp);
+ dissector_add_for_decode_as("btatt.handle", handle_tmp);
+ i_array += 1;
+ }
}
+
+void
+proto_register_btgatt(void)
+{
+ static hf_register_info hf[] = {
+ {&hf_gatt_nordic_uart_tx,
+ {"UART Tx", "btgatt.nordic.uart_tx.text",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_uart_rx,
+ {"UART Rx", "btgatt.nordic.uart_rx.text",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_packet,
+ {"Packet", "btgatt.nordic.dfu.packet",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_opcode,
+ {"Opcode", "btgatt.nordic.dfu.control_point.opcode",
+ FT_UINT8, BASE_DEC, VALS(nordic_dfu_control_point_opcode_vals), 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_init_packet,
+ {"Init Packet", "btgatt.nordic.dfu.control_point.init_packet",
+ FT_UINT8, BASE_HEX, VALS(nordic_dfu_control_point_init_packet_vals), 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_image_type,
+ {"Image Type", "btgatt.nordic.dfu.control_point.image_type",
+ FT_UINT8, BASE_HEX, VALS(nordic_dfu_control_point_image_type_vals), 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_number_of_bytes,
+ {"Number of Bytes of Firmware Image Received", "btgatt.nordic.dfu.control_point.number_of_bytes",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_number_of_packets,
+ {"Number of Packets", "btgatt.nordic.dfu.control_point.number_of_packets",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_request_opcode,
+ {"Request Opcode", "btgatt.nordic.dfu.control_point.request_opcode",
+ FT_UINT8, BASE_DEC, VALS(nordic_dfu_control_point_opcode_vals), 0x0,
+ NULL, HFILL}
+ },
+ {&hf_gatt_nordic_dfu_control_point_response_value,
+ {"Response Value", "btgatt.nordic.dfu.control_point.response_value",
+ FT_UINT8, BASE_DEC, VALS(nordic_dfu_control_point_response_value_vals), 0x0,
+ NULL, HFILL}
+ }
+ };
+
+
+ static gint *ett[] = {
+ &ett_btgatt
+ };
+
+ proto_btgatt = proto_register_protocol("Bluetooth GATT Attribute Protocol", "BT GATT", "btgatt");
+
+ btgatt_handle = new_register_dissector("btgatt", dissect_btgatt, proto_btgatt);
+
+ proto_register_field_array(proto_btgatt, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_btgatt(void)
+{
+
+}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*