Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-hci_usb.c
blobc410187e6a9d0f5b92f63072149c972e41fce927
1 /* packet-hci_usb.c
2 * Routines for Bluetooth HCI USB dissection
4 * Copyright 2012, Michal Labedzki for Tieto Corporation
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/reassemble.h>
19 #include "packet-bluetooth.h"
20 #include "packet-usb.h"
22 static int proto_hci_usb;
23 static int hf_bthci_usb_data;
24 static int hf_bthci_usb_packet_fragment;
25 static int hf_bthci_usb_packet_complete;
26 static int hf_bthci_usb_packet_unknown_fragment;
27 static int hf_bthci_usb_setup_request;
28 static int hf_bthci_usb_setup_value;
29 static int hf_bthci_usb_setup_adapter_id;
30 static int hf_bthci_usb_setup_length;
32 static int ett_hci_usb;
33 static int ett_hci_usb_msg_fragment;
34 static int ett_hci_usb_msg_fragments;
36 static int hf_msg_fragments;
37 static int hf_msg_fragment;
38 static int hf_msg_fragment_overlap;
39 static int hf_msg_fragment_overlap_conflicts;
40 static int hf_msg_fragment_multiple_tails;
41 static int hf_msg_fragment_too_long_fragment;
42 static int hf_msg_fragment_error;
43 static int hf_msg_fragment_count;
44 static int hf_msg_reassembled_in;
45 static int hf_msg_reassembled_length;
47 static wmem_tree_t *fragment_info_table;
49 static reassembly_table hci_usb_reassembly_table;
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;
57 typedef struct _fragment_info_t {
58 int remaining_length;
59 int fragment_id;
60 } fragment_info_t;
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"
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 }
91 static value_string_ext(request_vals_ext) = VALUE_STRING_EXT_INIT(request_vals);
94 void proto_register_hci_usb(void);
95 void proto_reg_handoff_hci_usb(void);
97 static int
98 dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
100 proto_item *ttree = NULL;
101 proto_tree *titem = NULL;
102 proto_item *pitem = NULL;
103 int offset = 0;
104 urb_info_t *urb;
105 tvbuff_t *next_tvb = NULL;
106 bluetooth_data_t *bluetooth_data;
107 int p2p_dir_save;
108 uint32_t session_id;
109 fragment_head *reassembled;
111 bluetooth_data = (bluetooth_data_t *) data;
113 /* Reject the packet if data is NULL */
114 if (data == NULL)
115 return 0;
117 DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_URB_INFO);
118 urb = bluetooth_data->previous_protocol_data.urb;
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);
123 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB");
125 p2p_dir_save = pinfo->p2p_dir;
126 pinfo->p2p_dir = (urb->is_request) ? P2P_DIR_SENT : P2P_DIR_RECV;
128 switch (pinfo->p2p_dir) {
130 case P2P_DIR_SENT:
131 col_set_str(pinfo->cinfo, COL_INFO, "Sent");
132 break;
134 case P2P_DIR_RECV:
135 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd");
136 break;
138 default:
139 col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection");
140 break;
143 if (urb->is_setup) {
144 proto_tree_add_item(ttree, hf_bthci_usb_setup_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
145 offset += 1;
147 proto_tree_add_item(ttree, hf_bthci_usb_setup_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
148 offset += 2;
150 proto_tree_add_item(ttree, hf_bthci_usb_setup_adapter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
151 offset += 2;
153 proto_tree_add_item(ttree, hf_bthci_usb_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
154 offset += 2;
157 session_id = urb->bus_id << 16 | urb->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | urb->endpoint;
159 bluetooth_data->adapter_id = urb->bus_id << 8 | urb->device_address;
160 /* TODO: adapter disconnect on some USB action, for now do not support adapter disconnection */
161 bluetooth_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
163 next_tvb = tvb_new_subset_remaining(tvb, offset);
164 if (!pinfo->fd->visited && urb->transfer_type != URB_ISOCHRONOUS &&
165 tvb_captured_length(tvb) == tvb_reported_length(tvb)) {
166 fragment_info_t *fragment_info;
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;
174 wmem_tree_insert32(fragment_info_table, session_id, fragment_info);
177 if (fragment_info->fragment_id == 0) {
178 switch(urb->transfer_type)
180 case URB_CONTROL:
181 fragment_info->remaining_length = tvb_get_uint8(tvb, offset + 2) + 3;
182 break;
183 case URB_INTERRUPT:
184 fragment_info->remaining_length = tvb_get_uint8(tvb, offset + 1) + 2;
185 break;
186 case URB_BULK:
187 fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4;
188 break;
192 fragment_info->remaining_length -= tvb_reported_length_remaining(tvb, offset);
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;
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);
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);
213 if (reassembled->len > (unsigned) 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);
220 switch(urb->transfer_type)
222 case URB_CONTROL:
223 call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data);
224 break;
225 case URB_INTERRUPT:
226 call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data);
227 break;
228 case URB_BULK:
229 call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data);
230 break;
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);
237 if (urb->transfer_type == URB_ISOCHRONOUS) {
238 call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data);
239 } else if (urb->transfer_type == URB_UNKNOWN) {
240 proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA);
243 offset += tvb_reported_length_remaining(tvb, offset);
245 pinfo->p2p_dir = p2p_dir_save;
247 return offset;
250 void
251 proto_register_hci_usb(void)
253 module_t *module;
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 }
261 { &hf_msg_fragment,
262 { "Message fragment", "hci_usb.msg.fragment",
263 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
264 NULL, HFILL }
266 { &hf_msg_fragment_overlap,
267 { "Message fragment overlap", "hci_usb.msg.fragment.overlap",
268 FT_BOOLEAN, BASE_NONE, NULL, 0x00,
269 NULL, HFILL }
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 }
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 }
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 }
286 { &hf_msg_fragment_error,
287 { "Message defragmentation error", "hci_usb.msg.fragment.error",
288 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
289 NULL, HFILL }
291 { &hf_msg_fragment_count,
292 { "Message fragment count", "hci_usb.msg.fragment.count",
293 FT_UINT32, BASE_DEC, NULL, 0x00,
294 NULL, HFILL }
296 { &hf_msg_reassembled_in,
297 { "Reassembled in", "hci_usb.msg.reassembled.in",
298 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
299 NULL, HFILL }
301 { &hf_msg_reassembled_length,
302 { "Reassembled MP2T length", "hci_usb.msg.reassembled.length",
303 FT_UINT32, BASE_DEC, NULL, 0x00,
304 NULL, HFILL }
306 { &hf_bthci_usb_packet_fragment,
307 { "Packet Fragment", "hci_usb.packet.fragment",
308 FT_NONE, BASE_NONE, NULL, 0x00,
309 NULL, HFILL }
311 { &hf_bthci_usb_packet_complete,
312 { "Packet Complete", "hci_usb.packet.complete",
313 FT_NONE, BASE_NONE, NULL, 0x00,
314 NULL, HFILL }
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 }
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 }},
326 { &hf_bthci_usb_setup_value,
327 { "wValue", "hci_usb.setup.wValue",
328 FT_UINT16, BASE_HEX, NULL, 0x0,
329 NULL, HFILL }},
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 }},
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 }
347 static int *ett[] = {
348 &ett_hci_usb,
349 &ett_hci_usb_msg_fragment,
350 &ett_hci_usb_msg_fragments,
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());
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);
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.");
368 void
369 proto_reg_handoff_hci_usb(void)
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);
378 * Editor modelines - https://www.wireshark.org/tools/modelines.html
380 * Local variables:
381 * c-basic-offset: 4
382 * tab-width: 8
383 * indent-tabs-mode: nil
384 * End:
386 * vi: set shiftwidth=4 tabstop=8 expandtab:
387 * :indentSize=4:tabSize=8:noTabs=true: