1 /* packet-hci_usb.c
2  * Routines for Bluetooth HCI USB dissection
3  *
4  * Copyright 2012, Michal Labedzki for Tieto Corporation
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "config.h"
14 
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/reassemble.h>
18 #include <wiretap/wtap.h>
19 
20 #include "packet-bluetooth.h"
21 
22 static int proto_hci_usb = -1;
23 static int hf_bthci_usb_data = -1;
24 static int hf_bthci_usb_packet_fragment = -1;
25 static int hf_bthci_usb_packet_complete = -1;
26 static int hf_bthci_usb_packet_unknown_fragment = -1;
27 static int hf_bthci_usb_setup_request = -1;
28 static int hf_bthci_usb_setup_value = -1;
29 static int hf_bthci_usb_setup_adapter_id = -1;
30 static int hf_bthci_usb_setup_length = -1;
31 
32 static gint ett_hci_usb = -1;
33 static gint ett_hci_usb_msg_fragment = -1;
34 static gint ett_hci_usb_msg_fragments = -1;
35 
36 static int hf_msg_fragments = -1;
37 static int hf_msg_fragment = -1;
38 static int hf_msg_fragment_overlap = -1;
39 static int hf_msg_fragment_overlap_conflicts = -1;
40 static int hf_msg_fragment_multiple_tails = -1;
41 static int hf_msg_fragment_too_long_fragment = -1;
42 static int hf_msg_fragment_error = -1;
43 static int hf_msg_fragment_count = -1;
44 static int hf_msg_reassembled_in = -1;
45 static int hf_msg_reassembled_length = -1;
46 
47 static wmem_tree_t *fragment_info_table = NULL;
48 
49 static reassembly_table hci_usb_reassembly_table;
50 
51 static dissector_handle_t hci_usb_handle;
52 static dissector_handle_t bthci_cmd_handle;
53 static dissector_handle_t bthci_evt_handle;
54 static dissector_handle_t bthci_acl_handle;
55 static dissector_handle_t bthci_sco_handle;
56 
57 typedef struct _fragment_info_t {
58     gint remaining_length;
59     gint fragment_id;
60 } fragment_info_t;
61 
62 static const fragment_items hci_usb_msg_frag_items = {
63     /* Fragment subtrees */
64     &ett_hci_usb_msg_fragment,
65     &ett_hci_usb_msg_fragments,
66     /* Fragment fields */
67     &hf_msg_fragments,
68     &hf_msg_fragment,
69     &hf_msg_fragment_overlap,
70     &hf_msg_fragment_overlap_conflicts,
71     &hf_msg_fragment_multiple_tails,
72     &hf_msg_fragment_too_long_fragment,
73     &hf_msg_fragment_error,
74     &hf_msg_fragment_count,
75     /* Reassembled in field */
76     &hf_msg_reassembled_in,
77     /* Reassembled length field */
78     &hf_msg_reassembled_length,
79     /* Reassembled data field */
80     NULL,
81     /* Tag */
82     "Message fragments"
83 };
84 
85 static const value_string request_vals[] = {
86     { 0x00,  "Primary Controller Function" },
87     { 0x2B,  "AMP Controller Function" },
88     { 0xE0,  "Primary Controller Function (Historical)" },
89     { 0x00, NULL }
90 };
91 static value_string_ext(request_vals_ext) = VALUE_STRING_EXT_INIT(request_vals);
92 
93 
94 void proto_register_hci_usb(void);
95 void proto_reg_handoff_hci_usb(void);
96 
97 static gint
98 dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
99 {
100     proto_item        *ttree = NULL;
101     proto_tree        *titem = NULL;
102     proto_item        *pitem = NULL;
103     gint               offset = 0;
104     usb_conv_info_t   *usb_conv_info;
105     tvbuff_t          *next_tvb = NULL;
106     bluetooth_data_t  *bluetooth_data;
107     gint               p2p_dir_save;
108     guint32            session_id;
109     fragment_head     *reassembled;
110 
111     bluetooth_data = (bluetooth_data_t *) data;
112 
113     /* Reject the packet if data is NULL */
114     if (data == NULL)
115         return 0;
116 
117     DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_USB_CONV_INFO);
118     usb_conv_info = bluetooth_data->previous_protocol_data.usb_conv_info;
119 
120     titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA);
121     ttree = proto_item_add_subtree(titem, ett_hci_usb);
122 
123     col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB");
124 
125     p2p_dir_save = pinfo->p2p_dir;
126     pinfo->p2p_dir = (usb_conv_info->is_request) ? P2P_DIR_SENT : P2P_DIR_RECV;
127 
128     switch (pinfo->p2p_dir) {
129 
130     case P2P_DIR_SENT:
131         col_set_str(pinfo->cinfo, COL_INFO, "Sent");
132         break;
133 
134     case P2P_DIR_RECV:
135         col_set_str(pinfo->cinfo, COL_INFO, "Rcvd");
136         break;
137 
138     default:
139         col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection");
140         break;
141     }
142 
143     if (usb_conv_info->is_setup) {
144         proto_tree_add_item(ttree, hf_bthci_usb_setup_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
145         offset += 1;
146 
147         proto_tree_add_item(ttree, hf_bthci_usb_setup_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
148         offset += 2;
149 
150         proto_tree_add_item(ttree, hf_bthci_usb_setup_adapter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
151         offset += 2;
152 
153         proto_tree_add_item(ttree, hf_bthci_usb_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
154         offset += 2;
155     }
156 
157     session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint;
158 
159     bluetooth_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address;
160 /* TODO: adapter disconnect on some USB action, for now do not support adapter disconnection */
161     bluetooth_data->adapter_disconnect_in_frame = &max_disconnect_in_frame;
162 
163     next_tvb = tvb_new_subset_remaining(tvb, offset);
164     if (!pinfo->fd->visited && usb_conv_info->endpoint <= 0x02 &&
165             tvb_captured_length(tvb) == tvb_reported_length(tvb)) {
166         fragment_info_t  *fragment_info;
167 
168         fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id);
169         if (fragment_info == NULL) {
170             fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t);
171             fragment_info->fragment_id = 0;
172             fragment_info->remaining_length = 0;
173 
174             wmem_tree_insert32(fragment_info_table, session_id, fragment_info);
175         }
176 
177         if (fragment_info->fragment_id == 0) {
178             switch(usb_conv_info->endpoint)
179             {
180             case 0:
181                 fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3;
182                 break;
183             case 1:
184                 fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2;
185                 break;
186             case 2:
187                 fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4;
188                 break;
189             }
190         }
191 
192         fragment_info->remaining_length -= tvb_reported_length_remaining(tvb, offset);
193 
194         fragment_add_seq_check(&hci_usb_reassembly_table,
195                                tvb, offset, pinfo, session_id, NULL,
196                                fragment_info->fragment_id, tvb_reported_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE);
197         if (fragment_info->remaining_length > 0)
198             fragment_info->fragment_id += 1;
199         else
200             fragment_info->fragment_id = 0;
201     }
202 
203     reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id);
204     if (reassembled && pinfo->num < reassembled->reassembled_in) {
205         pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA);
206         proto_item_set_generated(pitem);
207 
208         col_append_str(pinfo->cinfo, COL_INFO, " Fragment");
209     } else if (reassembled && pinfo->num == reassembled->reassembled_in) {
210         pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA);
211         proto_item_set_generated(pitem);
212 
213         if (reassembled->len > (guint) tvb_reported_length_remaining(tvb, offset)) {
214             next_tvb = process_reassembled_data(tvb, 0, pinfo,
215                     "Reassembled HCI_USB",
216                     reassembled, &hci_usb_msg_frag_items,
217                     NULL, ttree);
218         }
219 
220         switch(usb_conv_info->endpoint)
221         {
222         case 0:
223             call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data);
224             break;
225         case 1:
226             call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data);
227             break;
228         case 2:
229             call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data);
230             break;
231         }
232     } else {
233         pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA);
234         proto_item_set_generated(pitem);
235     }
236 
237     if (usb_conv_info->endpoint == 0x03) {
238         call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data);
239     } else if (usb_conv_info->endpoint > 0x03) {
240         proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA);
241     }
242 
243     offset += tvb_reported_length_remaining(tvb, offset);
244 
245     pinfo->p2p_dir = p2p_dir_save;
246 
247     return offset;
248 }
249 
250 void
251 proto_register_hci_usb(void)
252 {
253     module_t *module;
254 
255     static hf_register_info hf[] = {
256         {  &hf_msg_fragments,
257             { "Message fragments",               "hci_usb.msg.fragments",
258             FT_NONE, BASE_NONE, NULL, 0x00,
259             NULL, HFILL }
260         },
261         {  &hf_msg_fragment,
262             { "Message fragment",                "hci_usb.msg.fragment",
263             FT_FRAMENUM, BASE_NONE, NULL, 0x00,
264             NULL, HFILL }
265         },
266         {  &hf_msg_fragment_overlap,
267             { "Message fragment overlap",        "hci_usb.msg.fragment.overlap",
268             FT_BOOLEAN, BASE_NONE, NULL, 0x00,
269             NULL, HFILL }
270         },
271         {  &hf_msg_fragment_overlap_conflicts,
272             { "Message fragment overlapping with conflicting data", "hci_usb.msg.fragment.overlap.conflicts",
273             FT_BOOLEAN, BASE_NONE, NULL, 0x00,
274             NULL, HFILL }
275         },
276         {  &hf_msg_fragment_multiple_tails,
277             { "Message has multiple tail fragments", "hci_usb.msg.fragment.multiple_tails",
278             FT_BOOLEAN, BASE_NONE, NULL, 0x00,
279             NULL, HFILL }
280         },
281         {  &hf_msg_fragment_too_long_fragment,
282             { "Message fragment too long",       "hci_usb.msg.fragment.too_long_fragment",
283             FT_BOOLEAN, BASE_NONE, NULL, 0x00,
284             NULL, HFILL }
285         },
286         {  &hf_msg_fragment_error,
287             { "Message defragmentation error",   "hci_usb.msg.fragment.error",
288             FT_FRAMENUM, BASE_NONE, NULL, 0x00,
289             NULL, HFILL }
290         },
291         {  &hf_msg_fragment_count,
292             { "Message fragment count",          "hci_usb.msg.fragment.count",
293             FT_UINT32, BASE_DEC, NULL, 0x00,
294             NULL, HFILL }
295         },
296         {  &hf_msg_reassembled_in,
297             { "Reassembled in",                  "hci_usb.msg.reassembled.in",
298             FT_FRAMENUM, BASE_NONE, NULL, 0x00,
299             NULL, HFILL }
300         },
301         {  &hf_msg_reassembled_length,
302             { "Reassembled MP2T length",         "hci_usb.msg.reassembled.length",
303             FT_UINT32, BASE_DEC, NULL, 0x00,
304             NULL, HFILL }
305         },
306         { &hf_bthci_usb_packet_fragment,
307             { "Packet Fragment",                 "hci_usb.packet.fragment",
308             FT_NONE, BASE_NONE, NULL, 0x00,
309             NULL, HFILL }
310         },
311         { &hf_bthci_usb_packet_complete,
312             { "Packet Complete",                 "hci_usb.packet.complete",
313             FT_NONE, BASE_NONE, NULL, 0x00,
314             NULL, HFILL }
315         },
316         { &hf_bthci_usb_packet_unknown_fragment,
317             { "Unknown Packet Fragment",         "hci_usb.packet.unknown_fragment",
318             FT_NONE, BASE_NONE, NULL, 0x00,
319             NULL, HFILL }
320         },
321         { &hf_bthci_usb_setup_request,
322           { "bRequest",                          "hci_usb.setup.bRequest",
323             FT_UINT8, BASE_DEC | BASE_EXT_STRING, &request_vals_ext, 0x0,
324             NULL, HFILL }},
325 
326         { &hf_bthci_usb_setup_value,
327           { "wValue",                            "hci_usb.setup.wValue",
328             FT_UINT16, BASE_HEX, NULL, 0x0,
329             NULL, HFILL }},
330 
331         { &hf_bthci_usb_setup_adapter_id,
332           { "Adapter ID",                        "hci_usb.setup.adapter_id",
333             FT_UINT16, BASE_DEC, NULL, 0x0,
334             NULL, HFILL }},
335 
336         { &hf_bthci_usb_setup_length,
337           { "wLength",                           "hci_usb.setup.wLength",
338             FT_UINT16, BASE_DEC, NULL, 0x0,
339             NULL, HFILL }},
340         { &hf_bthci_usb_data,
341             { "Unknown Data",                    "hci_usb.data",
342             FT_NONE, BASE_NONE, NULL, 0x00,
343             NULL, HFILL }
344         }
345     };
346 
347     static gint *ett[] = {
348         &ett_hci_usb,
349         &ett_hci_usb_msg_fragment,
350         &ett_hci_usb_msg_fragments,
351     };
352 
353     reassembly_table_register(&hci_usb_reassembly_table,
354                           &addresses_reassembly_table_functions);
355     fragment_info_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
356 
357     proto_hci_usb = proto_register_protocol("Bluetooth HCI USB Transport", "HCI_USB", "hci_usb");
358     proto_register_field_array(proto_hci_usb, hf, array_length(hf));
359     proto_register_subtree_array(ett, array_length(ett));
360     hci_usb_handle = register_dissector("hci_usb", dissect_hci_usb, proto_hci_usb);
361 
362     module = prefs_register_protocol_subtree("Bluetooth", proto_hci_usb, NULL);
363     prefs_register_static_text_preference(module, "bthci_usb.version",
364             "Bluetooth HCI USB Transport from Core 4.0",
365             "Version of protocol supported by this dissector.");
366 }
367 
368 void
369 proto_reg_handoff_hci_usb(void)
370 {
371     bthci_cmd_handle = find_dissector_add_dependency("bthci_cmd", proto_hci_usb);
372     bthci_evt_handle = find_dissector_add_dependency("bthci_evt", proto_hci_usb);
373     bthci_acl_handle = find_dissector_add_dependency("bthci_acl", proto_hci_usb);
374     bthci_sco_handle = find_dissector_add_dependency("bthci_sco", proto_hci_usb);
375 }
376 
377 /*
378  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
379  *
380  * Local variables:
381  * c-basic-offset: 4
382  * tab-width: 8
383  * indent-tabs-mode: nil
384  * End:
385  *
386  * vi: set shiftwidth=4 tabstop=8 expandtab:
387  * :indentSize=4:tabSize=8:noTabs=true:
388  */
389