1*e018180dSDominic Spill /* packet-btatt.c
2*e018180dSDominic Spill * Routines for Bluetooth Attribute Protocol dissection
3*e018180dSDominic Spill *
4*e018180dSDominic Spill * Copyright 2012, Allan M. Madsen <[email protected]>
5*e018180dSDominic Spill *
6*e018180dSDominic Spill * $Id$
7*e018180dSDominic Spill *
8*e018180dSDominic Spill * Wireshark - Network traffic analyzer
9*e018180dSDominic Spill * By Gerald Combs <[email protected]>
10*e018180dSDominic Spill * Copyright 1998 Gerald Combs
11*e018180dSDominic Spill *
12*e018180dSDominic Spill * Wireshark - Network traffic analyzer
13*e018180dSDominic Spill * By Gerald Combs <[email protected]>
14*e018180dSDominic Spill * Copyright 1998 Gerald Combs
15*e018180dSDominic Spill *
16*e018180dSDominic Spill * This program is free software; you can redistribute it and/or
17*e018180dSDominic Spill * modify it under the terms of the GNU General Public License
18*e018180dSDominic Spill * as published by the Free Software Foundation; either version 2
19*e018180dSDominic Spill * of the License, or (at your option) any later version.
20*e018180dSDominic Spill *
21*e018180dSDominic Spill * This program is distributed in the hope that it will be useful,
22*e018180dSDominic Spill * but WITHOUT ANY WARRANTY; without even the implied warranty of
23*e018180dSDominic Spill * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24*e018180dSDominic Spill * GNU General Public License for more details.
25*e018180dSDominic Spill *
26*e018180dSDominic Spill * You should have received a copy of the GNU General Public License
27*e018180dSDominic Spill * along with this program; if not, write to the Free Software
28*e018180dSDominic Spill * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29*e018180dSDominic Spill */
30*e018180dSDominic Spill
31*e018180dSDominic Spill #include "config.h"
32*e018180dSDominic Spill
33*e018180dSDominic Spill #include <epan/packet.h>
34*e018180dSDominic Spill #include <epan/prefs.h>
35*e018180dSDominic Spill #include <epan/expert.h>
36*e018180dSDominic Spill #include <epan/dissectors/packet-btl2cap.h>
37*e018180dSDominic Spill
38*e018180dSDominic Spill #define BTL2CAP_PSM_ATT 0x001f
39*e018180dSDominic Spill #define BTL2CAP_FIXED_CID_ATT 0x0004
40*e018180dSDominic Spill
41*e018180dSDominic Spill /* Initialize the protocol and registered fields */
42*e018180dSDominic Spill static int proto_btatt = -1;
43*e018180dSDominic Spill
44*e018180dSDominic Spill static int hf_btatt_opcode = -1;
45*e018180dSDominic Spill static int hf_btatt_handle = -1;
46*e018180dSDominic Spill static int hf_btatt_starting_handle = -1;
47*e018180dSDominic Spill static int hf_btatt_ending_handle = -1;
48*e018180dSDominic Spill static int hf_btatt_group_end_handle = -1;
49*e018180dSDominic Spill static int hf_btatt_value = -1;
50*e018180dSDominic Spill static int hf_btatt_req_opcode_in_error = -1;
51*e018180dSDominic Spill static int hf_btatt_handle_in_error = -1;
52*e018180dSDominic Spill static int hf_btatt_error_code = -1;
53*e018180dSDominic Spill static int hf_btatt_uuid16 = -1;
54*e018180dSDominic Spill static int hf_btatt_uuid128 = -1;
55*e018180dSDominic Spill static int hf_btatt_client_rx_mtu = -1;
56*e018180dSDominic Spill static int hf_btatt_server_rx_mtu = -1;
57*e018180dSDominic Spill static int hf_btatt_uuid_format = -1;
58*e018180dSDominic Spill static int hf_btatt_length = -1;
59*e018180dSDominic Spill static int hf_btatt_offset = -1;
60*e018180dSDominic Spill static int hf_btatt_flags = -1;
61*e018180dSDominic Spill static int hf_btatt_sign_counter = -1;
62*e018180dSDominic Spill static int hf_btatt_signature = -1;
63*e018180dSDominic Spill
64*e018180dSDominic Spill /* Initialize the subtree pointers */
65*e018180dSDominic Spill static gint ett_btatt = -1;
66*e018180dSDominic Spill static gint ett_btatt_list = -1;
67*e018180dSDominic Spill
68*e018180dSDominic Spill /* Opcodes */
69*e018180dSDominic Spill static const value_string opcode_vals[] = {
70*e018180dSDominic Spill {0x01, "Error Response"},
71*e018180dSDominic Spill {0x02, "Exchange MTU Request"},
72*e018180dSDominic Spill {0x03, "Exchange MTU Response"},
73*e018180dSDominic Spill {0x04, "Find Information Request"},
74*e018180dSDominic Spill {0x05, "Find Information Response"},
75*e018180dSDominic Spill {0x06, "Find By Type Value Request"},
76*e018180dSDominic Spill {0x07, "Find By Type Value Response"},
77*e018180dSDominic Spill {0x08, "Read By Type Request"},
78*e018180dSDominic Spill {0x09, "Read By Type Response"},
79*e018180dSDominic Spill {0x0a, "Read Request"},
80*e018180dSDominic Spill {0x0b, "Read Response"},
81*e018180dSDominic Spill {0x0c, "Read Blob Request"},
82*e018180dSDominic Spill {0x0d, "Read Blob Response"},
83*e018180dSDominic Spill {0x0e, "Read Multiple Request"},
84*e018180dSDominic Spill {0x0f, "Read Multiple Response"},
85*e018180dSDominic Spill {0x10, "Read By Group Type Request"},
86*e018180dSDominic Spill {0x11, "Read By Group Type Response"},
87*e018180dSDominic Spill {0x12, "Write Request"},
88*e018180dSDominic Spill {0x13, "Write Response"},
89*e018180dSDominic Spill {0x16, "Prepare Write Request"},
90*e018180dSDominic Spill {0x17, "Prepare Write Response"},
91*e018180dSDominic Spill {0x18, "Execute Write Request"},
92*e018180dSDominic Spill {0x19, "Execute Write Response"},
93*e018180dSDominic Spill {0x1B, "Handle Value Notification"},
94*e018180dSDominic Spill {0x1D, "Handle Value Indication"},
95*e018180dSDominic Spill {0x1E, "Handle Value Confirmation"},
96*e018180dSDominic Spill {0x52, "Write Command"},
97*e018180dSDominic Spill {0xD2, "Signed Write Command"},
98*e018180dSDominic Spill {0x0, NULL}
99*e018180dSDominic Spill };
100*e018180dSDominic Spill
101*e018180dSDominic Spill /* Error codes */
102*e018180dSDominic Spill static const value_string error_vals[] = {
103*e018180dSDominic Spill {0x01, "Invalid Handle"},
104*e018180dSDominic Spill {0x02, "Read Not Permitted"},
105*e018180dSDominic Spill {0x03, "Write Not Permitted"},
106*e018180dSDominic Spill {0x04, "Invalid PDU"},
107*e018180dSDominic Spill {0x05, "Insufficient Authentication"},
108*e018180dSDominic Spill {0x06, "Request Not Supported"},
109*e018180dSDominic Spill {0x07, "Invalid Offset"},
110*e018180dSDominic Spill {0x08, "Insufficient Authorization"},
111*e018180dSDominic Spill {0x09, "Prepare Queue Full"},
112*e018180dSDominic Spill {0x0a, "Attribute Not Found"},
113*e018180dSDominic Spill {0x0b, "Attribute Not Long"},
114*e018180dSDominic Spill {0x0c, "Insufficient Encryption Key Size"},
115*e018180dSDominic Spill {0x0d, "Invalid Attribute Value Length"},
116*e018180dSDominic Spill {0x0e, "Unlikely Error"},
117*e018180dSDominic Spill {0x0f, "Insufficient Encryption"},
118*e018180dSDominic Spill {0x10, "Unsupported Group Type"},
119*e018180dSDominic Spill {0x11, "Insufficient Resources"},
120*e018180dSDominic Spill {0x80, "Application Error"},
121*e018180dSDominic Spill {0xfd, "Improper Client Characteristic Configuration Descriptor"},
122*e018180dSDominic Spill {0xfe, "Procedure Already In Progress"},
123*e018180dSDominic Spill {0xff, "Out of Range"},
124*e018180dSDominic Spill {0x0, NULL}
125*e018180dSDominic Spill };
126*e018180dSDominic Spill
127*e018180dSDominic Spill static const value_string uuid_vals[] = {
128*e018180dSDominic Spill /* Services - http://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
129*e018180dSDominic Spill {0x1800, "Generic Access"},
130*e018180dSDominic Spill {0x1801, "Generic Attribute"},
131*e018180dSDominic Spill {0x1802, "Immediate Alert"},
132*e018180dSDominic Spill {0x1803, "Link Loss"},
133*e018180dSDominic Spill {0x1804, "Tx Power"},
134*e018180dSDominic Spill {0x1805, "Current Time Service"},
135*e018180dSDominic Spill {0x1806, "Reference Time Update Service"},
136*e018180dSDominic Spill {0x1807, "Next DST Change Service"},
137*e018180dSDominic Spill {0x1808, "Glucose"},
138*e018180dSDominic Spill {0x1809, "Health Thermometer"},
139*e018180dSDominic Spill {0x180a, "Device Information"},
140*e018180dSDominic Spill {0x180d, "Heart Rate"},
141*e018180dSDominic Spill {0x180e, "Phone Alert Status Service"},
142*e018180dSDominic Spill {0x180f, "Battery Service"},
143*e018180dSDominic Spill {0x1810, "Blood Pressure"},
144*e018180dSDominic Spill {0x1811, "Alert Notification Service"},
145*e018180dSDominic Spill {0x1812, "Human Interface Device"},
146*e018180dSDominic Spill {0x1813, "Scan Parameters"},
147*e018180dSDominic Spill {0x1814, "Running Speed and Cadence"},
148*e018180dSDominic Spill {0x1816, "Cycling Speed and Cadence"},
149*e018180dSDominic Spill /* Declarations - http://developer.bluetooth.org/gatt/declarations/Pages/DeclarationsHome.aspx */
150*e018180dSDominic Spill {0x2800, "GATT Primary Service Declaration"},
151*e018180dSDominic Spill {0x2801, "GATT Secondary Service Declaration"},
152*e018180dSDominic Spill {0x2802, "GATT Include Declaration"},
153*e018180dSDominic Spill {0x2803, "GATT Characteristic Declaration"},
154*e018180dSDominic Spill /* Descriptors - http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx */
155*e018180dSDominic Spill {0x2900, "Characteristic Extended Properties"},
156*e018180dSDominic Spill {0x2901, "Characteristic User Description"},
157*e018180dSDominic Spill {0x2902, "Client Characteristic Configuration"},
158*e018180dSDominic Spill {0x2903, "Server Characteristic Configuration"},
159*e018180dSDominic Spill {0x2904, "Characteristic Presentation Format"},
160*e018180dSDominic Spill {0x2905, "Characteristic Aggregate Format"},
161*e018180dSDominic Spill {0x2906, "Valid Range"},
162*e018180dSDominic Spill {0x2907, "External Report Reference"},
163*e018180dSDominic Spill {0x2908, "Report Reference"},
164*e018180dSDominic Spill /* Characteristics - http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx */
165*e018180dSDominic Spill {0x2a00, "Device Name"},
166*e018180dSDominic Spill {0x2a01, "Appearance"},
167*e018180dSDominic Spill {0x2a02, "Peripheral Privacy Flag"},
168*e018180dSDominic Spill {0x2a03, "Reconnection Address"},
169*e018180dSDominic Spill {0x2a04, "Peripheral Preferred Connection Parameters"},
170*e018180dSDominic Spill {0x2a05, "Service Changed"},
171*e018180dSDominic Spill {0x2a06, "Alert Level"},
172*e018180dSDominic Spill {0x2a07, "Tx Power Level"},
173*e018180dSDominic Spill {0x2a08, "Date Time"},
174*e018180dSDominic Spill {0x2a09, "Day of Week"},
175*e018180dSDominic Spill {0x2a0a, "Day Date Time"},
176*e018180dSDominic Spill {0x2a0c, "Exact Time 256"},
177*e018180dSDominic Spill {0x2a0d, "DST Offset"},
178*e018180dSDominic Spill {0x2a0e, "Time Zone"},
179*e018180dSDominic Spill {0x2a0f, "Local Time Information"},
180*e018180dSDominic Spill {0x2a11, "Time with DST"},
181*e018180dSDominic Spill {0x2a12, "Time Accuracy"},
182*e018180dSDominic Spill {0x2a13, "Time Source"},
183*e018180dSDominic Spill {0x2a14, "Reference Time Information"},
184*e018180dSDominic Spill {0x2a16, "Time Update Control Point"},
185*e018180dSDominic Spill {0x2a17, "Time Update State"},
186*e018180dSDominic Spill {0x2a18, "Glucose Measurement"},
187*e018180dSDominic Spill {0x2a19, "Battery Level"},
188*e018180dSDominic Spill {0x2a1c, "Temperature Measurement"},
189*e018180dSDominic Spill {0x2a1d, "Temperature Type"},
190*e018180dSDominic Spill {0x2a1e, "Intermediate Temperature"},
191*e018180dSDominic Spill {0x2a21, "Measurement Interval"},
192*e018180dSDominic Spill {0x2a22, "Boot Keyboard Input Report"},
193*e018180dSDominic Spill {0x2a23, "System ID"},
194*e018180dSDominic Spill {0x2a24, "Model Number String"},
195*e018180dSDominic Spill {0x2a25, "Serial Number String"},
196*e018180dSDominic Spill {0x2a26, "Firmware Revision String"},
197*e018180dSDominic Spill {0x2a27, "Hardware Revision String"},
198*e018180dSDominic Spill {0x2a28, "Software Revision String"},
199*e018180dSDominic Spill {0x2a29, "Manufacturer Name String"},
200*e018180dSDominic Spill {0x2a2a, "IEEE 11073-20601 Reg. Cert. Data List"},
201*e018180dSDominic Spill {0x2a2b, "Current Time"},
202*e018180dSDominic Spill {0x2a31, "Scan Refresh"},
203*e018180dSDominic Spill {0x2a32, "Boot Keyboard Output Report"},
204*e018180dSDominic Spill {0x2a33, "Boot Mouse Input Report"},
205*e018180dSDominic Spill {0x2a34, "Glucose Measurement Context"},
206*e018180dSDominic Spill {0x2a35, "Blood Pressure Measurement"},
207*e018180dSDominic Spill {0x2a36, "Intermediate Cuff Pressure"},
208*e018180dSDominic Spill {0x2a37, "Heart Rate Measurement"},
209*e018180dSDominic Spill {0x2a38, "Body Sensor Location"},
210*e018180dSDominic Spill {0x2a39, "Heart Rate Control Point"},
211*e018180dSDominic Spill {0x2a3f, "Alert Status"},
212*e018180dSDominic Spill {0x2a40, "Ringer Control Point"},
213*e018180dSDominic Spill {0x2a41, "Ringer Setting"},
214*e018180dSDominic Spill {0x2a42, "Alert Category ID Bit Mask"},
215*e018180dSDominic Spill {0x2a43, "Alert Category ID"},
216*e018180dSDominic Spill {0x2a44, "Alert Notification Control Point"},
217*e018180dSDominic Spill {0x2a45, "Unread Alert Status"},
218*e018180dSDominic Spill {0x2a46, "New Alert"},
219*e018180dSDominic Spill {0x2a47, "Supported New Alert Category"},
220*e018180dSDominic Spill {0x2a48, "Supported Unread Alert Category"},
221*e018180dSDominic Spill {0x2a49, "Blood Pressure Feature"},
222*e018180dSDominic Spill {0x2a4a, "HID Information"},
223*e018180dSDominic Spill {0x2a4b, "Report Map"},
224*e018180dSDominic Spill {0x2a4c, "HID Control Point"},
225*e018180dSDominic Spill {0x2a4d, "Report"},
226*e018180dSDominic Spill {0x2a4e, "Protocol Mode"},
227*e018180dSDominic Spill {0x2a4f, "Scan Interval Window"},
228*e018180dSDominic Spill {0x2a50, "PnP ID"},
229*e018180dSDominic Spill {0x2a51, "Glucose Feature"},
230*e018180dSDominic Spill {0x2a52, "Record Access Control Point"},
231*e018180dSDominic Spill {0x2a53, "RSC Measurement"},
232*e018180dSDominic Spill {0x2a54, "RSC Feature"},
233*e018180dSDominic Spill {0x2a55, "SC Control Point"},
234*e018180dSDominic Spill {0x2a5b, "CSC Measurement"},
235*e018180dSDominic Spill {0x2a5c, "CSC Feature"},
236*e018180dSDominic Spill {0x2a5d, "Sensor Location"},
237*e018180dSDominic Spill {0x0, NULL}
238*e018180dSDominic Spill };
239*e018180dSDominic Spill static value_string_ext uuid_vals_ext = VALUE_STRING_EXT_INIT(uuid_vals);
240*e018180dSDominic Spill
241*e018180dSDominic Spill static const value_string uuid_format_vals[] = {
242*e018180dSDominic Spill {0x01, "16-bit UUIDs"},
243*e018180dSDominic Spill {0x02, "128-bit UUIDs"},
244*e018180dSDominic Spill {0x0, NULL}
245*e018180dSDominic Spill };
246*e018180dSDominic Spill
247*e018180dSDominic Spill static const value_string flags_vals[] = {
248*e018180dSDominic Spill {0x00, "Cancel All"},
249*e018180dSDominic Spill {0x01, "Immediately Write All"},
250*e018180dSDominic Spill {0x0, NULL}
251*e018180dSDominic Spill };
252*e018180dSDominic Spill
253*e018180dSDominic Spill static void
dissect_btatt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)254*e018180dSDominic Spill dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
255*e018180dSDominic Spill {
256*e018180dSDominic Spill int offset = 0;
257*e018180dSDominic Spill proto_item *ti, *item;
258*e018180dSDominic Spill proto_tree *st, *ltree;
259*e018180dSDominic Spill guint8 opcode;
260*e018180dSDominic Spill
261*e018180dSDominic Spill col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATT");
262*e018180dSDominic Spill
263*e018180dSDominic Spill switch (pinfo->p2p_dir) {
264*e018180dSDominic Spill
265*e018180dSDominic Spill case P2P_DIR_SENT:
266*e018180dSDominic Spill col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
267*e018180dSDominic Spill break;
268*e018180dSDominic Spill
269*e018180dSDominic Spill case P2P_DIR_RECV:
270*e018180dSDominic Spill col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
271*e018180dSDominic Spill break;
272*e018180dSDominic Spill
273*e018180dSDominic Spill case P2P_DIR_UNKNOWN:
274*e018180dSDominic Spill break;
275*e018180dSDominic Spill
276*e018180dSDominic Spill default:
277*e018180dSDominic Spill col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
278*e018180dSDominic Spill pinfo->p2p_dir);
279*e018180dSDominic Spill break;
280*e018180dSDominic Spill }
281*e018180dSDominic Spill
282*e018180dSDominic Spill if (tvb_length_remaining(tvb, 0) < 1)
283*e018180dSDominic Spill return;
284*e018180dSDominic Spill
285*e018180dSDominic Spill ti = proto_tree_add_item(tree, proto_btatt, tvb, 0, -1, ENC_NA);
286*e018180dSDominic Spill st = proto_item_add_subtree(ti, ett_btatt);
287*e018180dSDominic Spill
288*e018180dSDominic Spill item = proto_tree_add_item(st, hf_btatt_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN);
289*e018180dSDominic Spill opcode = tvb_get_guint8(tvb, 0);
290*e018180dSDominic Spill offset++;
291*e018180dSDominic Spill
292*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(opcode, opcode_vals, "<unknown>"));
293*e018180dSDominic Spill
294*e018180dSDominic Spill switch (opcode) {
295*e018180dSDominic Spill case 0x01: /* Error Response */
296*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_req_opcode_in_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
297*e018180dSDominic Spill offset++;
298*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle_in_error, tvb, offset, 2, ENC_LITTLE_ENDIAN);
299*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, " - %s, Handle: 0x%04x",
300*e018180dSDominic Spill val_to_str(tvb_get_guint8(tvb, offset+2), error_vals, "<unknown>"),
301*e018180dSDominic Spill tvb_get_letohs(tvb, offset));
302*e018180dSDominic Spill offset += 2;
303*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
304*e018180dSDominic Spill offset++;
305*e018180dSDominic Spill break;
306*e018180dSDominic Spill
307*e018180dSDominic Spill case 0x02: /* Exchange MTU Request */
308*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Client Rx MTU: %u", tvb_get_letohs(tvb, offset));
309*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_client_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
310*e018180dSDominic Spill offset += 2;
311*e018180dSDominic Spill break;
312*e018180dSDominic Spill
313*e018180dSDominic Spill case 0x03: /* Exchange MTU Response */
314*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Server Rx MTU: %u", tvb_get_letohs(tvb, offset));
315*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_server_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
316*e018180dSDominic Spill offset += 2;
317*e018180dSDominic Spill break;
318*e018180dSDominic Spill
319*e018180dSDominic Spill case 0x04: /* Find Information Request */
320*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Handles: 0x%04x..0x%04x",
321*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
322*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
323*e018180dSDominic Spill offset += 2;
324*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
325*e018180dSDominic Spill offset += 2;
326*e018180dSDominic Spill break;
327*e018180dSDominic Spill
328*e018180dSDominic Spill case 0x05: /* Find Information Response */
329*e018180dSDominic Spill {
330*e018180dSDominic Spill guint8 format = tvb_get_guint8(tvb, offset);
331*e018180dSDominic Spill
332*e018180dSDominic Spill item = proto_tree_add_item(st, hf_btatt_uuid_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
333*e018180dSDominic Spill offset++;
334*e018180dSDominic Spill
335*e018180dSDominic Spill if( format == 1 ) {
336*e018180dSDominic Spill while( tvb_length_remaining(tvb, offset) > 0) {
337*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
338*e018180dSDominic Spill offset += 2;
339*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
340*e018180dSDominic Spill offset += 2;
341*e018180dSDominic Spill }
342*e018180dSDominic Spill }
343*e018180dSDominic Spill else if( format == 2 ) {
344*e018180dSDominic Spill while( tvb_length_remaining(tvb, offset) > 0) {
345*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
346*e018180dSDominic Spill offset += 2;
347*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
348*e018180dSDominic Spill offset += 16;
349*e018180dSDominic Spill }
350*e018180dSDominic Spill }
351*e018180dSDominic Spill else {
352*e018180dSDominic Spill expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "Unknown format");
353*e018180dSDominic Spill }
354*e018180dSDominic Spill }
355*e018180dSDominic Spill break;
356*e018180dSDominic Spill
357*e018180dSDominic Spill case 0x06: /* Find By Type Value Request */
358*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x",
359*e018180dSDominic Spill val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"),
360*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
361*e018180dSDominic Spill
362*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
363*e018180dSDominic Spill offset += 2;
364*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
365*e018180dSDominic Spill offset += 2;
366*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
367*e018180dSDominic Spill offset += 2;
368*e018180dSDominic Spill if( tvb_length_remaining(tvb, offset) > 0)
369*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
370*e018180dSDominic Spill break;
371*e018180dSDominic Spill
372*e018180dSDominic Spill case 0x07: /* Find By Type Value Response */
373*e018180dSDominic Spill while( tvb_length_remaining(tvb, offset) > 0 ) {
374*e018180dSDominic Spill item = proto_tree_add_text(st, tvb, offset, 4,
375*e018180dSDominic Spill "Handles Info, Handle: 0x%04x, Group End Handle: 0x%04x",
376*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
377*e018180dSDominic Spill
378*e018180dSDominic Spill ltree = proto_item_add_subtree(item, ett_btatt_list);
379*e018180dSDominic Spill
380*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
381*e018180dSDominic Spill offset += 2;
382*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
383*e018180dSDominic Spill offset += 2;
384*e018180dSDominic Spill }
385*e018180dSDominic Spill break;
386*e018180dSDominic Spill
387*e018180dSDominic Spill case 0x08: /* Read By Type Request */
388*e018180dSDominic Spill case 0x10: /* Read By Group Type Request */
389*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x",
390*e018180dSDominic Spill val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"),
391*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
392*e018180dSDominic Spill
393*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
394*e018180dSDominic Spill offset += 2;
395*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
396*e018180dSDominic Spill offset += 2;
397*e018180dSDominic Spill
398*e018180dSDominic Spill if (tvb_length_remaining(tvb, offset) == 2) {
399*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
400*e018180dSDominic Spill offset += 2;
401*e018180dSDominic Spill }
402*e018180dSDominic Spill else if (tvb_length_remaining(tvb, offset) == 16) {
403*e018180dSDominic Spill item = proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
404*e018180dSDominic Spill proto_item_append_text(item, " (%s)", val_to_str_ext_const(tvb_get_letohs(tvb, offset),
405*e018180dSDominic Spill &uuid_vals_ext, "<unknown>"));
406*e018180dSDominic Spill offset += 16;
407*e018180dSDominic Spill }
408*e018180dSDominic Spill break;
409*e018180dSDominic Spill
410*e018180dSDominic Spill case 0x09: /* Read By Type Response */
411*e018180dSDominic Spill {
412*e018180dSDominic Spill guint8 length = tvb_get_guint8(tvb, offset);
413*e018180dSDominic Spill
414*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
415*e018180dSDominic Spill offset++;
416*e018180dSDominic Spill
417*e018180dSDominic Spill if(length > 0) {
418*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u",
419*e018180dSDominic Spill tvb_length_remaining(tvb, offset)/length);
420*e018180dSDominic Spill
421*e018180dSDominic Spill while (tvb_length_remaining(tvb, offset) >= length)
422*e018180dSDominic Spill {
423*e018180dSDominic Spill item = proto_tree_add_text(st, tvb, offset, length, "Attribute Data, Handle: 0x%04x",
424*e018180dSDominic Spill tvb_get_letohs(tvb, offset));
425*e018180dSDominic Spill
426*e018180dSDominic Spill ltree = proto_item_add_subtree(item, ett_btatt_list);
427*e018180dSDominic Spill
428*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
429*e018180dSDominic Spill offset += 2;
430*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length-2, ENC_LITTLE_ENDIAN);
431*e018180dSDominic Spill offset += (length-2);
432*e018180dSDominic Spill }
433*e018180dSDominic Spill }
434*e018180dSDominic Spill }
435*e018180dSDominic Spill break;
436*e018180dSDominic Spill
437*e018180dSDominic Spill case 0x0a: /* Read Request */
438*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
439*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
440*e018180dSDominic Spill offset += 2;
441*e018180dSDominic Spill break;
442*e018180dSDominic Spill
443*e018180dSDominic Spill case 0x0b: /* Read Response */
444*e018180dSDominic Spill case 0x0d: /* Read Blob Response */
445*e018180dSDominic Spill case 0x0f: /* Multiple Read Response */
446*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
447*e018180dSDominic Spill break;
448*e018180dSDominic Spill
449*e018180dSDominic Spill case 0x0c: /* Read Blob Request */
450*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u",
451*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
452*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
453*e018180dSDominic Spill offset += 2;
454*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
455*e018180dSDominic Spill offset += 2;
456*e018180dSDominic Spill break;
457*e018180dSDominic Spill
458*e018180dSDominic Spill case 0x0e: /* Multiple Read Request */
459*e018180dSDominic Spill if(tvb_length_remaining(tvb, offset) < 4) {
460*e018180dSDominic Spill expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
461*e018180dSDominic Spill "Too few handles, should be 2 or more");
462*e018180dSDominic Spill break;
463*e018180dSDominic Spill }
464*e018180dSDominic Spill
465*e018180dSDominic Spill col_append_str(pinfo->cinfo, COL_INFO, ", Handles: ");
466*e018180dSDominic Spill while (tvb_length_remaining(tvb, offset) >= 2) {
467*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
468*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, "0x%04x ", tvb_get_letohs(tvb, offset));
469*e018180dSDominic Spill offset += 2;
470*e018180dSDominic Spill }
471*e018180dSDominic Spill break;
472*e018180dSDominic Spill
473*e018180dSDominic Spill case 0x11: /* Read By Group Type Response */
474*e018180dSDominic Spill {
475*e018180dSDominic Spill guint8 length = tvb_get_guint8(tvb, offset);
476*e018180dSDominic Spill
477*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
478*e018180dSDominic Spill offset++;
479*e018180dSDominic Spill
480*e018180dSDominic Spill if(length > 0) {
481*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u", tvb_length_remaining(tvb, offset)/length);
482*e018180dSDominic Spill
483*e018180dSDominic Spill while (tvb_length_remaining(tvb, offset) >= length) {
484*e018180dSDominic Spill item = proto_tree_add_text(st, tvb, offset, length,
485*e018180dSDominic Spill "Attribute Data, Handle: 0x%04x, Group End Handle: 0x%04x",
486*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
487*e018180dSDominic Spill
488*e018180dSDominic Spill ltree = proto_item_add_subtree(item, ett_btatt_list);
489*e018180dSDominic Spill
490*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
491*e018180dSDominic Spill offset += 2;
492*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
493*e018180dSDominic Spill offset += 2;
494*e018180dSDominic Spill proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length-4, ENC_LITTLE_ENDIAN);
495*e018180dSDominic Spill offset += (length-4);
496*e018180dSDominic Spill }
497*e018180dSDominic Spill }
498*e018180dSDominic Spill }
499*e018180dSDominic Spill break;
500*e018180dSDominic Spill
501*e018180dSDominic Spill case 0x12: /* Write Request */
502*e018180dSDominic Spill case 0x52: /* Write Command */
503*e018180dSDominic Spill case 0x1b: /* Handle Value Notification */
504*e018180dSDominic Spill case 0x1d: /* Handle Value Indication */
505*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
506*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
507*e018180dSDominic Spill offset += 2;
508*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
509*e018180dSDominic Spill break;
510*e018180dSDominic Spill
511*e018180dSDominic Spill case 0x16: /* Prepare Write Request */
512*e018180dSDominic Spill case 0x17: /* Prepare Write Response */
513*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u",
514*e018180dSDominic Spill tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
515*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
516*e018180dSDominic Spill offset += 2;
517*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
518*e018180dSDominic Spill offset += 2;
519*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
520*e018180dSDominic Spill break;
521*e018180dSDominic Spill
522*e018180dSDominic Spill case 0x18: /* Execute Write Request */
523*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
524*e018180dSDominic Spill val_to_str(tvb_get_guint8(tvb, offset), flags_vals, "<unknown>"));
525*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
526*e018180dSDominic Spill offset++;
527*e018180dSDominic Spill break;
528*e018180dSDominic Spill
529*e018180dSDominic Spill case 0xd2: /* Signed Write Command */
530*e018180dSDominic Spill {
531*e018180dSDominic Spill guint8 length;
532*e018180dSDominic Spill
533*e018180dSDominic Spill col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
534*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
535*e018180dSDominic Spill offset += 2;
536*e018180dSDominic Spill length = tvb_length_remaining(tvb, offset);
537*e018180dSDominic Spill if (length > 12) {
538*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_value, tvb, offset, length-12, ENC_NA);
539*e018180dSDominic Spill offset+=length-12;
540*e018180dSDominic Spill }
541*e018180dSDominic Spill
542*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_sign_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
543*e018180dSDominic Spill offset+=4;
544*e018180dSDominic Spill proto_tree_add_item(st, hf_btatt_signature, tvb, offset, 8, ENC_NA);
545*e018180dSDominic Spill offset+=8;
546*e018180dSDominic Spill break;
547*e018180dSDominic Spill }
548*e018180dSDominic Spill default:
549*e018180dSDominic Spill break;
550*e018180dSDominic Spill }
551*e018180dSDominic Spill }
552*e018180dSDominic Spill
553*e018180dSDominic Spill void
proto_register_btatt(void)554*e018180dSDominic Spill proto_register_btatt(void)
555*e018180dSDominic Spill {
556*e018180dSDominic Spill module_t *module;
557*e018180dSDominic Spill
558*e018180dSDominic Spill static hf_register_info hf[] = {
559*e018180dSDominic Spill {&hf_btatt_opcode,
560*e018180dSDominic Spill {"Opcode", "btatt.opcode",
561*e018180dSDominic Spill FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
562*e018180dSDominic Spill NULL, HFILL}
563*e018180dSDominic Spill },
564*e018180dSDominic Spill {&hf_btatt_handle,
565*e018180dSDominic Spill {"Handle", "btatt.handle",
566*e018180dSDominic Spill FT_UINT16, BASE_HEX, NULL, 0x0,
567*e018180dSDominic Spill NULL, HFILL}
568*e018180dSDominic Spill },
569*e018180dSDominic Spill {&hf_btatt_starting_handle,
570*e018180dSDominic Spill {"Starting Handle", "btatt.starting_handle",
571*e018180dSDominic Spill FT_UINT16, BASE_HEX, NULL, 0x0,
572*e018180dSDominic Spill NULL, HFILL}
573*e018180dSDominic Spill },
574*e018180dSDominic Spill {&hf_btatt_ending_handle,
575*e018180dSDominic Spill {"Ending Handle", "btatt.ending_handle",
576*e018180dSDominic Spill FT_UINT16, BASE_HEX, NULL, 0x0,
577*e018180dSDominic Spill NULL, HFILL}
578*e018180dSDominic Spill },
579*e018180dSDominic Spill {&hf_btatt_group_end_handle,
580*e018180dSDominic Spill {"Group End Handle", "btatt.group_end_handle",
581*e018180dSDominic Spill FT_UINT16, BASE_HEX, NULL, 0x0,
582*e018180dSDominic Spill NULL, HFILL}
583*e018180dSDominic Spill },
584*e018180dSDominic Spill {&hf_btatt_value,
585*e018180dSDominic Spill {"Value", "btatt.value",
586*e018180dSDominic Spill FT_BYTES, BASE_NONE, NULL, 0x0,
587*e018180dSDominic Spill NULL, HFILL}
588*e018180dSDominic Spill },
589*e018180dSDominic Spill {&hf_btatt_req_opcode_in_error,
590*e018180dSDominic Spill {"Request Opcode in Error", "btatt.req_opcode_in_error",
591*e018180dSDominic Spill FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
592*e018180dSDominic Spill NULL, HFILL}
593*e018180dSDominic Spill },
594*e018180dSDominic Spill {&hf_btatt_handle_in_error,
595*e018180dSDominic Spill {"Handle in Error", "btatt.handle_in_error",
596*e018180dSDominic Spill FT_UINT16, BASE_HEX, NULL, 0x0,
597*e018180dSDominic Spill NULL, HFILL}
598*e018180dSDominic Spill },
599*e018180dSDominic Spill {&hf_btatt_error_code,
600*e018180dSDominic Spill {"Error Code", "btatt.error_code",
601*e018180dSDominic Spill FT_UINT8, BASE_HEX, VALS(error_vals), 0x0,
602*e018180dSDominic Spill NULL, HFILL}
603*e018180dSDominic Spill },
604*e018180dSDominic Spill {&hf_btatt_uuid16,
605*e018180dSDominic Spill {"UUID", "btatt.uuid16",
606*e018180dSDominic Spill FT_UINT16, BASE_HEX |BASE_EXT_STRING, &uuid_vals_ext, 0x0,
607*e018180dSDominic Spill NULL, HFILL}
608*e018180dSDominic Spill },
609*e018180dSDominic Spill {&hf_btatt_uuid128,
610*e018180dSDominic Spill {"UUID", "btatt.uuid128",
611*e018180dSDominic Spill FT_BYTES, BASE_NONE, NULL, 0x0,
612*e018180dSDominic Spill NULL, HFILL}
613*e018180dSDominic Spill },
614*e018180dSDominic Spill {&hf_btatt_client_rx_mtu,
615*e018180dSDominic Spill {"Client Rx MTU", "btatt.client_rx_mtu",
616*e018180dSDominic Spill FT_UINT16, BASE_DEC, NULL, 0x0,
617*e018180dSDominic Spill NULL, HFILL}
618*e018180dSDominic Spill },
619*e018180dSDominic Spill {&hf_btatt_server_rx_mtu,
620*e018180dSDominic Spill {"Server Rx MTU", "btatt.server_rx_mtu",
621*e018180dSDominic Spill FT_UINT16, BASE_DEC, NULL, 0x0,
622*e018180dSDominic Spill NULL, HFILL}
623*e018180dSDominic Spill },
624*e018180dSDominic Spill {&hf_btatt_uuid_format,
625*e018180dSDominic Spill {"UUID Format", "btatt.uuid_format",
626*e018180dSDominic Spill FT_UINT8, BASE_HEX, VALS(uuid_format_vals), 0x0,
627*e018180dSDominic Spill NULL, HFILL}
628*e018180dSDominic Spill },
629*e018180dSDominic Spill {&hf_btatt_length,
630*e018180dSDominic Spill {"Length", "btatt.length",
631*e018180dSDominic Spill FT_UINT8, BASE_DEC, NULL, 0x0,
632*e018180dSDominic Spill "Length of Handle/Value Pair", HFILL}
633*e018180dSDominic Spill },
634*e018180dSDominic Spill {&hf_btatt_offset,
635*e018180dSDominic Spill {"Offset", "btatt.offset",
636*e018180dSDominic Spill FT_UINT16, BASE_DEC, NULL, 0x0,
637*e018180dSDominic Spill NULL, HFILL}
638*e018180dSDominic Spill },
639*e018180dSDominic Spill {&hf_btatt_flags,
640*e018180dSDominic Spill {"Flags", "btatt.flags",
641*e018180dSDominic Spill FT_UINT8, BASE_HEX, VALS(flags_vals), 0x0,
642*e018180dSDominic Spill NULL, HFILL}
643*e018180dSDominic Spill },
644*e018180dSDominic Spill {&hf_btatt_sign_counter,
645*e018180dSDominic Spill {"Sign Counter", "btatt.sign_counter",
646*e018180dSDominic Spill FT_UINT32, BASE_DEC, NULL, 0x0,
647*e018180dSDominic Spill NULL, HFILL}
648*e018180dSDominic Spill },
649*e018180dSDominic Spill {&hf_btatt_signature,
650*e018180dSDominic Spill {"Signature", "btatt.signature",
651*e018180dSDominic Spill FT_BYTES, BASE_NONE, NULL, 0x0,
652*e018180dSDominic Spill NULL, HFILL}
653*e018180dSDominic Spill }
654*e018180dSDominic Spill };
655*e018180dSDominic Spill
656*e018180dSDominic Spill /* Setup protocol subtree array */
657*e018180dSDominic Spill static gint *ett[] = {
658*e018180dSDominic Spill &ett_btatt,
659*e018180dSDominic Spill &ett_btatt_list
660*e018180dSDominic Spill };
661*e018180dSDominic Spill
662*e018180dSDominic Spill /* Register the protocol name and description */
663*e018180dSDominic Spill proto_btatt = proto_register_protocol("Bluetooth Attribute Protocol", "ATT", "btatt");
664*e018180dSDominic Spill
665*e018180dSDominic Spill register_dissector("btatt", dissect_btatt, proto_btatt);
666*e018180dSDominic Spill
667*e018180dSDominic Spill /* Required function calls to register the header fields and subtrees used */
668*e018180dSDominic Spill proto_register_field_array(proto_btatt, hf, array_length(hf));
669*e018180dSDominic Spill proto_register_subtree_array(ett, array_length(ett));
670*e018180dSDominic Spill
671*e018180dSDominic Spill module = prefs_register_protocol(proto_btatt, NULL);
672*e018180dSDominic Spill prefs_register_static_text_preference(module, "att.version",
673*e018180dSDominic Spill "Bluetooth Protocol ATT version from Core 4.0",
674*e018180dSDominic Spill "Version of protocol supported by this dissector.");
675*e018180dSDominic Spill }
676*e018180dSDominic Spill
677*e018180dSDominic Spill void
proto_reg_handoff_btatt(void)678*e018180dSDominic Spill proto_reg_handoff_btatt(void)
679*e018180dSDominic Spill {
680*e018180dSDominic Spill dissector_handle_t btatt_handle;
681*e018180dSDominic Spill
682*e018180dSDominic Spill btatt_handle = find_dissector("btatt");
683*e018180dSDominic Spill dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_ATT, btatt_handle);
684*e018180dSDominic Spill dissector_add_uint("btl2cap.cid", BTL2CAP_FIXED_CID_ATT, btatt_handle);
685*e018180dSDominic Spill }
686*e018180dSDominic Spill
687*e018180dSDominic Spill /*
688*e018180dSDominic Spill * Editor modelines - http://www.wireshark.org/tools/modelines.html
689*e018180dSDominic Spill *
690*e018180dSDominic Spill * Local variables:
691*e018180dSDominic Spill * c-basic-offset: 4
692*e018180dSDominic Spill * tab-width: 8
693*e018180dSDominic Spill * indent-tabs-mode: nil
694*e018180dSDominic Spill * End:
695*e018180dSDominic Spill *
696*e018180dSDominic Spill * vi: set shiftwidth=4 tabstop=8 expandtab:
697*e018180dSDominic Spill * :indentSize=4:tabSize=8:noTabs=true:
698*e018180dSDominic Spill */
699