2 * Routines for Bluetooth Attribute Protocol dissection
4 * Copyright 2012, Allan M. Madsen <allan.m@madsen.dk>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/packet.h>
34 #include <epan/prefs.h>
35 #include <epan/expert.h>
36 #include "packet-btl2cap.h"
38 /* Initialize the protocol and registered fields */
39 static int proto_btatt
= -1;
41 static int hf_btatt_opcode
= -1;
42 static int hf_btatt_handle
= -1;
43 static int hf_btatt_starting_handle
= -1;
44 static int hf_btatt_ending_handle
= -1;
45 static int hf_btatt_group_end_handle
= -1;
46 static int hf_btatt_value
= -1;
47 static int hf_btatt_req_opcode_in_error
= -1;
48 static int hf_btatt_handle_in_error
= -1;
49 static int hf_btatt_error_code
= -1;
50 static int hf_btatt_uuid16
= -1;
51 static int hf_btatt_uuid128
= -1;
52 static int hf_btatt_client_rx_mtu
= -1;
53 static int hf_btatt_server_rx_mtu
= -1;
54 static int hf_btatt_uuid_format
= -1;
55 static int hf_btatt_length
= -1;
56 static int hf_btatt_offset
= -1;
57 static int hf_btatt_flags
= -1;
58 static int hf_btatt_sign_counter
= -1;
59 static int hf_btatt_signature
= -1;
60 static int hf_btatt_attribute_data
= -1;
61 static int hf_btatt_handles_info
= -1;
63 /* Initialize the subtree pointers */
64 static gint ett_btatt
= -1;
65 static gint ett_btatt_list
= -1;
67 static expert_field ei_btatt_uuid_format_unknown
= EI_INIT
;
68 static expert_field ei_btatt_handle_too_few
= EI_INIT
;
70 static dissector_handle_t btatt_handle
;
73 static const value_string opcode_vals
[] = {
74 {0x01, "Error Response"},
75 {0x02, "Exchange MTU Request"},
76 {0x03, "Exchange MTU Response"},
77 {0x04, "Find Information Request"},
78 {0x05, "Find Information Response"},
79 {0x06, "Find By Type Value Request"},
80 {0x07, "Find By Type Value Response"},
81 {0x08, "Read By Type Request"},
82 {0x09, "Read By Type Response"},
83 {0x0a, "Read Request"},
84 {0x0b, "Read Response"},
85 {0x0c, "Read Blob Request"},
86 {0x0d, "Read Blob Response"},
87 {0x0e, "Read Multiple Request"},
88 {0x0f, "Read Multiple Response"},
89 {0x10, "Read By Group Type Request"},
90 {0x11, "Read By Group Type Response"},
91 {0x12, "Write Request"},
92 {0x13, "Write Response"},
93 {0x16, "Prepare Write Request"},
94 {0x17, "Prepare Write Response"},
95 {0x18, "Execute Write Request"},
96 {0x19, "Execute Write Response"},
97 {0x1B, "Handle Value Notification"},
98 {0x1D, "Handle Value Indication"},
99 {0x1E, "Handle Value Confirmation"},
100 {0x52, "Write Command"},
101 {0xD2, "Signed Write Command"},
106 static const value_string error_vals
[] = {
107 {0x01, "Invalid Handle"},
108 {0x02, "Read Not Permitted"},
109 {0x03, "Write Not Permitted"},
110 {0x04, "Invalid PDU"},
111 {0x05, "Insufficient Authentication"},
112 {0x06, "Request Not Supported"},
113 {0x07, "Invalid Offset"},
114 {0x08, "Insufficient Authorization"},
115 {0x09, "Prepare Queue Full"},
116 {0x0a, "Attribute Not Found"},
117 {0x0b, "Attribute Not Long"},
118 {0x0c, "Insufficient Encryption Key Size"},
119 {0x0d, "Invalid Attribute Value Length"},
120 {0x0e, "Unlikely Error"},
121 {0x0f, "Insufficient Encryption"},
122 {0x10, "Unsupported Group Type"},
123 {0x11, "Insufficient Resources"},
124 {0x80, "Application Error"},
125 {0xfd, "Improper Client Characteristic Configuration Descriptor"},
126 {0xfe, "Procedure Already In Progress"},
127 {0xff, "Out of Range"},
131 static const value_string uuid_vals
[] = {
132 /* Services - http://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
133 {0x1800, "Generic Access"},
134 {0x1801, "Generic Attribute"},
135 {0x1802, "Immediate Alert"},
136 {0x1803, "Link Loss"},
137 {0x1804, "Tx Power"},
138 {0x1805, "Current Time Service"},
139 {0x1806, "Reference Time Update Service"},
140 {0x1807, "Next DST Change Service"},
142 {0x1809, "Health Thermometer"},
143 {0x180a, "Device Information"},
144 {0x180d, "Heart Rate"},
145 {0x180e, "Phone Alert Status Service"},
146 {0x180f, "Battery Service"},
147 {0x1810, "Blood Pressure"},
148 {0x1811, "Alert Notification Service"},
149 {0x1812, "Human Interface Device"},
150 {0x1813, "Scan Parameters"},
151 {0x1814, "Running Speed and Cadence"},
152 {0x1816, "Cycling Speed and Cadence"},
153 /* Declarations - http://developer.bluetooth.org/gatt/declarations/Pages/DeclarationsHome.aspx */
154 {0x2800, "GATT Primary Service Declaration"},
155 {0x2801, "GATT Secondary Service Declaration"},
156 {0x2802, "GATT Include Declaration"},
157 {0x2803, "GATT Characteristic Declaration"},
158 /* Descriptors - http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx */
159 {0x2900, "Characteristic Extended Properties"},
160 {0x2901, "Characteristic User Description"},
161 {0x2902, "Client Characteristic Configuration"},
162 {0x2903, "Server Characteristic Configuration"},
163 {0x2904, "Characteristic Presentation Format"},
164 {0x2905, "Characteristic Aggregate Format"},
165 {0x2906, "Valid Range"},
166 {0x2907, "External Report Reference"},
167 {0x2908, "Report Reference"},
168 /* Characteristics - http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx */
169 {0x2a00, "Device Name"},
170 {0x2a01, "Appearance"},
171 {0x2a02, "Peripheral Privacy Flag"},
172 {0x2a03, "Reconnection Address"},
173 {0x2a04, "Peripheral Preferred Connection Parameters"},
174 {0x2a05, "Service Changed"},
175 {0x2a06, "Alert Level"},
176 {0x2a07, "Tx Power Level"},
177 {0x2a08, "Date Time"},
178 {0x2a09, "Day of Week"},
179 {0x2a0a, "Day Date Time"},
180 {0x2a0c, "Exact Time 256"},
181 {0x2a0d, "DST Offset"},
182 {0x2a0e, "Time Zone"},
183 {0x2a0f, "Local Time Information"},
184 {0x2a11, "Time with DST"},
185 {0x2a12, "Time Accuracy"},
186 {0x2a13, "Time Source"},
187 {0x2a14, "Reference Time Information"},
188 {0x2a16, "Time Update Control Point"},
189 {0x2a17, "Time Update State"},
190 {0x2a18, "Glucose Measurement"},
191 {0x2a19, "Battery Level"},
192 {0x2a1c, "Temperature Measurement"},
193 {0x2a1d, "Temperature Type"},
194 {0x2a1e, "Intermediate Temperature"},
195 {0x2a21, "Measurement Interval"},
196 {0x2a22, "Boot Keyboard Input Report"},
197 {0x2a23, "System ID"},
198 {0x2a24, "Model Number String"},
199 {0x2a25, "Serial Number String"},
200 {0x2a26, "Firmware Revision String"},
201 {0x2a27, "Hardware Revision String"},
202 {0x2a28, "Software Revision String"},
203 {0x2a29, "Manufacturer Name String"},
204 {0x2a2a, "IEEE 11073-20601 Reg. Cert. Data List"},
205 {0x2a2b, "Current Time"},
206 {0x2a31, "Scan Refresh"},
207 {0x2a32, "Boot Keyboard Output Report"},
208 {0x2a33, "Boot Mouse Input Report"},
209 {0x2a34, "Glucose Measurement Context"},
210 {0x2a35, "Blood Pressure Measurement"},
211 {0x2a36, "Intermediate Cuff Pressure"},
212 {0x2a37, "Heart Rate Measurement"},
213 {0x2a38, "Body Sensor Location"},
214 {0x2a39, "Heart Rate Control Point"},
215 {0x2a3f, "Alert Status"},
216 {0x2a40, "Ringer Control Point"},
217 {0x2a41, "Ringer Setting"},
218 {0x2a42, "Alert Category ID Bit Mask"},
219 {0x2a43, "Alert Category ID"},
220 {0x2a44, "Alert Notification Control Point"},
221 {0x2a45, "Unread Alert Status"},
222 {0x2a46, "New Alert"},
223 {0x2a47, "Supported New Alert Category"},
224 {0x2a48, "Supported Unread Alert Category"},
225 {0x2a49, "Blood Pressure Feature"},
226 {0x2a4a, "HID Information"},
227 {0x2a4b, "Report Map"},
228 {0x2a4c, "HID Control Point"},
230 {0x2a4e, "Protocol Mode"},
231 {0x2a4f, "Scan Interval Window"},
233 {0x2a51, "Glucose Feature"},
234 {0x2a52, "Record Access Control Point"},
235 {0x2a53, "RSC Measurement"},
236 {0x2a54, "RSC Feature"},
237 {0x2a55, "SC Control Point"},
238 {0x2a5b, "CSC Measurement"},
239 {0x2a5c, "CSC Feature"},
240 {0x2a5d, "Sensor Location"},
243 static value_string_ext uuid_vals_ext
= VALUE_STRING_EXT_INIT(uuid_vals
);
245 static const value_string uuid_format_vals
[] = {
246 {0x01, "16-bit UUIDs"},
247 {0x02, "128-bit UUIDs"},
251 static const value_string flags_vals
[] = {
252 {0x00, "Cancel All"},
253 {0x01, "Immediately Write All"},
257 void proto_register_btatt(void);
258 void proto_reg_handoff_btatt(void);
261 dissect_btatt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
264 proto_item
*ti
, *item
;
265 proto_tree
*st
, *ltree
;
268 if (tvb_length_remaining(tvb
, 0) < 1)
271 ti
= proto_tree_add_item(tree
, proto_btatt
, tvb
, 0, -1, ENC_NA
);
272 st
= proto_item_add_subtree(ti
, ett_btatt
);
274 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ATT");
276 switch (pinfo
->p2p_dir
) {
278 col_set_str(pinfo
->cinfo
, COL_INFO
, "Sent ");
281 col_set_str(pinfo
->cinfo
, COL_INFO
, "Rcvd ");
284 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Unknown direction %d ",
289 item
= proto_tree_add_item(st
, hf_btatt_opcode
, tvb
, 0, 1, ENC_LITTLE_ENDIAN
);
290 opcode
= tvb_get_guint8(tvb
, 0);
293 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(opcode
, opcode_vals
, "<unknown>"));
296 case 0x01: /* Error Response */
297 proto_tree_add_item(st
, hf_btatt_req_opcode_in_error
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
299 proto_tree_add_item(st
, hf_btatt_handle_in_error
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
300 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - %s, Handle: 0x%04x",
301 val_to_str_const(tvb_get_guint8(tvb
, offset
+2), error_vals
, "<unknown>"),
302 tvb_get_letohs(tvb
, offset
));
304 proto_tree_add_item(st
, hf_btatt_error_code
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
308 case 0x02: /* Exchange MTU Request */
309 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Client Rx MTU: %u", tvb_get_letohs(tvb
, offset
));
310 proto_tree_add_item(st
, hf_btatt_client_rx_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
314 case 0x03: /* Exchange MTU Response */
315 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Server Rx MTU: %u", tvb_get_letohs(tvb
, offset
));
316 proto_tree_add_item(st
, hf_btatt_server_rx_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
320 case 0x04: /* Find Information Request */
321 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Handles: 0x%04x..0x%04x",
322 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
323 proto_tree_add_item(st
, hf_btatt_starting_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
325 proto_tree_add_item(st
, hf_btatt_ending_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
329 case 0x05: /* Find Information Response */
331 guint8 format
= tvb_get_guint8(tvb
, offset
);
333 item
= proto_tree_add_item(st
, hf_btatt_uuid_format
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
337 while( tvb_length_remaining(tvb
, offset
) > 0) {
338 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
340 proto_tree_add_item(st
, hf_btatt_uuid16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
344 else if( format
== 2 ) {
345 while( tvb_length_remaining(tvb
, offset
) > 0) {
346 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
348 proto_tree_add_item(st
, hf_btatt_uuid128
, tvb
, offset
, 16, ENC_NA
);
353 expert_add_info(pinfo
, item
, &ei_btatt_uuid_format_unknown
);
358 case 0x06: /* Find By Type Value Request */
359 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s, Handles: 0x%04x..0x%04x",
360 val_to_str_ext_const(tvb_get_letohs(tvb
, offset
+4), &uuid_vals_ext
, "<unknown>"),
361 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
363 proto_tree_add_item(st
, hf_btatt_starting_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
365 proto_tree_add_item(st
, hf_btatt_ending_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
367 proto_tree_add_item(st
, hf_btatt_uuid16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
369 if( tvb_length_remaining(tvb
, offset
) > 0)
370 proto_tree_add_item(st
, hf_btatt_value
, tvb
, offset
, -1, ENC_NA
);
373 case 0x07: /* Find By Type Value Response */
374 while( tvb_length_remaining(tvb
, offset
) > 0 ) {
375 item
= proto_tree_add_none_format(st
, hf_btatt_handles_info
, tvb
, offset
, 4,
376 "Handles Info, Handle: 0x%04x, Group End Handle: 0x%04x",
377 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
379 ltree
= proto_item_add_subtree(item
, ett_btatt_list
);
381 proto_tree_add_item(ltree
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
383 proto_tree_add_item(ltree
, hf_btatt_group_end_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
388 case 0x08: /* Read By Type Request */
389 case 0x10: /* Read By Group Type Request */
390 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s, Handles: 0x%04x..0x%04x",
391 val_to_str_ext_const(tvb_get_letohs(tvb
, offset
+4), &uuid_vals_ext
, "<unknown>"),
392 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
394 proto_tree_add_item(st
, hf_btatt_starting_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
396 proto_tree_add_item(st
, hf_btatt_ending_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
399 if (tvb_length_remaining(tvb
, offset
) == 2) {
400 proto_tree_add_item(st
, hf_btatt_uuid16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
403 else if (tvb_length_remaining(tvb
, offset
) == 16) {
404 item
= proto_tree_add_item(st
, hf_btatt_uuid128
, tvb
, offset
, 16, ENC_NA
);
405 proto_item_append_text(item
, " (%s)", val_to_str_ext_const(tvb_get_letohs(tvb
, offset
),
406 &uuid_vals_ext
, "<unknown>"));
411 case 0x09: /* Read By Type Response */
413 guint8 length
= tvb_get_guint8(tvb
, offset
);
415 proto_tree_add_item(st
, hf_btatt_length
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
419 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Attribute List Length: %u",
420 tvb_length_remaining(tvb
, offset
)/length
);
422 while (tvb_length_remaining(tvb
, offset
) >= length
)
424 item
= proto_tree_add_none_format(st
, hf_btatt_attribute_data
, tvb
,
425 offset
, length
, "Attribute Data, Handle: 0x%04x",
426 tvb_get_letohs(tvb
, offset
));
428 ltree
= proto_item_add_subtree(item
, ett_btatt_list
);
430 proto_tree_add_item(ltree
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
432 proto_tree_add_item(ltree
, hf_btatt_value
, tvb
, offset
, length
- 2, ENC_NA
);
433 offset
+= (length
-2);
439 case 0x0a: /* Read Request */
440 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Handle: 0x%04x", tvb_get_letohs(tvb
, offset
));
441 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
445 case 0x0b: /* Read Response */
446 case 0x0d: /* Read Blob Response */
447 case 0x0f: /* Multiple Read Response */
448 proto_tree_add_item(st
, hf_btatt_value
, tvb
, offset
, -1, ENC_NA
);
451 case 0x0c: /* Read Blob Request */
452 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Handle: 0x%04x, Offset: %u",
453 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
454 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
456 proto_tree_add_item(st
, hf_btatt_offset
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
460 case 0x0e: /* Multiple Read Request */
461 if(tvb_length_remaining(tvb
, offset
) < 4) {
462 expert_add_info(pinfo
, item
, &ei_btatt_handle_too_few
);
466 col_append_str(pinfo
->cinfo
, COL_INFO
, ", Handles: ");
467 while (tvb_length_remaining(tvb
, offset
) >= 2) {
468 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
469 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "0x%04x ", tvb_get_letohs(tvb
, offset
));
474 case 0x11: /* Read By Group Type Response */
476 guint8 length
= tvb_get_guint8(tvb
, offset
);
478 proto_tree_add_item(st
, hf_btatt_length
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
482 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Attribute List Length: %u", tvb_length_remaining(tvb
, offset
)/length
);
484 while (tvb_length_remaining(tvb
, offset
) >= length
) {
485 item
= proto_tree_add_none_format(st
, hf_btatt_attribute_data
, tvb
, offset
, length
,
486 "Attribute Data, Handle: 0x%04x, Group End Handle: 0x%04x",
487 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
489 ltree
= proto_item_add_subtree(item
, ett_btatt_list
);
491 proto_tree_add_item(ltree
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
493 proto_tree_add_item(ltree
, hf_btatt_group_end_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
495 proto_tree_add_item(ltree
, hf_btatt_value
, tvb
, offset
, length
- 4, ENC_NA
);
496 offset
+= (length
-4);
502 case 0x12: /* Write Request */
503 case 0x52: /* Write Command */
504 case 0x1b: /* Handle Value Notification */
505 case 0x1d: /* Handle Value Indication */
506 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Handle: 0x%04x", tvb_get_letohs(tvb
, offset
));
507 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
509 proto_tree_add_item(st
, hf_btatt_value
, tvb
, offset
, -1, ENC_NA
);
512 case 0x16: /* Prepare Write Request */
513 case 0x17: /* Prepare Write Response */
514 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Handle: 0x%04x, Offset: %u",
515 tvb_get_letohs(tvb
, offset
), tvb_get_letohs(tvb
, offset
+2));
516 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
518 proto_tree_add_item(st
, hf_btatt_offset
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
520 proto_tree_add_item(st
, hf_btatt_value
, tvb
, offset
, -1, ENC_NA
);
523 case 0x18: /* Execute Write Request */
524 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s",
525 val_to_str_const(tvb_get_guint8(tvb
, offset
), flags_vals
, "<unknown>"));
526 proto_tree_add_item(st
, hf_btatt_flags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
530 case 0xd2: /* Signed Write Command */
534 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Handle: 0x%04x", tvb_get_letohs(tvb
, offset
));
535 proto_tree_add_item(st
, hf_btatt_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
537 length
= tvb_length_remaining(tvb
, offset
);
539 proto_tree_add_item(st
, hf_btatt_value
, tvb
, offset
, length
-12, ENC_NA
);
543 proto_tree_add_item(st
, hf_btatt_sign_counter
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
545 proto_tree_add_item(st
, hf_btatt_signature
, tvb
, offset
, 8, ENC_NA
);
556 proto_register_btatt(void)
560 static hf_register_info hf
[] = {
562 {"Opcode", "btatt.opcode",
563 FT_UINT8
, BASE_HEX
, VALS(opcode_vals
), 0x0,
566 {&hf_btatt_handles_info
,
567 {"Handles Info", "btatt.handles_info",
568 FT_NONE
, BASE_NONE
, NULL
, 0x0,
571 {&hf_btatt_attribute_data
,
572 {"Attribute Data", "btatt.attribute_data",
573 FT_NONE
, BASE_NONE
, NULL
, 0x0,
577 {"Handle", "btatt.handle",
578 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
581 {&hf_btatt_starting_handle
,
582 {"Starting Handle", "btatt.starting_handle",
583 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
586 {&hf_btatt_ending_handle
,
587 {"Ending Handle", "btatt.ending_handle",
588 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
591 {&hf_btatt_group_end_handle
,
592 {"Group End Handle", "btatt.group_end_handle",
593 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
597 {"Value", "btatt.value",
598 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
601 {&hf_btatt_req_opcode_in_error
,
602 {"Request Opcode in Error", "btatt.req_opcode_in_error",
603 FT_UINT8
, BASE_HEX
, VALS(opcode_vals
), 0x0,
606 {&hf_btatt_handle_in_error
,
607 {"Handle in Error", "btatt.handle_in_error",
608 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
611 {&hf_btatt_error_code
,
612 {"Error Code", "btatt.error_code",
613 FT_UINT8
, BASE_HEX
, VALS(error_vals
), 0x0,
617 {"UUID", "btatt.uuid16",
618 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
, &uuid_vals_ext
, 0x0,
622 {"UUID", "btatt.uuid128",
623 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
626 {&hf_btatt_client_rx_mtu
,
627 {"Client Rx MTU", "btatt.client_rx_mtu",
628 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
631 {&hf_btatt_server_rx_mtu
,
632 {"Server Rx MTU", "btatt.server_rx_mtu",
633 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
636 {&hf_btatt_uuid_format
,
637 {"UUID Format", "btatt.uuid_format",
638 FT_UINT8
, BASE_HEX
, VALS(uuid_format_vals
), 0x0,
642 {"Length", "btatt.length",
643 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
644 "Length of Handle/Value Pair", HFILL
}
647 {"Offset", "btatt.offset",
648 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
652 {"Flags", "btatt.flags",
653 FT_UINT8
, BASE_HEX
, VALS(flags_vals
), 0x0,
656 {&hf_btatt_sign_counter
,
657 {"Sign Counter", "btatt.sign_counter",
658 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
661 {&hf_btatt_signature
,
662 {"Signature", "btatt.signature",
663 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
668 /* Setup protocol subtree array */
669 static gint
*ett
[] = {
674 static ei_register_info ei
[] = {
675 { &ei_btatt_uuid_format_unknown
, { "btatt.uuid_format.unknown", PI_PROTOCOL
, PI_WARN
, "Unknown format", EXPFILL
}},
676 { &ei_btatt_handle_too_few
, { "btatt.handle.too_few", PI_PROTOCOL
, PI_WARN
, "Too few handles, should be 2 or more", EXPFILL
}},
679 expert_module_t
* expert_btatt
;
681 /* Register the protocol name and description */
682 proto_btatt
= proto_register_protocol("Bluetooth Attribute Protocol", "BT ATT", "btatt");
684 btatt_handle
= new_register_dissector("btatt", dissect_btatt
, proto_btatt
);
686 /* Required function calls to register the header fields and subtrees used */
687 proto_register_field_array(proto_btatt
, hf
, array_length(hf
));
688 proto_register_subtree_array(ett
, array_length(ett
));
689 expert_btatt
= expert_register_protocol(proto_btatt
);
690 expert_register_field_array(expert_btatt
, ei
, array_length(ei
));
692 module
= prefs_register_protocol(proto_btatt
, NULL
);
693 prefs_register_static_text_preference(module
, "att.version",
694 "Bluetooth Protocol ATT version from Core 4.0",
695 "Version of protocol supported by this dissector.");
699 proto_reg_handoff_btatt(void)
701 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_ATT
, btatt_handle
);
702 dissector_add_uint("btl2cap.cid", BTL2CAP_FIXED_CID_ATT
, btatt_handle
);
706 * Editor modelines - http://www.wireshark.org/tools/modelines.html
711 * indent-tabs-mode: nil
714 * vi: set shiftwidth=4 tabstop=8 expandtab:
715 * :indentSize=4:tabSize=8:noTabs=true: