HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-btatt.c
blobc12cd88c471426646f17ac0161dccf737f316950
1 /* packet-btatt.c
2 * Routines for Bluetooth Attribute Protocol dissection
4 * Copyright 2012, Allan M. Madsen <allan.m@madsen.dk>
6 * $Id$
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.
31 #include "config.h"
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;
72 /* Opcodes */
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"},
102 {0x0, NULL}
105 /* Error codes */
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"},
128 {0x0, NULL}
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"},
141 {0x1808, "Glucose"},
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"},
229 {0x2a4d, "Report"},
230 {0x2a4e, "Protocol Mode"},
231 {0x2a4f, "Scan Interval Window"},
232 {0x2a50, "PnP ID"},
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"},
241 {0x0, NULL}
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"},
248 {0x0, NULL}
251 static const value_string flags_vals[] = {
252 {0x00, "Cancel All"},
253 {0x01, "Immediately Write All"},
254 {0x0, NULL}
257 void proto_register_btatt(void);
258 void proto_reg_handoff_btatt(void);
260 static int
261 dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
263 int offset = 0;
264 proto_item *ti, *item;
265 proto_tree *st, *ltree;
266 guint8 opcode;
268 if (tvb_length_remaining(tvb, 0) < 1)
269 return 0;
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) {
277 case P2P_DIR_SENT:
278 col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
279 break;
280 case P2P_DIR_RECV:
281 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
282 break;
283 default:
284 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
285 pinfo->p2p_dir);
286 break;
289 item = proto_tree_add_item(st, hf_btatt_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN);
290 opcode = tvb_get_guint8(tvb, 0);
291 offset++;
293 col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>"));
295 switch (opcode) {
296 case 0x01: /* Error Response */
297 proto_tree_add_item(st, hf_btatt_req_opcode_in_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
298 offset++;
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));
303 offset += 2;
304 proto_tree_add_item(st, hf_btatt_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
305 offset++;
306 break;
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);
311 offset += 2;
312 break;
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);
317 offset += 2;
318 break;
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);
324 offset += 2;
325 proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
326 offset += 2;
327 break;
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);
334 offset++;
336 if( format == 1 ) {
337 while( tvb_length_remaining(tvb, offset) > 0) {
338 proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
339 offset += 2;
340 proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
341 offset += 2;
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);
347 offset += 2;
348 proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
349 offset += 16;
352 else {
353 expert_add_info(pinfo, item, &ei_btatt_uuid_format_unknown);
356 break;
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);
364 offset += 2;
365 proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
366 offset += 2;
367 proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
368 offset += 2;
369 if( tvb_length_remaining(tvb, offset) > 0)
370 proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
371 break;
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);
382 offset += 2;
383 proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
384 offset += 2;
386 break;
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);
395 offset += 2;
396 proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
397 offset += 2;
399 if (tvb_length_remaining(tvb, offset) == 2) {
400 proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
401 offset += 2;
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>"));
407 offset += 16;
409 break;
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);
416 offset++;
418 if(length > 0) {
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);
431 offset += 2;
432 proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length - 2, ENC_NA);
433 offset += (length-2);
437 break;
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);
442 offset += 2;
443 break;
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);
449 break;
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);
455 offset += 2;
456 proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
457 offset += 2;
458 break;
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);
463 break;
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));
470 offset += 2;
472 break;
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);
479 offset++;
481 if(length > 0) {
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);
492 offset += 2;
493 proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
494 offset += 2;
495 proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length - 4, ENC_NA);
496 offset += (length-4);
500 break;
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);
508 offset += 2;
509 proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
510 break;
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);
517 offset += 2;
518 proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
519 offset += 2;
520 proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
521 break;
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);
527 offset++;
528 break;
530 case 0xd2: /* Signed Write Command */
532 guint8 length;
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);
536 offset += 2;
537 length = tvb_length_remaining(tvb, offset);
538 if (length > 12) {
539 proto_tree_add_item(st, hf_btatt_value, tvb, offset, length-12, ENC_NA);
540 offset+=length-12;
543 proto_tree_add_item(st, hf_btatt_sign_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
544 offset+=4;
545 proto_tree_add_item(st, hf_btatt_signature, tvb, offset, 8, ENC_NA);
546 offset+=8;
547 break;
549 default:
550 break;
552 return offset;
555 void
556 proto_register_btatt(void)
558 module_t *module;
560 static hf_register_info hf[] = {
561 {&hf_btatt_opcode,
562 {"Opcode", "btatt.opcode",
563 FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
564 NULL, HFILL}
566 {&hf_btatt_handles_info,
567 {"Handles Info", "btatt.handles_info",
568 FT_NONE, BASE_NONE, NULL, 0x0,
569 NULL, HFILL}
571 {&hf_btatt_attribute_data,
572 {"Attribute Data", "btatt.attribute_data",
573 FT_NONE, BASE_NONE, NULL, 0x0,
574 NULL, HFILL}
576 {&hf_btatt_handle,
577 {"Handle", "btatt.handle",
578 FT_UINT16, BASE_HEX, NULL, 0x0,
579 NULL, HFILL}
581 {&hf_btatt_starting_handle,
582 {"Starting Handle", "btatt.starting_handle",
583 FT_UINT16, BASE_HEX, NULL, 0x0,
584 NULL, HFILL}
586 {&hf_btatt_ending_handle,
587 {"Ending Handle", "btatt.ending_handle",
588 FT_UINT16, BASE_HEX, NULL, 0x0,
589 NULL, HFILL}
591 {&hf_btatt_group_end_handle,
592 {"Group End Handle", "btatt.group_end_handle",
593 FT_UINT16, BASE_HEX, NULL, 0x0,
594 NULL, HFILL}
596 {&hf_btatt_value,
597 {"Value", "btatt.value",
598 FT_BYTES, BASE_NONE, NULL, 0x0,
599 NULL, HFILL}
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,
604 NULL, HFILL}
606 {&hf_btatt_handle_in_error,
607 {"Handle in Error", "btatt.handle_in_error",
608 FT_UINT16, BASE_HEX, NULL, 0x0,
609 NULL, HFILL}
611 {&hf_btatt_error_code,
612 {"Error Code", "btatt.error_code",
613 FT_UINT8, BASE_HEX, VALS(error_vals), 0x0,
614 NULL, HFILL}
616 {&hf_btatt_uuid16,
617 {"UUID", "btatt.uuid16",
618 FT_UINT16, BASE_HEX |BASE_EXT_STRING, &uuid_vals_ext, 0x0,
619 NULL, HFILL}
621 {&hf_btatt_uuid128,
622 {"UUID", "btatt.uuid128",
623 FT_BYTES, BASE_NONE, NULL, 0x0,
624 NULL, HFILL}
626 {&hf_btatt_client_rx_mtu,
627 {"Client Rx MTU", "btatt.client_rx_mtu",
628 FT_UINT16, BASE_DEC, NULL, 0x0,
629 NULL, HFILL}
631 {&hf_btatt_server_rx_mtu,
632 {"Server Rx MTU", "btatt.server_rx_mtu",
633 FT_UINT16, BASE_DEC, NULL, 0x0,
634 NULL, HFILL}
636 {&hf_btatt_uuid_format,
637 {"UUID Format", "btatt.uuid_format",
638 FT_UINT8, BASE_HEX, VALS(uuid_format_vals), 0x0,
639 NULL, HFILL}
641 {&hf_btatt_length,
642 {"Length", "btatt.length",
643 FT_UINT8, BASE_DEC, NULL, 0x0,
644 "Length of Handle/Value Pair", HFILL}
646 {&hf_btatt_offset,
647 {"Offset", "btatt.offset",
648 FT_UINT16, BASE_DEC, NULL, 0x0,
649 NULL, HFILL}
651 {&hf_btatt_flags,
652 {"Flags", "btatt.flags",
653 FT_UINT8, BASE_HEX, VALS(flags_vals), 0x0,
654 NULL, HFILL}
656 {&hf_btatt_sign_counter,
657 {"Sign Counter", "btatt.sign_counter",
658 FT_UINT32, BASE_DEC, NULL, 0x0,
659 NULL, HFILL}
661 {&hf_btatt_signature,
662 {"Signature", "btatt.signature",
663 FT_BYTES, BASE_NONE, NULL, 0x0,
664 NULL, HFILL}
668 /* Setup protocol subtree array */
669 static gint *ett[] = {
670 &ett_btatt,
671 &ett_btatt_list
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.");
698 void
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
708 * Local variables:
709 * c-basic-offset: 4
710 * tab-width: 8
711 * indent-tabs-mode: nil
712 * End:
714 * vi: set shiftwidth=4 tabstop=8 expandtab:
715 * :indentSize=4:tabSize=8:noTabs=true: