2 * Routines for the Bluetooth L2CAP dissection
3 * Copyright 2002, Christoph Scholz <scholz@cs.uni-bonn.de>
4 * From: http://affix.sourceforge.net/archive/ethereal_affix-3.patch
6 * Refactored for wireshark checkin
9 * Added handling and reassembly of LE-Frames
10 * Anders Broman at ericsson dot com 2016
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <epan/packet.h>
22 #include <epan/exceptions.h>
23 #include <epan/expert.h>
24 #include <epan/decode_as.h>
25 #include <epan/proto_data.h>
26 #include <epan/reassemble.h>
27 #include <epan/unit_strings.h>
29 #include <wiretap/wtap.h>
31 #include "packet-bluetooth.h"
32 #include "packet-bthci_acl.h"
33 #include "packet-btsdp.h"
34 #include "packet-btl2cap.h"
36 /* Initialize the protocol and registered fields */
39 static int hf_btl2cap_length
;
40 static int hf_btl2cap_cid
;
41 static int hf_btl2cap_payload
;
42 static int hf_btl2cap_command
;
43 static int hf_btl2cap_cmd_code
;
44 static int hf_btl2cap_cmd_ident
;
45 static int hf_btl2cap_cmd_length
;
46 static int hf_btl2cap_cmd_data
;
47 static int hf_btl2cap_psm
;
48 static int hf_btl2cap_psm_dynamic
;
49 static int hf_btl2cap_scid
;
50 static int hf_btl2cap_dcid
;
51 static int hf_btl2cap_icid
;
52 static int hf_btl2cap_controller
;
53 static int hf_btl2cap_dcontroller
;
54 static int hf_btl2cap_result
;
55 static int hf_btl2cap_move_result
;
56 static int hf_btl2cap_move_confirmation_result
;
57 static int hf_btl2cap_status
;
58 static int hf_btl2cap_rej_reason
;
59 static int hf_btl2cap_sig_mtu
;
60 static int hf_btl2cap_info_mtu
;
61 static int hf_btl2cap_info_flowcontrol
;
62 static int hf_btl2cap_info_retransmission
;
63 static int hf_btl2cap_info_bidirqos
;
64 static int hf_btl2cap_info_enh_retransmission
;
65 static int hf_btl2cap_info_streaming
;
66 static int hf_btl2cap_info_fcs
;
67 static int hf_btl2cap_info_flow_spec
;
68 static int hf_btl2cap_info_fixedchan
;
69 static int hf_btl2cap_info_fixedchans
;
70 static int hf_btl2cap_info_fixedchans_null
;
71 static int hf_btl2cap_info_fixedchans_signal
;
72 static int hf_btl2cap_info_fixedchans_connless
;
73 static int hf_btl2cap_info_fixedchans_amp_man
;
74 static int hf_btl2cap_info_fixedchans_rfu
;
75 static int hf_btl2cap_info_fixedchans_smp
;
76 static int hf_btl2cap_info_fixedchans_amp_test
;
77 static int hf_btl2cap_info_window
;
78 static int hf_btl2cap_info_unicast
;
79 static int hf_btl2cap_info_type
;
80 static int hf_btl2cap_info_result
;
81 static int hf_btl2cap_configuration_result
;
82 static int hf_btl2cap_info_extfeatures
;
83 static int hf_btl2cap_option
;
84 static int hf_btl2cap_option_type
;
85 static int hf_btl2cap_option_length
;
86 static int hf_btl2cap_option_mtu
;
87 static int hf_btl2cap_option_flushTO
;
88 static int hf_btl2cap_option_flush_to_us
;
89 static int hf_btl2cap_option_flags
;
90 static int hf_btl2cap_option_service_type
;
91 static int hf_btl2cap_option_tokenrate
;
92 static int hf_btl2cap_option_tokenbucketsize
;
93 static int hf_btl2cap_option_peakbandwidth
;
94 static int hf_btl2cap_option_latency
;
95 static int hf_btl2cap_option_delayvariation
;
96 static int hf_btl2cap_option_retransmissionmode
;
97 static int hf_btl2cap_option_txwindow
;
98 static int hf_btl2cap_option_maxtransmit
;
99 static int hf_btl2cap_option_retransmittimeout
;
100 static int hf_btl2cap_option_monitortimeout
;
101 static int hf_btl2cap_option_mps
;
102 static int hf_btl2cap_option_fcs
;
103 static int hf_btl2cap_option_window
;
104 static int hf_btl2cap_option_identifier
;
105 static int hf_btl2cap_option_sdu_size
;
106 static int hf_btl2cap_option_sdu_arrival_time
;
107 static int hf_btl2cap_option_access_latency
;
108 static int hf_btl2cap_control
;
109 static int hf_btl2cap_control_sar
;
110 static int hf_btl2cap_control_reqseq
;
111 static int hf_btl2cap_control_txseq
;
112 static int hf_btl2cap_control_retransmissiondisable
;
113 static int hf_btl2cap_control_supervisory
;
114 static int hf_btl2cap_control_type
;
115 static int hf_btl2cap_fcs
;
116 static int hf_btl2cap_sdulength
;
117 static int hf_btl2cap_continuation_to
;
118 static int hf_btl2cap_reassembled_in
;
119 static int hf_btl2cap_min_interval
;
120 static int hf_btl2cap_max_interval
;
121 static int hf_btl2cap_peripheral_latency
;
122 static int hf_btl2cap_timeout_multiplier
;
123 static int hf_btl2cap_conn_param_result
;
124 static int hf_btl2cap_credits
;
125 static int hf_btl2cap_initial_credits
;
126 static int hf_btl2cap_le_result
;
127 static int hf_btl2cap_le_psm
;
128 static int hf_btl2cap_flags_reserved
;
129 static int hf_btl2cap_flags_continuation
;
130 static int hf_btl2cap_data
;
131 static int hf_btl2cap_service
;
132 static int hf_btl2cap_connect_in_frame
;
133 static int hf_btl2cap_disconnect_in_frame
;
135 static int hf_btl2cap_le_sdu_fragments
;
136 static int hf_btl2cap_le_sdu_fragment
;
137 static int hf_btl2cap_le_sdu_fragment_overlap
;
138 static int hf_btl2cap_le_sdu_fragment_overlap_conflicts
;
139 static int hf_btl2cap_le_sdu_fragment_multiple_tails
;
140 static int hf_btl2cap_le_sdu_fragment_too_long_fragment
;
141 static int hf_btl2cap_le_sdu_fragment_error
;
142 static int hf_btl2cap_le_sdu_fragment_count
;
143 static int hf_btl2cap_le_sdu_reassembled_in
;
144 static int hf_btl2cap_le_sdu_reassembled_length
;
146 static int hf_btl2cap_le_sdu_length
;
148 /* Initialize the subtree pointers */
149 static int ett_btl2cap
;
150 static int ett_btl2cap_cmd
;
151 static int ett_btl2cap_option
;
152 static int ett_btl2cap_extfeatures
;
153 static int ett_btl2cap_fixedchans
;
154 static int ett_btl2cap_control
;
155 static int ett_btl2cap_le_sdu_fragment
;
156 static int ett_btl2cap_le_sdu_fragments
;
158 static expert_field ei_btl2cap_parameter_mismatch
;
159 static expert_field ei_btl2cap_sdulength_bad
;
160 static expert_field ei_btl2cap_length_bad
;
161 static expert_field ei_btl2cap_unknown_command_code
;
163 /* Initialize dissector table */
164 static dissector_table_t l2cap_psm_dissector_table
;
165 static dissector_table_t l2cap_cid_dissector_table
;
167 /* This table maps command identity values to psm values. */
168 static wmem_tree_t
*cmd_ident_to_psm_table
;
170 /* This table maps cid values to psm values.
171 * The same table is used both for SCID and DCID.
172 * For Remote CIDs (Receive Request SCID or Sent Response DCID)
173 * we 'or' the CID with 0x80000000 in this table
175 static wmem_tree_t
*cid_to_psm_table
;
177 /* 5.4 RETRANSMISSION AND FLOW CONTROL OPTION
180 * 0x00 L2CAP Basic Mode
181 * 0x01 Retransmission mode
182 * 0x02 Flow control mode
183 * 0x03 Enhanced Retransmission mode
184 * 0x04 Streaming mode
185 * Other values Reserved for future use
188 #define L2CAP_BASIC_MODE 0
189 /* XXX Cheat and define a vaue for
190 * Connection-Oriented Channels in LE Credit Based Flow Control Mode
192 #define L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE 0xff
194 typedef struct _config_data_t
{
197 wmem_tree_t
*start_fragments
; /* indexed by pinfo->num */
198 /* Used for LE frame reassembly */
199 unsigned segmentation_started
: 1; /* 0 = No, 1 = Yes */
200 unsigned segment_len_rem
; /* The remaining segment length, used to find last segment */
203 typedef struct _sdu_reassembly_t
205 uint8_t *reassembled
;
207 uint32_t first_frame
;
210 int cur_off
; /* counter used by reassembly */
213 typedef struct _psm_data_t
{
214 uint32_t interface_id
;
221 uint32_t connect_in_frame
;
222 uint32_t disconnect_in_frame
;
227 typedef struct _btl2cap_frame_data_t
230 unsigned first_fragment
: 1; /* 0 = No, 1 = First or only fragment*/
231 unsigned more_fragments
: 1; /* 0 = Last fragment, 1 = more fragments*/
232 } btl2cap_frame_data_t
;
234 static const value_string command_code_vals
[] = {
235 { 0x01, "Command Reject" },
236 { 0x02, "Connection Request" },
237 { 0x03, "Connection Response" },
238 { 0x04, "Configure Request" },
239 { 0x05, "Configure Response" },
240 { 0x06, "Disconnection Request" },
241 { 0x07, "Disconnection Response" },
242 { 0x08, "Echo Request" },
243 { 0x09, "Echo Response" },
244 { 0x0A, "Information Request" },
245 { 0x0B, "Information Response" },
246 { 0x0C, "Create Channel Request" },
247 { 0x0D, "Create Channel Response" },
248 { 0x0E, "Move Channel Request" },
249 { 0x0F, "Move Channel Response" },
250 { 0x10, "Move Channel Confirmation" },
251 { 0x11, "Move Channel Confirmation Response" },
252 { 0x12, "Connection Parameter Update Request" },
253 { 0x13, "Connection Parameter Update Response" },
254 { 0x14, "LE Credit Based Connection Request" },
255 { 0x15, "LE Credit Based Connection Response" },
256 { 0x16, "LE Flow Control Credit" },
257 { 0x17, "L2CAP Credit Based Connection Request" },
258 { 0x18, "L2CAP Credit Based Connection Response" },
259 { 0x19, "L2CAP Credit Based Reconfigure Request" },
260 { 0x1A, "L2CAP Credit Based Reconfigure Response" },
265 static const value_string psm_vals
[] = {
267 { 0x0003, "RFCOMM" },
268 { 0x0005, "TCS-BIN" },
269 { 0x0007, "TCS-BIN-CORDLESS" },
271 { 0x0011, "HID-Control" },
272 { 0x0013, "HID-Interrupt" },
274 { 0x0017, "AVCTP-Control" },
276 { 0x001B, "AVCTP-Browsing" },
277 { 0x001D, "UDI_C-Plane" },
285 value_string_ext ext_psm_vals
= VALUE_STRING_EXT_INIT(psm_vals
);
287 static const value_string result_vals
[] = {
288 { 0x0000, "Successful" },
289 { 0x0001, "Pending" },
290 { 0x0002, "Refused - PSM not supported" },
291 { 0x0003, "Refused - security block" },
292 { 0x0004, "Refused - no resources available" },
293 { 0x0005, "Refused - Controller ID not supported" },
297 static const value_string le_result_vals
[] = {
298 { 0x0000, "Connection Successful" },
299 { 0x0002, "Connection Refused - LE_PSM Not Supported" },
300 { 0x0004, "Connection Refused - No Resources Available" },
301 { 0x0005, "Connection Refused - Insufficient Authentication" },
302 { 0x0006, "Connection Refused - Insufficient Authorization" },
303 { 0x0007, "Connection Refused - Insufficient Encryption Key Size" },
304 { 0x0008, "Connection Refused - Insufficient Encryption" },
308 static const value_string move_result_vals
[] = {
309 { 0x0000, "Success" },
310 { 0x0001, "Pending" },
311 { 0x0002, "Refused - Controller ID not supported" },
312 { 0x0003, "Refused - New Controller ID is same as old" },
313 { 0x0004, "Refused - Configuration not supported" },
314 { 0x0005, "Refused - Move Channel collision" },
315 { 0x0006, "Refused - Channel not allowed to be moved" },
319 static const value_string move_result_confirmation_vals
[] = {
320 { 0x0000, "Success - both sides succeed" },
321 { 0x0001, "Failure - one or both sides refuse" },
325 static const value_string configuration_result_vals
[] = {
326 { 0x0000, "Success"},
327 { 0x0001, "Failure - unacceptable parameters" },
328 { 0x0002, "Failure - reject (no reason provided)" },
329 { 0x0003, "Failure - unknown options" },
330 { 0x0004, "Pending" },
331 { 0x0005, "Failure - flow spec rejected" },
335 static const value_string conn_param_result_vals
[] = {
336 { 0x0000, "Accepted" },
337 { 0x0001, "Rejected" },
341 static const value_string status_vals
[] = {
342 { 0x0000, "No further information available" },
343 { 0x0001, "Authentication pending" },
344 { 0x0002, "Authorization pending" },
348 static const value_string reason_vals
[] = {
349 { 0x0000, "Command not understood" },
350 { 0x0001, "Signaling MTU exceeded" },
351 { 0x0002, "Invalid CID in request" },
355 static const value_string info_type_vals
[] = {
356 { 0x0001, "Connectionless MTU" },
357 { 0x0002, "Extended Features Mask" },
358 { 0x0003, "Fixed Channels Supported" },
362 static const value_string info_result_vals
[] = {
363 { 0x0000, "Success" },
364 { 0x0001, "Not Supported" },
368 static const value_string option_servicetype_vals
[] = {
369 { 0x00, "No traffic" },
370 { 0x01, "Best effort (Default)" },
371 { 0x02, "Guaranteed" },
375 static const value_string option_type_vals
[] = {
376 { 0x01, "Maximum Transmission Unit" },
377 { 0x02, "Flush Timeout" },
378 { 0x03, "Quality of Service" },
379 { 0x04, "Retransmission and Flow Control" },
381 { 0x06, "Extended Flow Specification" },
382 { 0x07, "Extended Window Size" },
386 static const value_string option_retransmissionmode_vals
[] = {
387 { 0x00, "Basic Mode" },
388 { 0x01, "Retransmission Mode" },
389 { 0x02, "Flow Control Mode" },
390 { 0x03, "Enhanced Retransmission Mode" },
391 { 0x04, "Streaming Mode" },
395 static const value_string control_sar_vals
[] = {
396 { 0x00, "Unsegmented" },
399 { 0x03, "Continuation" },
403 static const value_string control_supervisory_vals
[] = {
411 static const value_string control_type_vals
[] = {
417 static const value_string option_fcs_vals
[] = {
419 { 0x01, "16-bit FCS" },
423 static const value_string ctrl_id_code_vals
[] = {
424 { 0x00, "Bluetooth BR/EDR" },
425 { 0x01, "Wifi 802.11" },
429 static const range_string cid_rvals
[] = {
430 { 0x0000, 0x0000, "Null identifier" },
431 { 0x0001, 0x0001, "L2CAP Signaling Channel" },
432 { 0x0002, 0x0002, "Connectionless Channel" },
433 { 0x0003, 0x0003, "AMP Manager Protocol" },
434 { 0x0004, 0x0004, "Attribute Protocol" },
435 { 0x0005, 0x0005, "Low Energy L2CAP Signaling Channel" },
436 { 0x0006, 0x0006, "Security Manager Protocol" },
437 { 0x0007, 0x003E, "Reserved" },
438 { 0x003F, 0x003F, "AMP Test Manager" },
439 { 0x0040, 0xFFFF, "Dynamically Allocated Channel" },
443 static const range_string le_psm_rvals
[] = {
444 { 0x0001, 0x007F, "Fixed, SIG Assigned" },
445 { 0x0080, 0x00FF, "Dynamically Allocated" },
446 { 0x0100, 0xFFFF, "Reserved" },
450 static const unit_name_string units_ll_connection_event
= { " LL Connection Event", " LL Connection Events" };
452 #define PROTO_DATA_BTL2CAP_CID 0
453 #define PROTO_DATA_BTL2CAP_PSM 1
455 void proto_register_btl2cap(void);
456 void proto_reg_handoff_btl2cap(void);
459 static reassembly_table btl2cap_le_sdu_reassembly_table
;
461 static const fragment_items btl2cap_le_sdu_frag_items
= {
462 /* Fragment subtrees */
463 &ett_btl2cap_le_sdu_fragment
,
464 &ett_btl2cap_le_sdu_fragments
,
465 /* Fragment fields */
466 &hf_btl2cap_le_sdu_fragments
,
467 &hf_btl2cap_le_sdu_fragment
,
468 &hf_btl2cap_le_sdu_fragment_overlap
,
469 &hf_btl2cap_le_sdu_fragment_overlap_conflicts
,
470 &hf_btl2cap_le_sdu_fragment_multiple_tails
,
471 &hf_btl2cap_le_sdu_fragment_too_long_fragment
,
472 &hf_btl2cap_le_sdu_fragment_error
,
473 &hf_btl2cap_le_sdu_fragment_count
,
474 /* Reassembled in field */
475 &hf_btl2cap_le_sdu_reassembled_in
,
476 /* Reassembled length field */
477 &hf_btl2cap_le_sdu_reassembled_length
,
478 /* Reassembled data field */
481 "BTL2CAP LE SDU fragments"
485 static void btl2cap_cid_prompt(packet_info
*pinfo
, char* result
)
487 uint16_t *value_data
;
489 value_data
= (uint16_t *) p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_CID
);
491 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "L2CAP CID 0x%04x as", (unsigned) *value_data
);
493 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Unknown L2CAP CID");
496 static void *btl2cap_cid_value(packet_info
*pinfo
)
498 uint16_t *value_data
;
500 value_data
= (uint16_t *) p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_CID
);
503 return GUINT_TO_POINTER((unsigned long)*value_data
);
508 static void btl2cap_psm_prompt(packet_info
*pinfo
, char* result
)
510 uint16_t *value_data
;
512 value_data
= (uint16_t *) p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
);
514 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "L2CAP PSM 0x%04x as", (unsigned) *value_data
);
516 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Unknown L2CAP PSM");
519 static void *btl2cap_psm_value(packet_info
*pinfo
)
521 uint16_t *value_data
;
523 value_data
= (uint16_t *) p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
);
526 return GUINT_TO_POINTER((unsigned long)*value_data
);
532 get_service_uuid(packet_info
*pinfo
, btl2cap_data_t
*l2cap_data
, uint16_t psm
, bool is_local_psm
)
534 wmem_tree_key_t key
[10];
535 uint32_t k_interface_id
;
536 uint32_t k_adapter_id
;
538 uint32_t k_direction
;
539 uint32_t k_bd_addr_oui
;
540 uint32_t k_bd_addr_id
;
541 uint32_t k_service_type
;
542 uint32_t k_service_channel
;
543 uint32_t k_frame_number
;
544 uint32_t interface_id
;
546 uint32_t remote_bd_addr_oui
;
547 uint32_t remote_bd_addr_id
;
548 service_info_t
*service_info
;
550 interface_id
= l2cap_data
->interface_id
;
551 adapter_id
= l2cap_data
->adapter_id
;
553 k_interface_id
= interface_id
;
554 k_adapter_id
= adapter_id
;
555 k_sdp_psm
= SDP_PSM_DEFAULT
;
556 k_direction
= (is_local_psm
) ? P2P_DIR_SENT
: P2P_DIR_RECV
;
557 if (k_direction
== P2P_DIR_RECV
) {
558 k_bd_addr_oui
= l2cap_data
->remote_bd_addr_oui
;
559 k_bd_addr_id
= l2cap_data
->remote_bd_addr_id
;
565 remote_bd_addr_oui
= k_bd_addr_oui
;
566 remote_bd_addr_id
= k_bd_addr_id
;
568 k_service_type
= BTSDP_L2CAP_PROTOCOL_UUID
;
569 k_service_channel
= psm
;
570 k_frame_number
= pinfo
->num
;
573 key
[0].key
= &k_interface_id
;
575 key
[1].key
= &k_adapter_id
;
577 key
[2].key
= &k_sdp_psm
;
579 key
[3].key
= &k_direction
;
581 key
[4].key
= &k_bd_addr_oui
;
583 key
[5].key
= &k_bd_addr_id
;
585 key
[6].key
= &k_service_type
;
587 key
[7].key
= &k_service_channel
;
589 key
[8].key
= &k_frame_number
;
593 service_info
= btsdp_get_service_info(key
);
596 service_info
->interface_id
== interface_id
&&
597 service_info
->adapter_id
== adapter_id
&&
598 service_info
->sdp_psm
== SDP_PSM_DEFAULT
&&
599 ((service_info
->direction
== P2P_DIR_RECV
&&
600 service_info
->bd_addr_oui
== remote_bd_addr_oui
&&
601 service_info
->bd_addr_id
== remote_bd_addr_id
) ||
602 (service_info
->direction
!= P2P_DIR_RECV
&&
603 service_info
->bd_addr_oui
== 0 &&
604 service_info
->bd_addr_id
== 0)) &&
605 service_info
->type
== BTSDP_L2CAP_PROTOCOL_UUID
&&
606 service_info
->channel
== psm
)
608 return service_info
->uuid
.bt_uuid
;
615 dissect_comrej(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
, proto_tree
*tree
)
619 reason
= tvb_get_letohs(tvb
, offset
);
620 proto_tree_add_item(tree
, hf_btl2cap_rej_reason
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
624 case 0x0000: /* Command not understood */
627 case 0x0001: /* Signaling MTU exceeded */
628 proto_tree_add_item(tree
, hf_btl2cap_sig_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
632 case 0x0002: /* Invalid CID in requests */
633 proto_tree_add_item(tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
636 proto_tree_add_item(tree
, hf_btl2cap_dcid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
649 dissect_connrequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
650 proto_tree
*tree
, proto_tree
*command_tree
, bool is_ch_request
,
651 bthci_acl_data_t
*acl_data
, btl2cap_data_t
*l2cap_data
)
655 const char *psm_str
= "<NONE>";
657 psm
= tvb_get_letohs(tvb
, offset
);
659 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
) == NULL
) {
660 uint16_t *value_data
;
662 value_data
= wmem_new(wmem_file_scope(), uint16_t);
665 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
, value_data
);
668 if (psm
< BTL2CAP_DYNAMIC_PSM_START
) {
669 proto_tree_add_item(command_tree
, hf_btl2cap_psm
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
670 psm_str
= val_to_str_const(psm
, psm_vals
, "Unknown PSM");
675 item
= proto_tree_add_item(command_tree
, hf_btl2cap_psm_dynamic
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
677 uuid
= get_service_uuid(pinfo
, l2cap_data
, psm
, (pinfo
->p2p_dir
== P2P_DIR_RECV
) ? true : false);
679 psm_str
= val_to_str_ext_const(uuid
, &bluetooth_uuid_vals_ext
, "Unknown PSM");
680 proto_item_append_text(item
, " (%s)", psm_str
);
685 scid
= tvb_get_letohs(tvb
, offset
);
686 proto_tree_add_item(command_tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
689 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s, SCID: 0x%04x)", psm_str
, scid
);
692 proto_tree_add_item(command_tree
, hf_btl2cap_controller
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
696 if (!pinfo
->fd
->visited
) {
697 wmem_tree_key_t key
[6];
698 uint32_t k_interface_id
;
699 uint32_t k_adapter_id
;
702 uint32_t k_frame_number
;
703 uint32_t interface_id
;
706 psm_data_t
*psm_data
;
708 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
709 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
711 interface_id
= HCI_INTERFACE_DEFAULT
;
712 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
713 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
715 k_interface_id
= interface_id
;
716 k_adapter_id
= adapter_id
;
718 k_cid
= scid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x80000000 : 0x00000000);
719 k_frame_number
= pinfo
->num
;
721 psm_data
= wmem_new0(wmem_file_scope(), psm_data_t
);
722 if (pinfo
->p2p_dir
== P2P_DIR_RECV
) {
723 psm_data
->local_cid
= BTL2CAP_UNKNOWN_CID
;
724 psm_data
->remote_cid
= scid
| 0x80000000;
726 psm_data
->local_cid
= scid
;
727 psm_data
->remote_cid
= BTL2CAP_UNKNOWN_CID
;
730 psm_data
->local_service
= (pinfo
->p2p_dir
== P2P_DIR_RECV
) ? true : false;
731 psm_data
->in
.start_fragments
= wmem_tree_new(wmem_file_scope());
732 psm_data
->out
.start_fragments
= wmem_tree_new(wmem_file_scope());
733 psm_data
->interface_id
= k_interface_id
;
734 psm_data
->adapter_id
= k_adapter_id
;
735 psm_data
->chandle
= k_chandle
;
736 psm_data
->connect_in_frame
= pinfo
->num
;
737 psm_data
->disconnect_in_frame
= bluetooth_max_disconnect_in_frame
;
740 key
[0].key
= &k_interface_id
;
742 key
[1].key
= &k_adapter_id
;
744 key
[2].key
= &k_chandle
;
748 key
[4].key
= &k_frame_number
;
752 wmem_tree_insert32_array(cid_to_psm_table
, key
, psm_data
);
756 proto_item
*sub_item
;
757 uint32_t bt_uuid
= 0;
758 uint32_t disconnect_in_frame
= 0;
759 psm_data_t
*psm_data
;
760 wmem_tree_key_t key
[6];
761 uint32_t k_interface_id
;
762 uint32_t k_adapter_id
;
765 uint32_t k_frame_number
;
766 uint32_t interface_id
;
770 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
771 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
773 interface_id
= HCI_INTERFACE_DEFAULT
;
774 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
775 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
777 k_interface_id
= interface_id
;
778 k_adapter_id
= adapter_id
;
780 k_cid
= scid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x80000000 : 0x00000000);
781 k_frame_number
= pinfo
->num
;
784 key
[0].key
= &k_interface_id
;
786 key
[1].key
= &k_adapter_id
;
788 key
[2].key
= &k_chandle
;
792 key
[4].key
= &k_frame_number
;
796 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
798 psm_data
->interface_id
== interface_id
&&
799 psm_data
->adapter_id
== adapter_id
&&
800 psm_data
->chandle
== chandle
&&
801 psm_data
->local_cid
== k_cid
)
803 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm_data
->psm
, psm_data
->local_service
);
804 disconnect_in_frame
= psm_data
->disconnect_in_frame
;
808 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_service
, tvb
, 0, 0, bt_uuid
);
809 proto_item_set_generated(sub_item
);
812 if (disconnect_in_frame
< bluetooth_max_disconnect_in_frame
) {
813 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_disconnect_in_frame
, tvb
, 0, 0, disconnect_in_frame
);
814 proto_item_set_generated(sub_item
);
821 dissect_le_credit_based_connrequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
822 proto_tree
*tree
, proto_tree
*command_tree
, uint16_t cid
, uint8_t cmd_ident
,
823 bthci_acl_data_t
*acl_data
, btl2cap_data_t
*l2cap_data
)
826 proto_item
*psm_item
;
831 proto_tree_add_item_ret_uint(command_tree
, hf_btl2cap_le_psm
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &psm
);
833 psm_item
= proto_tree_add_item(command_tree
, hf_btl2cap_psm
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
834 proto_item_set_generated(psm_item
);
838 proto_tree_add_item_ret_uint(command_tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &scid
);
841 proto_tree_add_item(command_tree
, hf_btl2cap_option_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
844 proto_tree_add_item(command_tree
, hf_btl2cap_option_mps
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
847 proto_tree_add_item(command_tree
, hf_btl2cap_initial_credits
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
850 if (!pinfo
->fd
->visited
) {
851 wmem_tree_key_t key
[8];
852 uint32_t k_interface_id
;
853 uint32_t k_adapter_id
;
856 uint32_t k_cmd_ident
;
857 uint32_t k_frame_number
;
858 uint32_t interface_id
;
861 psm_data_t
*psm_data
;
865 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
866 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
868 interface_id
= HCI_INTERFACE_DEFAULT
;
869 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
870 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
872 k_interface_id
= interface_id
;
873 k_adapter_id
= adapter_id
;
876 k_cmd_ident
= cmd_ident
;
877 k_frame_number
= pinfo
->num
;
880 psm_data
= wmem_new0(wmem_file_scope(), psm_data_t
);
882 if (pinfo
->p2p_dir
== P2P_DIR_RECV
) {
883 key_cid
= scid
| 0x80000000;
884 psm_data
->local_cid
= BTL2CAP_UNKNOWN_CID
;
885 psm_data
->remote_cid
= key_cid
;
889 psm_data
->local_cid
= key_cid
;
890 psm_data
->remote_cid
= BTL2CAP_UNKNOWN_CID
;
894 psm_data
->local_service
= (pinfo
->p2p_dir
== P2P_DIR_RECV
) ? true : false;
895 psm_data
->in
.mode
= L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
;
896 psm_data
->in
.start_fragments
= wmem_tree_new(wmem_file_scope());
897 psm_data
->out
.mode
= L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
;
898 psm_data
->out
.start_fragments
= wmem_tree_new(wmem_file_scope());
899 psm_data
->interface_id
= k_interface_id
;
900 psm_data
->adapter_id
= k_adapter_id
;
901 psm_data
->chandle
= k_chandle
;
902 psm_data
->connect_in_frame
= pinfo
->num
;
903 psm_data
->disconnect_in_frame
= bluetooth_max_disconnect_in_frame
;
906 key
[0].key
= &k_interface_id
;
908 key
[1].key
= &k_adapter_id
;
910 key
[2].key
= &k_chandle
;
914 key
[4].key
= &k_cmd_ident
;
916 key
[5].key
= &k_frame_number
;
918 key
[6].key
= &cid_index
;
922 wmem_tree_insert32_array(cmd_ident_to_psm_table
, key
, psm_data
);
927 key
[4].key
= &k_frame_number
;
931 wmem_tree_insert32_array(cid_to_psm_table
, key
, psm_data
);
935 proto_item
*sub_item
;
936 uint32_t bt_uuid
= 0;
937 uint32_t disconnect_in_frame
= 0;
938 psm_data_t
*psm_data
;
939 wmem_tree_key_t key
[6];
940 uint32_t k_interface_id
;
941 uint32_t k_adapter_id
;
944 uint32_t k_frame_number
;
945 uint32_t interface_id
;
949 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
950 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
952 interface_id
= HCI_INTERFACE_DEFAULT
;
953 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
954 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
956 k_interface_id
= interface_id
;
957 k_adapter_id
= adapter_id
;
960 k_frame_number
= pinfo
->num
;
963 key
[0].key
= &k_interface_id
;
965 key
[1].key
= &k_adapter_id
;
967 key
[2].key
= &k_chandle
;
971 key
[4].key
= &k_frame_number
;
975 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
977 psm_data
->interface_id
== interface_id
&&
978 psm_data
->adapter_id
== adapter_id
&&
979 psm_data
->chandle
== chandle
&&
980 psm_data
->local_cid
== k_cid
)
982 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm_data
->psm
, psm_data
->local_service
);
983 disconnect_in_frame
= psm_data
->disconnect_in_frame
;
987 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_service
, tvb
, 0, 0, bt_uuid
);
988 proto_item_set_generated(sub_item
);
991 if (disconnect_in_frame
< bluetooth_max_disconnect_in_frame
) {
992 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_disconnect_in_frame
, tvb
, 0, 0, disconnect_in_frame
);
993 proto_item_set_generated(sub_item
);
1001 dissect_le_credit_based_connresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1002 proto_tree
*tree
, uint16_t cid
, uint8_t cmd_ident
, bthci_acl_data_t
*acl_data
)
1006 proto_tree_add_item_ret_uint(tree
, hf_btl2cap_dcid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &dcid
);
1009 proto_tree_add_item(tree
, hf_btl2cap_option_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1012 proto_tree_add_item(tree
, hf_btl2cap_option_mps
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1015 proto_tree_add_item(tree
, hf_btl2cap_initial_credits
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1018 proto_tree_add_item(tree
, hf_btl2cap_le_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1022 if (pinfo
->fd
->visited
== 0) {
1023 psm_data_t
*psm_data
;
1024 wmem_tree_key_t key
[8];
1025 uint32_t k_interface_id
;
1026 uint32_t k_adapter_id
;
1029 uint32_t k_cmd_ident
;
1030 uint32_t k_frame_number
;
1031 uint32_t interface_id
;
1032 uint32_t adapter_id
;
1037 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1038 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1040 interface_id
= HCI_INTERFACE_DEFAULT
;
1041 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1042 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1044 k_interface_id
= interface_id
;
1045 k_adapter_id
= adapter_id
;
1046 k_chandle
= chandle
;
1048 k_cmd_ident
= cmd_ident
;
1049 k_frame_number
= pinfo
->num
;
1053 key
[0].key
= &k_interface_id
;
1055 key
[1].key
= &k_adapter_id
;
1057 key
[2].key
= &k_chandle
;
1059 key
[3].key
= &k_cid
;
1061 key
[4].key
= &k_cmd_ident
;
1063 key
[5].key
= &k_frame_number
;
1065 key
[6].key
= &cid_index
;
1069 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cmd_ident_to_psm_table
, key
);
1071 psm_data
->interface_id
== interface_id
&&
1072 psm_data
->adapter_id
== adapter_id
&&
1073 psm_data
->chandle
== chandle
&&
1074 psm_data
->disconnect_in_frame
> pinfo
->num
)
1076 key_cid
= dcid
| ((pinfo
->p2p_dir
!= P2P_DIR_RECV
) ? 0x00000000 : 0x80000000);
1078 k_interface_id
= interface_id
;
1079 k_adapter_id
= adapter_id
;
1080 k_chandle
= chandle
;
1082 k_frame_number
= pinfo
->num
;
1085 key
[0].key
= &k_interface_id
;
1087 key
[1].key
= &k_adapter_id
;
1089 key
[2].key
= &k_chandle
;
1091 key
[3].key
= &k_cid
;
1093 key
[4].key
= &k_frame_number
;
1097 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
1098 psm_data
->remote_cid
= key_cid
;
1100 psm_data
->local_cid
= key_cid
;
1102 wmem_tree_insert32_array(cid_to_psm_table
, key
, psm_data
);
1109 dissect_l2cap_credit_based_connrequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1110 proto_tree
*tree
, proto_tree
*command_tree
, uint16_t cid
, uint8_t cmd_ident
,
1111 uint16_t length
, bthci_acl_data_t
*acl_data
, btl2cap_data_t
*l2cap_data
)
1114 proto_item
*psm_item
;
1119 proto_tree_add_item_ret_uint(command_tree
, hf_btl2cap_le_psm
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &psm
);
1121 psm_item
= proto_tree_add_item(command_tree
, hf_btl2cap_psm
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1122 proto_item_set_generated(psm_item
);
1126 proto_tree_add_item(command_tree
, hf_btl2cap_option_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1129 proto_tree_add_item(command_tree
, hf_btl2cap_option_mps
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1132 proto_tree_add_item(command_tree
, hf_btl2cap_initial_credits
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1136 while (offset
< length
+ 8) {
1137 proto_tree_add_item_ret_uint(command_tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &scid
);
1140 if (!pinfo
->fd
->visited
) {
1141 wmem_tree_key_t key
[8];
1142 uint32_t k_interface_id
;
1143 uint32_t k_adapter_id
;
1146 uint32_t k_cmd_ident
;
1147 uint32_t k_frame_number
;
1148 uint32_t interface_id
;
1149 uint32_t adapter_id
;
1151 psm_data_t
*psm_data
;
1154 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1155 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1157 interface_id
= HCI_INTERFACE_DEFAULT
;
1158 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1159 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1161 k_interface_id
= interface_id
;
1162 k_adapter_id
= adapter_id
;
1163 k_chandle
= chandle
;
1165 k_cmd_ident
= cmd_ident
;
1166 k_frame_number
= pinfo
->num
;
1168 psm_data
= wmem_new0(wmem_file_scope(), psm_data_t
);
1170 if (pinfo
->p2p_dir
== P2P_DIR_RECV
) {
1171 key_cid
= scid
| 0x80000000;
1172 psm_data
->local_cid
= BTL2CAP_UNKNOWN_CID
;
1173 psm_data
->remote_cid
= key_cid
;
1177 psm_data
->local_cid
= key_cid
;
1178 psm_data
->remote_cid
= BTL2CAP_UNKNOWN_CID
;
1181 psm_data
->psm
= psm
;
1182 psm_data
->local_service
= (pinfo
->p2p_dir
== P2P_DIR_RECV
) ? true : false;
1183 psm_data
->in
.mode
= L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
;
1184 psm_data
->in
.start_fragments
= wmem_tree_new(wmem_file_scope());
1185 psm_data
->out
.mode
= L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
;
1186 psm_data
->out
.start_fragments
= wmem_tree_new(wmem_file_scope());
1187 psm_data
->interface_id
= k_interface_id
;
1188 psm_data
->adapter_id
= k_adapter_id
;
1189 psm_data
->chandle
= k_chandle
;
1190 psm_data
->connect_in_frame
= pinfo
->num
;
1191 psm_data
->disconnect_in_frame
= bluetooth_max_disconnect_in_frame
;
1194 key
[0].key
= &k_interface_id
;
1196 key
[1].key
= &k_adapter_id
;
1198 key
[2].key
= &k_chandle
;
1200 key
[3].key
= &k_cid
;
1202 key
[4].key
= &k_cmd_ident
;
1204 key
[5].key
= &k_frame_number
;
1206 key
[6].key
= &cid_index
;
1210 wmem_tree_insert32_array(cmd_ident_to_psm_table
, key
, psm_data
);
1215 key
[4].key
= &k_frame_number
;
1219 wmem_tree_insert32_array(cid_to_psm_table
, key
, psm_data
);
1223 proto_item
*sub_item
;
1224 uint32_t bt_uuid
= 0;
1225 uint32_t disconnect_in_frame
= 0;
1226 psm_data_t
*psm_data
;
1227 wmem_tree_key_t key
[6];
1228 uint32_t k_interface_id
;
1229 uint32_t k_adapter_id
;
1232 uint32_t k_frame_number
;
1233 uint32_t interface_id
;
1234 uint32_t adapter_id
;
1237 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1238 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1240 interface_id
= HCI_INTERFACE_DEFAULT
;
1241 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1242 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1244 k_interface_id
= interface_id
;
1245 k_adapter_id
= adapter_id
;
1246 k_chandle
= chandle
;
1248 k_frame_number
= pinfo
->num
;
1251 key
[0].key
= &k_interface_id
;
1253 key
[1].key
= &k_adapter_id
;
1255 key
[2].key
= &k_chandle
;
1257 key
[3].key
= &k_cid
;
1259 key
[4].key
= &k_frame_number
;
1263 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
1265 psm_data
->interface_id
== interface_id
&&
1266 psm_data
->adapter_id
== adapter_id
&&
1267 psm_data
->chandle
== chandle
&&
1268 psm_data
->local_cid
== k_cid
)
1270 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm_data
->psm
, psm_data
->local_service
);
1271 disconnect_in_frame
= psm_data
->disconnect_in_frame
;
1275 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_service
, tvb
, 0, 0, bt_uuid
);
1276 proto_item_set_generated(sub_item
);
1279 if (disconnect_in_frame
< bluetooth_max_disconnect_in_frame
) {
1280 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_disconnect_in_frame
, tvb
, 0, 0, disconnect_in_frame
);
1281 proto_item_set_generated(sub_item
);
1291 dissect_l2cap_credit_based_connresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1292 proto_tree
*tree
, uint16_t cid
, uint8_t cmd_ident
, uint16_t length
,
1293 bthci_acl_data_t
*acl_data
)
1298 proto_tree_add_item(tree
, hf_btl2cap_option_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1301 proto_tree_add_item(tree
, hf_btl2cap_option_mps
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1304 proto_tree_add_item(tree
, hf_btl2cap_initial_credits
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1307 proto_tree_add_item(tree
, hf_btl2cap_le_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1311 while (offset
< length
+ 8) {
1312 proto_tree_add_item_ret_uint(tree
, hf_btl2cap_dcid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &dcid
);
1315 if (pinfo
->fd
->visited
== 0) {
1316 psm_data_t
*psm_data
;
1317 wmem_tree_key_t key
[8];
1318 uint32_t k_interface_id
;
1319 uint32_t k_adapter_id
;
1322 uint32_t k_cmd_ident
;
1323 uint32_t k_frame_number
;
1324 uint32_t interface_id
;
1325 uint32_t adapter_id
;
1329 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1330 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1332 interface_id
= HCI_INTERFACE_DEFAULT
;
1333 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1334 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1336 k_interface_id
= interface_id
;
1337 k_adapter_id
= adapter_id
;
1338 k_chandle
= chandle
;
1340 k_cmd_ident
= cmd_ident
;
1341 k_frame_number
= pinfo
->num
;
1344 key
[0].key
= &k_interface_id
;
1346 key
[1].key
= &k_adapter_id
;
1348 key
[2].key
= &k_chandle
;
1350 key
[3].key
= &k_cid
;
1352 key
[4].key
= &k_cmd_ident
;
1354 key
[5].key
= &k_frame_number
;
1356 key
[6].key
= &cid_index
;
1360 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cmd_ident_to_psm_table
, key
);
1362 psm_data
->interface_id
== interface_id
&&
1363 psm_data
->adapter_id
== adapter_id
&&
1364 psm_data
->chandle
== chandle
&&
1365 psm_data
->disconnect_in_frame
> pinfo
->num
)
1367 key_cid
= dcid
| ((pinfo
->p2p_dir
!= P2P_DIR_RECV
) ? 0x00000000 : 0x80000000);
1369 k_interface_id
= interface_id
;
1370 k_adapter_id
= adapter_id
;
1371 k_chandle
= chandle
;
1373 k_frame_number
= pinfo
->num
;
1376 key
[0].key
= &k_interface_id
;
1378 key
[1].key
= &k_adapter_id
;
1380 key
[2].key
= &k_chandle
;
1382 key
[3].key
= &k_cid
;
1384 key
[4].key
= &k_frame_number
;
1388 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
1389 psm_data
->remote_cid
= key_cid
;
1391 psm_data
->local_cid
= key_cid
;
1393 wmem_tree_insert32_array(cid_to_psm_table
, key
, psm_data
);
1401 dissect_movechanrequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1406 icid
= tvb_get_letohs(tvb
, offset
);
1407 proto_tree_add_item(tree
, hf_btl2cap_icid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1410 ctrl_id
= tvb_get_uint8(tvb
, offset
);
1411 proto_tree_add_item(tree
, hf_btl2cap_dcontroller
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1414 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (ICID: 0x%04x, move to %s)", icid
,
1415 val_to_str_const(ctrl_id
, ctrl_id_code_vals
, "Unknown controller"));
1421 dissect_options(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
, proto_tree
*tree
, int length
, config_data_t
*config_data
)
1423 proto_item
*ti_option
;
1424 proto_tree
*ti_option_subtree
;
1425 uint8_t option_type
, option_length
;
1428 config_data
->mode
= L2CAP_BASIC_MODE
;
1429 config_data
->txwindow
= 0;
1432 while (length
> 0) {
1433 option_type
= tvb_get_uint8(tvb
, offset
);
1434 option_length
= tvb_get_uint8(tvb
, offset
+ 1);
1436 ti_option
= proto_tree_add_none_format(tree
,
1437 hf_btl2cap_option
, tvb
,
1438 offset
, option_length
+ 2,
1440 ti_option_subtree
= proto_item_add_subtree(ti_option
, ett_btl2cap_option
);
1441 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1442 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_length
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
1445 if (option_length
!= 0) {
1446 switch (option_type
) {
1447 case 0x01: /* MTU */
1448 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1451 proto_item_append_text(ti_option
, "MTU");
1454 case 0x02: /* Flush timeout */
1455 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_flushTO
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1458 proto_item_append_text(ti_option
, "Flush Timeout");
1461 case 0x03: /* QOS */
1462 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_flags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1465 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_service_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1468 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_tokenrate
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1471 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_tokenbucketsize
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1474 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_peakbandwidth
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1477 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_latency
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1480 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_delayvariation
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1483 proto_item_append_text(ti_option
, "QOS");
1486 case 0x04: /* Retransmission and Flow Control*/
1489 config_data
->mode
= tvb_get_uint8(tvb
, offset
);
1490 config_data
->txwindow
= tvb_get_uint8(tvb
, offset
+ 1);
1492 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_retransmissionmode
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1495 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_txwindow
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1498 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_maxtransmit
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1501 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_retransmittimeout
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1504 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_monitortimeout
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1507 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_mps
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1510 proto_item_append_text(ti_option
, "Retransmission and Flow Control");
1513 case 0x05: /* FCS */
1514 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_fcs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1517 proto_item_append_text(ti_option
, "FCS");
1520 case 0x06: /* Extended Flow Specification */
1521 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_identifier
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1524 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_service_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1527 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_sdu_size
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1530 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_sdu_arrival_time
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1533 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_access_latency
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1536 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_flush_to_us
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1539 proto_item_append_text(ti_option
, "Extended Flow Specification");
1542 case 0x07: /* Extended Window Size */
1543 proto_tree_add_item(ti_option_subtree
, hf_btl2cap_option_window
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1546 proto_item_append_text(ti_option
, "Extended Window Size");
1550 proto_item_append_text(ti_option
, "unknown");
1551 offset
+= option_length
;
1555 length
-= (option_length
+ 2);
1563 dissect_configrequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1564 proto_tree
*tree
, uint16_t length
, bthci_acl_data_t
*acl_data
)
1568 dcid
= tvb_get_letohs(tvb
, offset
);
1570 proto_tree_add_item(tree
, hf_btl2cap_dcid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1573 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (DCID: 0x%04x)", dcid
);
1575 proto_tree_add_item(tree
, hf_btl2cap_flags_reserved
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1576 proto_tree_add_item(tree
, hf_btl2cap_flags_continuation
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1580 psm_data_t
*psm_data
;
1581 config_data_t
*config_data
;
1582 wmem_tree_key_t key
[6];
1583 uint32_t k_interface_id
;
1584 uint32_t k_adapter_id
;
1587 uint32_t k_frame_number
;
1588 uint32_t interface_id
;
1589 uint32_t adapter_id
;
1593 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1594 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1596 interface_id
= HCI_INTERFACE_DEFAULT
;
1597 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1598 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1599 cid
= dcid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x00000000 : 0x80000000);
1601 k_interface_id
= interface_id
;
1602 k_adapter_id
= adapter_id
;
1603 k_chandle
= chandle
;
1605 k_frame_number
= pinfo
->num
;
1608 key
[0].key
= &k_interface_id
;
1610 key
[1].key
= &k_adapter_id
;
1612 key
[2].key
= &k_chandle
;
1614 key
[3].key
= &k_cid
;
1616 key
[4].key
= &k_frame_number
;
1620 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
1622 psm_data
->interface_id
== interface_id
&&
1623 psm_data
->adapter_id
== adapter_id
&&
1624 psm_data
->chandle
== chandle
&&
1625 ((pinfo
->p2p_dir
== P2P_DIR_SENT
&& psm_data
->remote_cid
== cid
) ||
1626 (pinfo
->p2p_dir
== P2P_DIR_RECV
&& psm_data
->local_cid
== cid
)) &&
1627 psm_data
->disconnect_in_frame
> pinfo
->num
)
1629 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
1630 config_data
= &(psm_data
->out
);
1632 config_data
= &(psm_data
->in
);
1636 if (config_data
!= NULL
) {
1637 /* Reset config_data that might have been set by an earlier
1638 * Configure Request that failed.
1640 config_data
->mode
= L2CAP_BASIC_MODE
;
1641 config_data
->txwindow
= 0;
1643 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1644 offset
= dissect_options(tvb
, offset
, pinfo
, tree
, length
- 4, config_data
);
1653 dissect_inforequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1657 info_type
= tvb_get_letohs(tvb
, offset
);
1658 proto_tree_add_item(tree
, hf_btl2cap_info_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1661 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)", val_to_str_const(info_type
, info_type_vals
, "Unknown type"));
1666 dissect_inforesponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1668 uint16_t info_type
, result
;
1670 info_type
= tvb_get_letohs(tvb
, offset
);
1671 proto_tree_add_item(tree
, hf_btl2cap_info_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1674 result
= tvb_get_letohs(tvb
, offset
);
1675 proto_tree_add_item(tree
, hf_btl2cap_info_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1678 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s, %s)",
1679 val_to_str_const(info_type
, info_type_vals
, "Unknown type"),
1680 val_to_str_const(result
, info_result_vals
, "Unknown result"));
1682 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1683 proto_item
*ti_features
;
1684 proto_tree
*ti_features_subtree
;
1687 switch (info_type
) {
1688 case 0x0001: /* Connectionless MTU */
1689 proto_tree_add_item(tree
, hf_btl2cap_info_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1693 case 0x0002: /* Extended Features */
1694 ti_features
= proto_tree_add_none_format(tree
,
1695 hf_btl2cap_info_extfeatures
, tvb
,
1698 ti_features_subtree
= proto_item_add_subtree(ti_features
, ett_btl2cap_extfeatures
);
1699 features
= tvb_get_letohl(tvb
, offset
);
1701 proto_item_append_text(ti_features
, "FlowControl ");
1703 proto_item_append_text(ti_features
, "Retransmission ");
1705 proto_item_append_text(ti_features
, "BiDirQOS ");
1707 proto_item_append_text(ti_features
, "EnhRetransmission ");
1708 if (features
& 0x10)
1709 proto_item_append_text(ti_features
, "Streaming ");
1710 if (features
& 0x20)
1711 proto_item_append_text(ti_features
, "FCS ");
1712 if (features
& 0x40)
1713 proto_item_append_text(ti_features
, "FlowSpec ");
1714 if (features
& 0x80)
1715 proto_item_append_text(ti_features
, "FixedChan ");
1716 if (features
& 0x100)
1717 proto_item_append_text(ti_features
, "WindowSize ");
1718 if (features
& 0x200)
1719 proto_item_append_text(ti_features
, "Unicast ");
1720 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_flowcontrol
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1721 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_retransmission
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1722 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_bidirqos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1723 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_enh_retransmission
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1724 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_streaming
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1725 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fcs
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1726 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_flow_spec
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1727 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchan
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1728 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_window
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1729 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_unicast
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1734 case 0x0003: /* Fixed Channels Supported */
1735 ti_features
= proto_tree_add_none_format(tree
,
1736 hf_btl2cap_info_fixedchans
, tvb
,
1738 "Fixed Channels Supported:");
1739 ti_features_subtree
= proto_item_add_subtree(ti_features
, ett_btl2cap_fixedchans
);
1740 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_null
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1741 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_signal
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1742 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_connless
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1743 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_amp_man
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1744 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_rfu
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1745 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_smp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1747 proto_tree_add_item(ti_features_subtree
, hf_btl2cap_info_fixedchans_amp_test
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1753 proto_tree_add_item(tree
, hf_btl2cap_cmd_data
, tvb
, offset
, -1, ENC_NA
);
1754 offset
+= tvb_reported_length_remaining(tvb
, offset
);
1764 dissect_configresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1765 proto_tree
*tree
, uint16_t length
, bthci_acl_data_t
*acl_data
)
1771 scid
= tvb_get_letohs(tvb
, offset
);
1773 proto_tree_add_item(tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1776 proto_tree_add_item(tree
, hf_btl2cap_flags_reserved
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1777 proto_tree_add_item(tree
, hf_btl2cap_flags_continuation
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1780 result
= tvb_get_letohs(tvb
, offset
);
1781 proto_tree_add_item(tree
, hf_btl2cap_configuration_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1784 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - %s (SCID: 0x%04x)",
1785 val_to_str_const(result
, configuration_result_vals
, "Unknown"), scid
);
1787 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1788 psm_data_t
*psm_data
;
1789 config_data_t
*config_data
;
1790 wmem_tree_key_t key
[6];
1791 uint32_t k_interface_id
;
1792 uint32_t k_adapter_id
;
1795 uint32_t k_frame_number
;
1796 uint32_t interface_id
;
1797 uint32_t adapter_id
;
1801 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1802 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1804 interface_id
= HCI_INTERFACE_DEFAULT
;
1805 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1806 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1807 cid
= scid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x00000000 : 0x80000000);
1809 k_interface_id
= interface_id
;
1810 k_adapter_id
= adapter_id
;
1811 k_chandle
= chandle
;
1813 k_frame_number
= pinfo
->num
;
1816 key
[0].key
= &k_interface_id
;
1818 key
[1].key
= &k_adapter_id
;
1820 key
[2].key
= &k_chandle
;
1822 key
[3].key
= &k_cid
;
1824 key
[4].key
= &k_frame_number
;
1828 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
1830 psm_data
->interface_id
== interface_id
&&
1831 psm_data
->adapter_id
== adapter_id
&&
1832 psm_data
->chandle
== chandle
&&
1833 ((pinfo
->p2p_dir
== P2P_DIR_SENT
&& psm_data
->local_cid
== cid
) ||
1834 (pinfo
->p2p_dir
== P2P_DIR_RECV
&& psm_data
->remote_cid
== cid
)) &&
1835 psm_data
->disconnect_in_frame
> pinfo
->num
)
1837 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
1838 config_data
= &(psm_data
->out
);
1840 config_data
= &(psm_data
->in
);
1844 offset
= dissect_options(tvb
, offset
, pinfo
, tree
, length
- 6, config_data
);
1851 dissect_connresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
1852 proto_tree
*tree
, bthci_acl_data_t
*acl_data
)
1854 uint16_t scid
, dcid
, result
;
1856 dcid
= tvb_get_letohs(tvb
, offset
);
1857 proto_tree_add_item(tree
, hf_btl2cap_dcid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1860 scid
= tvb_get_letohs(tvb
, offset
);
1861 proto_tree_add_item(tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1864 result
= tvb_get_letohs(tvb
, offset
);
1865 proto_tree_add_item(tree
, hf_btl2cap_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1868 proto_tree_add_item(tree
, hf_btl2cap_status
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1872 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Success (SCID: 0x%04x, DCID: 0x%04x)", scid
, dcid
);
1875 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - %s (SCID: 0x%04x)",
1876 val_to_str_const(result
, result_vals
, "Unknown"), scid
);
1879 if (pinfo
->fd
->visited
== 0) {
1880 psm_data_t
*psm_data
;
1881 wmem_tree_key_t key
[6];
1882 uint32_t k_interface_id
;
1883 uint32_t k_adapter_id
;
1886 uint32_t k_frame_number
;
1887 uint32_t interface_id
;
1888 uint32_t adapter_id
;
1892 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
1893 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
1895 interface_id
= HCI_INTERFACE_DEFAULT
;
1896 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
1897 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
1898 cid
= scid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x00000000 : 0x80000000);
1900 k_interface_id
= interface_id
;
1901 k_adapter_id
= adapter_id
;
1902 k_chandle
= chandle
;
1904 k_frame_number
= pinfo
->num
;
1907 key
[0].key
= &k_interface_id
;
1909 key
[1].key
= &k_adapter_id
;
1911 key
[2].key
= &k_chandle
;
1913 key
[3].key
= &k_cid
;
1915 key
[4].key
= &k_frame_number
;
1919 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
1921 psm_data
->interface_id
== interface_id
&&
1922 psm_data
->adapter_id
== adapter_id
&&
1923 psm_data
->chandle
== chandle
&&
1924 ((pinfo
->p2p_dir
== P2P_DIR_SENT
&& psm_data
->remote_cid
== cid
) ||
1925 (pinfo
->p2p_dir
== P2P_DIR_RECV
&& psm_data
->local_cid
== cid
)) &&
1926 psm_data
->disconnect_in_frame
> pinfo
->num
)
1928 cid
= dcid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x80000000 : 0x00000000);
1930 k_interface_id
= interface_id
;
1931 k_adapter_id
= adapter_id
;
1932 k_chandle
= chandle
;
1934 k_frame_number
= pinfo
->num
;
1937 key
[0].key
= &k_interface_id
;
1939 key
[1].key
= &k_adapter_id
;
1941 key
[2].key
= &k_chandle
;
1943 key
[3].key
= &k_cid
;
1945 key
[4].key
= &k_frame_number
;
1949 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
1950 psm_data
->remote_cid
= cid
;
1952 psm_data
->local_cid
= cid
;
1954 wmem_tree_insert32_array(cid_to_psm_table
, key
, psm_data
);
1962 dissect_chanresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, bthci_acl_data_t
*acl_data
)
1964 return dissect_connresponse(tvb
, offset
, pinfo
, tree
, acl_data
);
1968 dissect_movechanresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1970 uint16_t icid
, result
;
1972 icid
= tvb_get_letohs(tvb
, offset
);
1973 proto_tree_add_item(tree
, hf_btl2cap_icid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1976 result
= tvb_get_letohs(tvb
, offset
);
1977 proto_tree_add_item(tree
, hf_btl2cap_move_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1980 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (ICID: 0x%04x, %s)", icid
,
1981 val_to_str_const(result
, move_result_vals
, "Unknown result"));
1987 dissect_movechanconfirmation(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1989 uint16_t icid
, result
;
1991 icid
= tvb_get_letohs(tvb
, offset
);
1992 proto_tree_add_item(tree
, hf_btl2cap_icid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1995 result
= tvb_get_letohs(tvb
, offset
);
1996 proto_tree_add_item(tree
, hf_btl2cap_move_confirmation_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1999 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (ICID: 0x%04x, %s)", icid
,
2000 val_to_str_const(result
, move_result_confirmation_vals
, "Unknown result"));
2006 dissect_movechanconfirmationresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
2010 icid
= tvb_get_letohs(tvb
, offset
);
2011 proto_tree_add_item(tree
, hf_btl2cap_icid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2014 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (ICID: 0x%04x)", icid
);
2019 dissect_connparamrequest(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
2022 uint16_t max_interval
, peripheral_latency
;
2024 item
= proto_tree_add_item(tree
, hf_btl2cap_min_interval
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2025 proto_item_append_text(item
, " (%g msec)", tvb_get_letohs(tvb
, offset
) * 1.25);
2027 item
= proto_tree_add_item(tree
, hf_btl2cap_max_interval
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2028 proto_item_append_text(item
, " (%g msec)", tvb_get_letohs(tvb
, offset
) * 1.25);
2029 max_interval
= tvb_get_letohs(tvb
, offset
);
2031 item
= proto_tree_add_item(tree
, hf_btl2cap_peripheral_latency
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2032 peripheral_latency
= tvb_get_letohs(tvb
, offset
);
2034 if(peripheral_latency
>= 500 || max_interval
== 0 ||
2035 peripheral_latency
> 10.0 * tvb_get_letohs(tvb
, offset
+ 2) / (max_interval
*1.25))
2036 expert_add_info(pinfo
, item
, &ei_btl2cap_parameter_mismatch
);
2039 item
= proto_tree_add_item(tree
, hf_btl2cap_timeout_multiplier
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2040 proto_item_append_text(item
, " (%g sec)", tvb_get_letohs(tvb
, offset
) * 0.01);
2047 dissect_connparamresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
2051 result
= tvb_get_letohs(tvb
, offset
);
2052 proto_tree_add_item(tree
, hf_btl2cap_conn_param_result
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2055 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)",
2056 val_to_str_const(result
, conn_param_result_vals
, "Unknown result"));
2062 dissect_disconnrequestresponse(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
2063 proto_tree
*tree
, proto_tree
*command_tree
, bthci_acl_data_t
*acl_data
, btl2cap_data_t
*l2cap_data
,
2069 const char *service_name
= "Unknown";
2071 dcid
= tvb_get_letohs(tvb
, offset
);
2072 proto_tree_add_item(command_tree
, hf_btl2cap_dcid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2075 scid
= tvb_get_letohs(tvb
, offset
);
2076 proto_tree_add_item(command_tree
, hf_btl2cap_scid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2079 if (!pinfo
->fd
->visited
) {
2080 psm_data_t
*psm_data
;
2081 wmem_tree_key_t key
[6];
2082 uint32_t k_interface_id
;
2083 uint32_t k_adapter_id
;
2086 uint32_t k_frame_number
;
2087 uint32_t interface_id
;
2088 uint32_t adapter_id
;
2093 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
2094 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
2096 interface_id
= HCI_INTERFACE_DEFAULT
;
2097 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
2098 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
2099 if ((is_request
&& pinfo
->p2p_dir
== P2P_DIR_SENT
) ||
2100 (!is_request
&& pinfo
->p2p_dir
== P2P_DIR_RECV
)) {
2101 key_dcid
= dcid
| 0x80000000;
2104 key_dcid
= scid
| 0x80000000;
2108 k_interface_id
= interface_id
;
2109 k_adapter_id
= adapter_id
;
2110 k_chandle
= chandle
;
2112 k_frame_number
= pinfo
->num
;
2115 key
[0].key
= &k_interface_id
;
2117 key
[1].key
= &k_adapter_id
;
2119 key
[2].key
= &k_chandle
;
2121 key
[3].key
= &k_cid
;
2123 key
[4].key
= &k_frame_number
;
2127 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
2129 psm_data
->interface_id
== interface_id
&&
2130 psm_data
->adapter_id
== adapter_id
&&
2131 psm_data
->chandle
== chandle
&&
2132 psm_data
->remote_cid
== key_dcid
&&
2133 psm_data
->disconnect_in_frame
== bluetooth_max_disconnect_in_frame
)
2135 psm_data
->disconnect_in_frame
= pinfo
->num
;
2138 k_interface_id
= interface_id
;
2139 k_adapter_id
= adapter_id
;
2140 k_chandle
= chandle
;
2142 k_frame_number
= pinfo
->num
;
2145 key
[0].key
= &k_interface_id
;
2147 key
[1].key
= &k_adapter_id
;
2149 key
[2].key
= &k_chandle
;
2151 key
[3].key
= &k_cid
;
2153 key
[4].key
= &k_frame_number
;
2157 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
2159 psm_data
->interface_id
== interface_id
&&
2160 psm_data
->adapter_id
== adapter_id
&&
2161 psm_data
->chandle
== chandle
&&
2162 psm_data
->local_cid
== key_scid
&&
2163 psm_data
->disconnect_in_frame
== bluetooth_max_disconnect_in_frame
)
2165 psm_data
->disconnect_in_frame
= pinfo
->num
;
2170 proto_item
*sub_item
;
2171 uint32_t bt_uuid
= 0;
2172 uint32_t connect_in_frame
= 0;
2173 psm_data_t
*psm_data
;
2174 wmem_tree_key_t key
[6];
2175 uint32_t k_interface_id
;
2176 uint32_t k_adapter_id
;
2179 uint32_t k_frame_number
;
2180 uint32_t interface_id
;
2181 uint32_t adapter_id
;
2185 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
2186 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
2188 interface_id
= HCI_INTERFACE_DEFAULT
;
2189 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
2190 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
2191 if ((is_request
&& pinfo
->p2p_dir
== P2P_DIR_SENT
) ||
2192 (!is_request
&& pinfo
->p2p_dir
== P2P_DIR_RECV
)) {
2193 key_dcid
= dcid
| 0x80000000;
2195 key_dcid
= scid
| 0x80000000;
2198 k_interface_id
= interface_id
;
2199 k_adapter_id
= adapter_id
;
2200 k_chandle
= chandle
;
2202 k_frame_number
= pinfo
->num
;
2205 key
[0].key
= &k_interface_id
;
2207 key
[1].key
= &k_adapter_id
;
2209 key
[2].key
= &k_chandle
;
2211 key
[3].key
= &k_cid
;
2213 key
[4].key
= &k_frame_number
;
2217 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
2219 psm_data
->interface_id
== interface_id
&&
2220 psm_data
->adapter_id
== adapter_id
&&
2221 psm_data
->chandle
== chandle
&&
2222 psm_data
->remote_cid
== key_dcid
)
2224 psm
= psm_data
->psm
;
2225 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm_data
->psm
, psm_data
->local_service
);
2226 connect_in_frame
= psm_data
->connect_in_frame
;
2230 bluetooth_uuid_t uuid
;
2233 uuid
.bt_uuid
= bt_uuid
;
2234 uuid
.data
[0] = bt_uuid
>> 8;
2235 uuid
.data
[1] = bt_uuid
& 0xFF;
2237 service_name
= val_to_str_ext_const(uuid
.bt_uuid
, &bluetooth_uuid_vals_ext
, "Unknown");
2240 if (strcmp(service_name
, "Unknown") == 0) {
2241 service_name
= val_to_str_const(psm
, psm_vals
, "Unknown");
2245 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_psm
, tvb
, offset
, 0, psm
);
2246 proto_item_set_generated(sub_item
);
2250 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_service
, tvb
, 0, 0, bt_uuid
);
2251 proto_item_set_generated(sub_item
);
2254 if (connect_in_frame
> 0) {
2255 sub_item
= proto_tree_add_uint(tree
, hf_btl2cap_connect_in_frame
, tvb
, 0, 0, connect_in_frame
);
2256 proto_item_set_generated(sub_item
);
2261 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (SCID: 0x%04x, DCID: 0x%04x, PSM: 0x%04x, Service: %s)", scid
, dcid
, psm
, service_name
);
2263 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (SCID: 0x%04x, DCID: 0x%04x, PSM: Unknown, Service: %s)", scid
, dcid
, service_name
);
2270 dissect_b_frame(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2271 proto_tree
*btl2cap_tree
, uint16_t cid
, uint16_t psm
,
2272 bool is_local_psm
, uint16_t length
, int offset
, btl2cap_data_t
*l2cap_data
)
2276 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), length
);
2278 col_append_str(pinfo
->cinfo
, COL_INFO
, "Connection oriented channel");
2281 proto_item
*psm_item
;
2283 bluetooth_uuid_t uuid
;
2285 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
) == NULL
) {
2286 uint16_t *value_data
;
2288 value_data
= wmem_new(wmem_file_scope(), uint16_t);
2291 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
, value_data
);
2294 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm
, is_local_psm
);
2297 uuid
.bt_uuid
= bt_uuid
;
2298 uuid
.data
[0] = bt_uuid
>> 8;
2299 uuid
.data
[1] = bt_uuid
& 0xFF;
2301 if (bt_uuid
&& p_get_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
) == NULL
) {
2304 value_data
= wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
));
2306 p_add_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
, value_data
);
2309 if (psm
< BTL2CAP_DYNAMIC_PSM_START
) {
2310 psm_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_psm
, tvb
, offset
, 0, psm
);
2313 psm_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_psm_dynamic
, tvb
, offset
, 0, psm
);
2315 proto_item_append_text(psm_item
, ": %s",
2316 val_to_str_ext_const(uuid
.bt_uuid
, &bluetooth_uuid_vals_ext
, "Unknown service"));
2318 proto_item_set_generated(psm_item
);
2320 /* call next dissector */
2321 if (!dissector_try_uint_with_data(l2cap_cid_dissector_table
, (uint32_t) cid
, next_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2322 if (!dissector_try_uint_with_data(l2cap_psm_dissector_table
, (uint32_t) psm
, next_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2323 /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2324 if (!dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
), next_tvb
, pinfo
, tree
, true,l2cap_data
)) {
2325 /* unknown protocol. declare as data */
2326 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
2330 offset
= tvb_captured_length(tvb
);
2332 if (!dissector_try_uint_with_data(l2cap_cid_dissector_table
, (uint32_t) cid
, next_tvb
, pinfo
, tree
, true, l2cap_data
))
2333 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
2334 offset
= tvb_captured_length(tvb
);
2339 /* An LE-frame is a PDU used in LE Credit Based Flow Control Mode. It
2340 * contains an SDU segment and additional protocol information, encapsulated
2341 * by a Basic L2CAP header.
2344 dissect_le_frame(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2345 proto_tree
*btl2cap_tree
, uint16_t cid
, uint16_t psm
, bool is_local_psm
,
2346 uint16_t length
, int offset
, config_data_t
*config_data
, btl2cap_data_t
*l2cap_data
,
2350 tvbuff_t
*new_tvb
= NULL
;
2351 bluetooth_uuid_t uuid
;
2352 btl2cap_frame_data_t
*btl2cap_frame_data
= NULL
;
2353 fragment_head
*frag_btl2cap_le_sdu
= NULL
;
2355 if ((!pinfo
->fd
->visited
) && (config_data
) && !is_retransmit
) {
2356 btl2cap_frame_data
= wmem_new0(wmem_file_scope(), btl2cap_frame_data_t
);
2357 if (config_data
->segmentation_started
== 1) {
2358 config_data
->segment_len_rem
= config_data
->segment_len_rem
- length
;
2359 if (config_data
->segment_len_rem
> 0) {
2360 btl2cap_frame_data
->more_fragments
= 1;
2362 btl2cap_frame_data
->more_fragments
= 0;
2363 config_data
->segmentation_started
= 0;
2364 config_data
->segment_len_rem
= 0;
2367 /* First Frame in this SDU, SDU length is present */
2368 uint16_t sdu_length
;
2370 sdu_length
= tvb_get_letohs(tvb
, offset
);
2371 btl2cap_frame_data
->first_fragment
= 1;
2372 if (sdu_length
== length
- 2) {
2373 /* Complete SDU no segmentation */
2374 btl2cap_frame_data
->more_fragments
= 0;
2375 config_data
->segmentation_started
= 0;
2376 config_data
->segment_len_rem
= 0;
2378 btl2cap_frame_data
->more_fragments
= 1;
2379 config_data
->segmentation_started
= 1;
2380 config_data
->segment_len_rem
= sdu_length
- (length
- 2);
2383 p_add_proto_data(wmem_file_scope(), pinfo
, proto_btl2cap
, pinfo
->curr_layer_num
, btl2cap_frame_data
);
2385 /* Not the first pass */
2386 btl2cap_frame_data
= (btl2cap_frame_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_btl2cap
, pinfo
->curr_layer_num
);
2389 col_append_str(pinfo
->cinfo
, COL_INFO
, "Connection oriented channel, LE Information frame");
2391 if (!btl2cap_frame_data
) {
2392 /* Without frame data we do not have enough information to dissect the packet */
2393 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
2394 return tvb_captured_length(tvb
);
2399 proto_item
*psm_item
;
2402 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
) == NULL
) {
2403 uint16_t *value_data
;
2405 value_data
= wmem_new(wmem_file_scope(), uint16_t);
2408 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
, value_data
);
2411 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm
, is_local_psm
);
2414 uuid
.bt_uuid
= bt_uuid
;
2415 uuid
.data
[0] = bt_uuid
>> 8;
2416 uuid
.data
[1] = bt_uuid
& 0xFF;
2418 if (bt_uuid
&& p_get_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
) == NULL
) {
2421 value_data
= wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
));
2423 p_add_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
, value_data
);
2426 if (psm
< BTL2CAP_DYNAMIC_PSM_START
) {
2427 psm_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_psm
, tvb
, offset
, 0, psm
);
2429 psm_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_psm_dynamic
, tvb
, offset
, 0, psm
);
2431 proto_item_append_text(psm_item
, ": %s",
2432 val_to_str_ext_const(uuid
.bt_uuid
, &bluetooth_uuid_vals_ext
, "Unknown service"));
2434 proto_item_set_generated(psm_item
);
2437 if (btl2cap_frame_data
->first_fragment
) {
2438 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_le_sdu_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2440 length
= length
- 2;
2442 pinfo
->fragmented
= true;
2443 frag_btl2cap_le_sdu
= fragment_add_seq_next(&btl2cap_le_sdu_reassembly_table
,
2446 cid
, /* uint32_t ID for fragments belonging together */
2448 length
, /* Fragment length */
2449 btl2cap_frame_data
->more_fragments
); /* More fragments */
2451 new_tvb
= process_reassembled_data(tvb
, offset
, pinfo
,
2453 frag_btl2cap_le_sdu
,
2454 &btl2cap_le_sdu_frag_items
,
2460 if (!dissector_try_uint_with_data(l2cap_cid_dissector_table
, (uint32_t)cid
, new_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2461 if (!dissector_try_uint_with_data(l2cap_psm_dissector_table
, (uint32_t)psm
, new_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2462 /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2463 if (!dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
), new_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2464 /* unknown protocol. declare as data */
2465 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
2470 /* call next dissector */
2471 if (!dissector_try_uint_with_data(l2cap_cid_dissector_table
, (uint32_t)cid
, new_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2472 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
2475 return tvb_captured_length(tvb
);
2478 col_set_str(pinfo
->cinfo
, COL_INFO
, "L2CAP LE Fragment");
2479 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
2481 return tvb_captured_length(tvb
);
2485 dissect_i_frame(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2486 proto_tree
*btl2cap_tree
, psm_data_t
*psm_data
, uint16_t length
,
2487 int offset
, config_data_t
*config_data
, btl2cap_data_t
*l2cap_data
)
2489 tvbuff_t
*next_tvb
= NULL
;
2490 uint16_t control
, segment
;
2492 proto_item
* ti_control
;
2493 proto_tree
* ti_control_subtree
;
2494 sdu_reassembly_t
*mfp
= NULL
;
2495 uint16_t psm
= (psm_data
? psm_data
->psm
: 0);
2497 control
= tvb_get_letohs(tvb
, offset
);
2498 segment
= (control
& 0xC000) >> 14;
2501 col_append_str(pinfo
->cinfo
, COL_INFO
, "[I] Unsegmented SDU");
2504 col_append_str(pinfo
->cinfo
, COL_INFO
, "[I] Start SDU");
2507 col_append_str(pinfo
->cinfo
, COL_INFO
, "[I] End SDU");
2510 col_append_str(pinfo
->cinfo
, COL_INFO
, "[I] Continuation SDU");
2513 ti_control
= proto_tree_add_none_format(btl2cap_tree
, hf_btl2cap_control
, tvb
,
2514 offset
, 2, "Control: %s reqseq:%d r:%d txseq:%d",
2515 val_to_str_const((control
& 0xC000) >> 14, control_sar_vals
, "unknown"),
2516 (control
& 0x3F00) >> 8,
2517 (control
& 0x0080) >> 7,
2518 (control
& 0x007E) >> 1);
2519 ti_control_subtree
= proto_item_add_subtree(ti_control
, ett_btl2cap_control
);
2520 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_sar
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2521 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_reqseq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2522 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_retransmissiondisable
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2523 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_txseq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2524 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2527 /*Segmented frames with SAR = start have an extra SDU length header field*/
2528 if (segment
== 0x01) {
2531 sdulen
= tvb_get_letohs(tvb
, offset
);
2532 pi
= proto_tree_add_item(btl2cap_tree
, hf_btl2cap_sdulength
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2536 /* Detect malformed data */
2539 expert_add_info_format(pinfo
, pi
, &ei_btl2cap_sdulength_bad
,
2540 "SDU length too short: %u", length
);
2541 THROW(ReportedBoundsError
);
2544 length
-= 6; /*Control, SDUlength, FCS*/
2546 if (sdulen
< length
) {
2548 expert_add_info_format(pinfo
, pi
, &ei_btl2cap_sdulength_bad
,
2549 "SDU length less than length of first packet (%u < %u)", sdulen
, length
);
2552 if (!pinfo
->fd
->visited
) {
2553 mfp
= wmem_new(wmem_file_scope(), sdu_reassembly_t
);
2554 mfp
->first_frame
= pinfo
->num
;
2555 mfp
->last_frame
= 0;
2556 mfp
->tot_len
= sdulen
;
2557 mfp
->reassembled
= (uint8_t *) wmem_alloc(wmem_file_scope(), sdulen
);
2558 tvb_memcpy(tvb
, mfp
->reassembled
, offset
, sdulen
);
2559 mfp
->cur_off
= sdulen
;
2560 wmem_tree_insert32(config_data
->start_fragments
, pinfo
->num
, mfp
);
2562 mfp
= (sdu_reassembly_t
*)wmem_tree_lookup32(config_data
->start_fragments
, pinfo
->num
);
2564 if (mfp
!= NULL
&& mfp
->last_frame
) {
2566 item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_reassembled_in
, tvb
, 0, 0, mfp
->last_frame
);
2567 proto_item_set_generated(item
);
2568 col_append_frame_number(pinfo
, COL_INFO
, "[Reassembled in #%u] ", mfp
->last_frame
);
2572 expert_add_info_format(pinfo
, btl2cap_tree
, &ei_btl2cap_length_bad
,
2573 "Control / FCS length too short: %u", length
);
2574 THROW(ReportedBoundsError
);
2576 length
-= 4; /*Control, FCS*/
2578 if (segment
== 0x02 || segment
== 0x03) {
2579 mfp
= (sdu_reassembly_t
*)wmem_tree_lookup32_le(config_data
->start_fragments
, pinfo
->num
);
2580 if (!pinfo
->fd
->visited
) {
2581 if (mfp
!= NULL
&& !mfp
->last_frame
&& (mfp
->tot_len
>=mfp
->cur_off
+ length
)) {
2582 tvb_memcpy(tvb
, mfp
->reassembled
+ mfp
->cur_off
, offset
, length
);
2583 mfp
->cur_off
+= length
;
2584 if (segment
== 0x02) {
2585 mfp
->last_frame
= pinfo
->num
;
2591 item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_continuation_to
, tvb
, 0, 0, mfp
->first_frame
);
2592 proto_item_set_generated(item
);
2593 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[Continuation to #%u] ", mfp
->first_frame
);
2596 if (segment
== 0x02 && mfp
!= NULL
&& mfp
->last_frame
== pinfo
->num
) {
2597 next_tvb
= tvb_new_child_real_data(tvb
, (uint8_t *)mfp
->reassembled
, mfp
->tot_len
, mfp
->tot_len
);
2598 add_new_data_source(pinfo
, next_tvb
, "Reassembled L2CAP");
2600 /*pass up to higher layer if we have a complete packet*/
2601 if (segment
== 0x00) {
2602 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
) - 2, length
);
2606 proto_item
*psm_item
;
2608 bluetooth_uuid_t uuid
;
2610 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
) == NULL
) {
2611 uint16_t *value_data
;
2613 value_data
= wmem_new(wmem_file_scope(), uint16_t);
2616 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
, value_data
);
2619 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm
, psm_data
->local_service
);
2622 uuid
.bt_uuid
= bt_uuid
;
2623 uuid
.data
[0] = bt_uuid
>> 8;
2624 uuid
.data
[1] = bt_uuid
& 0xFF;
2626 if (bt_uuid
&& p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
) == NULL
) {
2629 value_data
= wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
));
2631 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
, value_data
);
2634 if (psm
< BTL2CAP_DYNAMIC_PSM_START
) {
2635 psm_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_psm
, tvb
, offset
, 0, psm
);
2637 psm_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_psm_dynamic
, tvb
, offset
, 0, psm
);
2639 proto_item_append_text(psm_item
, " (%s)",
2640 val_to_str_ext_const(uuid
.bt_uuid
, &bluetooth_uuid_vals_ext
, "Unknown service"));
2642 proto_item_set_generated(psm_item
);
2644 /* call next dissector */
2645 if (!dissector_try_uint_with_data(l2cap_psm_dissector_table
, (uint32_t) psm
, next_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2646 /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2647 if (!dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
), next_tvb
, pinfo
, tree
, true,l2cap_data
)) {
2648 /* unknown protocol. declare as data */
2649 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, next_tvb
, 0, tvb_reported_length(next_tvb
), ENC_NA
);
2654 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, next_tvb
, 0, tvb_reported_length(next_tvb
), ENC_NA
);
2657 offset
+= tvb_reported_length_remaining(tvb
, offset
) - 2;
2658 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_fcs
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2664 dissect_s_frame(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, proto_tree
*btl2cap_tree
,
2665 uint16_t psm _U_
, uint16_t length _U_
, int offset
, config_data_t
*config_data _U_
)
2667 proto_item
*ti_control
;
2668 proto_tree
*ti_control_subtree
;
2671 control
= tvb_get_letohs(tvb
, offset
);
2673 switch ((control
& 0x000C) >> 2) {
2675 col_append_str(pinfo
->cinfo
, COL_INFO
, "[S] Receiver Ready");
2678 col_append_str(pinfo
->cinfo
, COL_INFO
, "[S] Reject");
2681 col_append_str(pinfo
->cinfo
, COL_INFO
, "[S] Unknown supervisory frame");
2685 ti_control
= proto_tree_add_none_format(btl2cap_tree
, hf_btl2cap_control
, tvb
,
2686 offset
, 2, "Control: %s reqseq:%d r:%d",
2687 val_to_str_const((control
& 0x000C) >> 2, control_supervisory_vals
, "unknown"),
2688 (control
& 0x3F00) >> 8,
2689 (control
& 0x0080) >> 7);
2690 ti_control_subtree
= proto_item_add_subtree(ti_control
, ett_btl2cap_control
);
2692 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_reqseq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2693 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_retransmissiondisable
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2694 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_supervisory
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2695 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2698 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_fcs
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2705 dissect_btl2cap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
2709 proto_tree
*btl2cap_tree
;
2710 proto_item
*length_item
;
2715 tvbuff_t
*next_tvb
= NULL
;
2716 psm_data_t
*psm_data
;
2717 bthci_acl_data_t
*acl_data
;
2718 btl2cap_data_t
*l2cap_data
;
2719 bool dir_in_col
= true;
2721 acl_data
= (bthci_acl_data_t
*) data
;
2723 if ((acl_data
) && (acl_data
->is_btle
)) {
2726 ti
= proto_tree_add_item(tree
, proto_btl2cap
, tvb
, offset
, -1, ENC_NA
);
2727 btl2cap_tree
= proto_item_add_subtree(ti
, ett_btl2cap
);
2729 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "L2CAP");
2732 switch (pinfo
->p2p_dir
) {
2734 col_set_str(pinfo
->cinfo
, COL_INFO
, "Sent ");
2737 col_set_str(pinfo
->cinfo
, COL_INFO
, "Rcvd ");
2740 col_set_str(pinfo
->cinfo
, COL_INFO
, "UnknownDirection ");
2744 col_clear(pinfo
->cinfo
, COL_INFO
);
2747 length
= tvb_get_letohs(tvb
, offset
);
2748 length_item
= proto_tree_add_item(btl2cap_tree
, hf_btl2cap_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2749 if (tvb_captured_length_remaining(tvb
, offset
) < length
) {
2750 expert_add_info(pinfo
, length_item
, &ei_btl2cap_length_bad
);
2751 /* Try to dissect as more as possible */
2752 length
= tvb_captured_length_remaining(tvb
, offset
) - 4;
2757 cid
= tvb_get_letohs(tvb
, offset
);
2758 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_cid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2759 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_CID
) == NULL
) {
2760 uint16_t *value_data
;
2762 value_data
= wmem_new(wmem_file_scope(), uint16_t);
2765 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_CID
, value_data
);
2769 l2cap_data
= wmem_new(pinfo
->pool
, btl2cap_data_t
);
2771 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
2772 l2cap_data
->interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
2774 l2cap_data
->interface_id
= HCI_INTERFACE_DEFAULT
;
2776 l2cap_data
->adapter_id
= acl_data
->adapter_id
;
2777 l2cap_data
->adapter_disconnect_in_frame
= acl_data
->adapter_disconnect_in_frame
;
2778 l2cap_data
->chandle
= acl_data
->chandle
;
2779 l2cap_data
->hci_disconnect_in_frame
= acl_data
->disconnect_in_frame
;
2780 l2cap_data
->remote_bd_addr_oui
= acl_data
->remote_bd_addr_oui
;
2781 l2cap_data
->remote_bd_addr_id
= acl_data
->remote_bd_addr_id
;
2783 l2cap_data
->adapter_id
= HCI_ADAPTER_DEFAULT
;
2784 l2cap_data
->adapter_disconnect_in_frame
= &bluetooth_max_disconnect_in_frame
;
2785 l2cap_data
->chandle
= 0;
2786 l2cap_data
->hci_disconnect_in_frame
= &bluetooth_max_disconnect_in_frame
;
2787 l2cap_data
->remote_bd_addr_oui
= 0;
2788 l2cap_data
->remote_bd_addr_id
= 0;
2791 l2cap_data
->disconnect_in_frame
= &bluetooth_max_disconnect_in_frame
;
2793 l2cap_data
->cid
= cid
;
2794 l2cap_data
->local_cid
= BTL2CAP_UNKNOWN_CID
;
2795 l2cap_data
->remote_cid
= BTL2CAP_UNKNOWN_CID
;
2796 l2cap_data
->is_local_psm
= false;
2797 l2cap_data
->psm
= 0;
2799 if (cid
== BTL2CAP_FIXED_CID_SIGNAL
|| cid
== BTL2CAP_FIXED_CID_LE_SIGNAL
) {
2800 /* This is a command packet*/
2801 while (offset
< length
+ 4) {
2803 proto_item
*ti_command
;
2804 proto_tree
*btl2cap_cmd_tree
;
2807 uint16_t cmd_length
;
2808 const char *cmd_str
;
2810 ti_command
= proto_tree_add_none_format(btl2cap_tree
,
2811 hf_btl2cap_command
, tvb
,
2814 btl2cap_cmd_tree
= proto_item_add_subtree(ti_command
, ett_btl2cap_cmd
);
2816 cmd_code
= tvb_get_uint8(tvb
, offset
);
2817 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_cmd_code
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2820 cmd_ident
= tvb_get_uint8(tvb
, offset
);
2821 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_cmd_ident
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2824 cmd_length
= tvb_get_letohs(tvb
, offset
);
2825 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_cmd_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2826 proto_item_set_len(ti_command
, cmd_length
+ 4);
2829 cmd_str
= val_to_str_const(cmd_code
, command_code_vals
, "Unknown command");
2830 proto_item_append_text(ti_command
, "%s", cmd_str
);
2831 col_append_str(pinfo
->cinfo
, COL_INFO
, cmd_str
);
2834 case 0x01: /* Command Reject */
2835 offset
= dissect_comrej(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2838 case 0x02: /* Connection Request */
2839 offset
= dissect_connrequest(tvb
, offset
, pinfo
, btl2cap_tree
, btl2cap_cmd_tree
, false, acl_data
, l2cap_data
);
2842 case 0x03: /* Connection Response */
2843 offset
= dissect_connresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
, acl_data
);
2846 case 0x04: /* Configure Request */
2847 offset
= dissect_configrequest(tvb
, offset
, pinfo
, btl2cap_cmd_tree
, cmd_length
, acl_data
);
2850 case 0x05: /* Configure Response */
2851 offset
= dissect_configresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
, cmd_length
, acl_data
);
2854 case 0x06: /* Disconnect Request */
2855 offset
= dissect_disconnrequestresponse(tvb
, offset
, pinfo
, btl2cap_tree
, btl2cap_cmd_tree
, acl_data
, l2cap_data
, true);
2858 case 0x07: /* Disconnect Response */
2859 offset
= dissect_disconnrequestresponse(tvb
, offset
, pinfo
, btl2cap_tree
, btl2cap_cmd_tree
, acl_data
, l2cap_data
, false);
2862 case 0x08: /* Echo Request */
2863 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_data
, tvb
, offset
, -1, ENC_NA
);
2864 offset
= tvb_reported_length(tvb
);
2867 case 0x09: /* Echo Response */
2868 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_data
, tvb
, offset
, -1, ENC_NA
);
2869 offset
= tvb_reported_length(tvb
);
2872 case 0x0a: /* Information Request */
2873 offset
= dissect_inforequest(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2876 case 0x0b: /* Information Response */
2877 offset
= dissect_inforesponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2880 case 0x0c: /* Create Channel Request */
2881 offset
= dissect_connrequest(tvb
, offset
, pinfo
, btl2cap_tree
, btl2cap_cmd_tree
, true, acl_data
, l2cap_data
);
2884 case 0x0d: /* Create Channel Response */
2885 offset
= dissect_chanresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
, acl_data
);
2888 case 0x0e: /* Move Channel Request */
2889 offset
= dissect_movechanrequest(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2892 case 0x0f: /* Move Channel Response */
2893 offset
= dissect_movechanresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2896 case 0x10: /* Move Channel Confirmation */
2897 offset
= dissect_movechanconfirmation(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2900 case 0x11: /* Move Channel Confirmation Response */
2901 offset
= dissect_movechanconfirmationresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2904 case 0x12: /* Connection Parameter Request */
2905 offset
= dissect_connparamrequest(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2908 case 0x13: /* Connection Parameter Response */
2909 offset
= dissect_connparamresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
);
2912 case 0x14: /* LE Credit Based Connection Request */
2913 offset
= dissect_le_credit_based_connrequest(tvb
, offset
, pinfo
, btl2cap_tree
, btl2cap_cmd_tree
, cid
, cmd_ident
, acl_data
, l2cap_data
);
2915 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (CID: %04x, Initial Credits: %u)",
2916 tvb_get_letohs(tvb
, offset
- 8), tvb_get_letohs(tvb
, offset
- 2));
2919 case 0x15: /* LE Credit Based Connection Response */
2920 offset
= dissect_le_credit_based_connresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
, cid
, cmd_ident
, acl_data
);
2922 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (CID: %04x, Initial Credits: %u)",
2923 tvb_get_letohs(tvb
, offset
- 10), tvb_get_letohs(tvb
, offset
- 4));
2926 case 0x16: /* LE Flow Control Credit */
2927 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_cid
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2930 proto_tree_add_item(btl2cap_cmd_tree
, hf_btl2cap_credits
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2933 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (CID: %04x, Credits: %u)",
2934 tvb_get_letohs(tvb
, offset
- 4), tvb_get_letohs(tvb
, offset
- 2));
2937 case 0x17: /* L2CAP Credit Based Connection Request */
2938 offset
= dissect_l2cap_credit_based_connrequest(tvb
, offset
, pinfo
, btl2cap_tree
, btl2cap_cmd_tree
, cid
, cmd_ident
, cmd_length
, acl_data
, l2cap_data
);
2941 case 0x18: /* L2CAP Credit Based Connection Response */
2942 offset
= dissect_l2cap_credit_based_connresponse(tvb
, offset
, pinfo
, btl2cap_cmd_tree
, cid
, cmd_ident
, cmd_length
, acl_data
);
2946 proto_tree_add_expert(btl2cap_cmd_tree
, pinfo
, &ei_btl2cap_unknown_command_code
, tvb
, offset
, -1);
2947 offset
+= tvb_reported_length_remaining(tvb
, offset
);
2952 else if (cid
== BTL2CAP_FIXED_CID_CONNLESS
) { /* Connectionless reception channel */
2953 col_append_str(pinfo
->cinfo
, COL_INFO
, "Connectionless reception channel");
2955 psm
= tvb_get_letohs(tvb
, offset
);
2956 if (pinfo
->p2p_dir
== P2P_DIR_RECV
) {
2957 l2cap_data
->local_cid
= cid
;
2958 l2cap_data
->remote_cid
= BTL2CAP_UNKNOWN_CID
;
2960 l2cap_data
->local_cid
= BTL2CAP_UNKNOWN_CID
;
2961 l2cap_data
->remote_cid
= cid
;
2963 l2cap_data
->psm
= psm
;
2964 l2cap_data
->disconnect_in_frame
= &bluetooth_max_disconnect_in_frame
;
2966 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
) == NULL
) {
2967 uint16_t *value_data
;
2969 value_data
= wmem_new(wmem_file_scope(), uint16_t);
2972 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btl2cap
, PROTO_DATA_BTL2CAP_PSM
, value_data
);
2975 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_psm
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2978 /* 3.2 "For G-frames, the PDU length equals the payload size plus the
2979 * number of octets in the PSM."
2980 * Substract the PSM length. (Yes, technically the PSM is "at least"
2981 * two octets in length, Little Endian where only the MSB (== Last)
2982 * has least significant bit 0, and that's used to detect the size.
2983 * We only use 2 octets everywhere in this dissector, though.)
2986 expert_add_info_format(pinfo
, length_item
, &ei_btl2cap_length_bad
,
2987 "PDU length too short: %u (should include PSM)", length
);
2988 THROW(ReportedBoundsError
);
2991 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
);
2993 /* call next dissector */
2994 if (!dissector_try_uint_with_data(l2cap_psm_dissector_table
, (uint32_t) psm
, next_tvb
, pinfo
, tree
, true, l2cap_data
)) {
2995 /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2997 bluetooth_uuid_t uuid
;
2999 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm
, (pinfo
->p2p_dir
== P2P_DIR_RECV
) ? true : false );
3002 uuid
.bt_uuid
= bt_uuid
;
3003 uuid
.data
[0] = bt_uuid
>> 8;
3004 uuid
.data
[1] = bt_uuid
& 0xFF;
3006 if (bt_uuid
&& p_get_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
) == NULL
) {
3009 value_data
= wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
));
3011 p_add_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
, value_data
);
3014 if (!dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
), next_tvb
, pinfo
, tree
, true, l2cap_data
)) {
3015 /* unknown protocol. declare as data */
3016 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
3018 offset
= tvb_captured_length(tvb
);
3021 else if (cid
<= BTL2CAP_FIXED_CID_LAST
) {
3022 if (cid
== BTL2CAP_FIXED_CID_AMP_MAN
) {
3023 control
= tvb_get_letohs(tvb
, offset
);
3024 if (control
& 0x1) {
3025 offset
= dissect_s_frame(tvb
, pinfo
, tree
, btl2cap_tree
, 0 /* unused */, length
, offset
, NULL
/* unused */);
3027 proto_item
* ti_control
;
3028 proto_tree
* ti_control_subtree
;
3030 ti_control
= proto_tree_add_none_format(btl2cap_tree
, hf_btl2cap_control
, tvb
,
3031 offset
, 2, "Control: %s reqseq:%d r:%d txseq:%d",
3032 val_to_str_const((control
& 0xC000) >> 14, control_sar_vals
, "unknown"),
3033 (control
& 0x3F00) >> 8,
3034 (control
& 0x0080) >> 7,
3035 (control
& 0x007E) >> 1);
3036 ti_control_subtree
= proto_item_add_subtree(ti_control
, ett_btl2cap_control
);
3037 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_sar
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3038 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_reqseq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3039 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_retransmissiondisable
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3040 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_txseq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3041 proto_tree_add_item(ti_control_subtree
, hf_btl2cap_control_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3043 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_fcs
, tvb
, tvb_reported_length(tvb
) - 2, 2, ENC_LITTLE_ENDIAN
);
3045 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
)-2, length
);
3049 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), length
);
3051 /* call next dissector */
3052 if (next_tvb
&& !dissector_try_uint_with_data(l2cap_cid_dissector_table
, (uint32_t) cid
,
3053 next_tvb
, pinfo
, tree
, true, l2cap_data
)) {
3054 /* unknown protocol. declare as data */
3055 proto_tree_add_item(btl2cap_tree
, hf_btl2cap_payload
, tvb
, offset
, length
, ENC_NA
);
3057 offset
= tvb_captured_length(tvb
);
3059 else /* if (cid > BTL2CAP_FIXED_CID_LAST) */ { /* Connection oriented channel */
3060 wmem_tree_key_t key
[6];
3061 uint32_t k_interface_id
;
3062 uint32_t k_adapter_id
;
3065 uint32_t k_frame_number
;
3066 uint32_t interface_id
;
3067 uint32_t adapter_id
;
3071 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
3072 interface_id
= pinfo
->rec
->rec_header
.packet_header
.interface_id
;
3074 interface_id
= HCI_INTERFACE_DEFAULT
;
3075 adapter_id
= (acl_data
) ? acl_data
->adapter_id
: HCI_ADAPTER_DEFAULT
;
3076 chandle
= (acl_data
) ? acl_data
->chandle
: 0;
3077 key_cid
= cid
| ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x00000000 : 0x80000000);
3079 k_interface_id
= interface_id
;
3080 k_adapter_id
= adapter_id
;
3081 k_chandle
= chandle
;
3083 k_frame_number
= pinfo
->num
;
3086 key
[0].key
= &k_interface_id
;
3088 key
[1].key
= &k_adapter_id
;
3090 key
[2].key
= &k_chandle
;
3092 key
[3].key
= &k_cid
;
3094 key
[4].key
= &k_frame_number
;
3098 psm_data
= (psm_data_t
*)wmem_tree_lookup32_array_le(cid_to_psm_table
, key
);
3100 psm_data
->interface_id
== interface_id
&&
3101 psm_data
->adapter_id
== adapter_id
&&
3102 psm_data
->chandle
== chandle
&&
3103 (psm_data
->local_cid
== key_cid
||
3104 psm_data
->remote_cid
== key_cid
) &&
3105 psm_data
->disconnect_in_frame
> pinfo
->num
)
3107 config_data_t
*config_data
;
3108 proto_item
*sub_item
;
3111 psm
= psm_data
->psm
;
3112 l2cap_data
->local_cid
= psm_data
->local_cid
;
3113 l2cap_data
->remote_cid
= psm_data
->remote_cid
;
3114 l2cap_data
->psm
= psm
;
3115 l2cap_data
->is_local_psm
= psm_data
->local_service
;
3116 l2cap_data
->disconnect_in_frame
= &psm_data
->disconnect_in_frame
;
3118 if (pinfo
->p2p_dir
== P2P_DIR_RECV
)
3119 config_data
= &(psm_data
->in
);
3121 config_data
= &(psm_data
->out
);
3123 if (psm_data
->connect_in_frame
> 0 && psm_data
->connect_in_frame
< UINT32_MAX
) {
3124 sub_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_connect_in_frame
, tvb
, 0, 0, psm_data
->connect_in_frame
);
3125 proto_item_set_generated(sub_item
);
3128 if (psm_data
->disconnect_in_frame
> 0 && psm_data
->disconnect_in_frame
< UINT32_MAX
) {
3129 sub_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_disconnect_in_frame
, tvb
, 0, 0, psm_data
->disconnect_in_frame
);
3130 proto_item_set_generated(sub_item
);
3133 bt_uuid
= get_service_uuid(pinfo
, l2cap_data
, psm_data
->psm
, psm_data
->local_service
);
3135 sub_item
= proto_tree_add_uint(btl2cap_tree
, hf_btl2cap_service
, tvb
, 0, 0, bt_uuid
);
3136 proto_item_set_generated(sub_item
);
3139 if (config_data
->mode
== L2CAP_BASIC_MODE
) {
3140 offset
= dissect_b_frame(tvb
, pinfo
, tree
, btl2cap_tree
, cid
, psm
, psm_data
->local_service
, length
, offset
, l2cap_data
);
3141 } else if (config_data
->mode
== L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
) {
3142 bool is_retransmit
= false;
3144 is_retransmit
= acl_data
->is_btle_retransmit
;
3146 offset
= dissect_le_frame(tvb
, pinfo
, tree
, btl2cap_tree
, cid
, psm
, psm_data
->local_service
, length
, offset
, config_data
, l2cap_data
, is_retransmit
);
3148 control
= tvb_get_letohs(tvb
, offset
);
3149 if (control
& 0x1) {
3150 offset
= dissect_s_frame(tvb
, pinfo
, tree
, btl2cap_tree
, psm
, length
, offset
, config_data
);
3152 offset
= dissect_i_frame(tvb
, pinfo
, tree
, btl2cap_tree
, psm_data
, length
, offset
, config_data
, l2cap_data
);
3157 offset
= dissect_b_frame(tvb
, pinfo
, tree
, btl2cap_tree
, cid
, psm
, false, length
, offset
, l2cap_data
);
3164 /* Register the protocol with Wireshark */
3166 proto_register_btl2cap(void)
3168 expert_module_t
*expert_btl2cap
;
3169 /* Setup list of header fields See Section 1.6.1 for details*/
3170 static hf_register_info hf
[] = {
3171 { &hf_btl2cap_length
,
3172 { "Length", "btl2cap.length",
3173 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3174 "L2CAP Payload Length", HFILL
}
3177 { "CID", "btl2cap.cid",
3178 FT_UINT16
, BASE_HEX
| BASE_RANGE_STRING
, RVALS(cid_rvals
), 0x0,
3179 "L2CAP Channel Identifier", HFILL
}
3181 { &hf_btl2cap_payload
,
3182 { "Payload", "btl2cap.payload",
3183 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3184 "L2CAP Payload", HFILL
}
3186 { &hf_btl2cap_command
,
3187 { "Command", "btl2cap.command",
3188 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3189 "L2CAP Command", HFILL
}
3191 { &hf_btl2cap_cmd_code
,
3192 { "Command Code", "btl2cap.cmd_code",
3193 FT_UINT8
, BASE_HEX
, VALS(command_code_vals
), 0x0,
3194 "L2CAP Command Code", HFILL
}
3196 { &hf_btl2cap_cmd_ident
,
3197 { "Command Identifier", "btl2cap.cmd_ident",
3198 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3199 "L2CAP Command Identifier", HFILL
}
3201 { &hf_btl2cap_cmd_length
,
3202 { "Command Length", "btl2cap.cmd_length",
3203 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3204 "L2CAP Command Length", HFILL
}
3206 { &hf_btl2cap_cmd_data
,
3207 { "Command Data", "btl2cap.cmd_data",
3208 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3209 "L2CAP Command Data", HFILL
}
3212 { "PSM", "btl2cap.psm",
3213 FT_UINT16
, BASE_HEX
, VALS(psm_vals
), 0x0,
3214 "Protocol/Service Multiplexer", HFILL
}
3216 { &hf_btl2cap_psm_dynamic
,
3217 { "Dynamic PSM", "btl2cap.psm",
3218 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
3219 "Dynamic Protocol/Service Multiplexer", HFILL
}
3222 { "Source CID", "btl2cap.scid",
3223 FT_UINT16
, BASE_HEX
| BASE_RANGE_STRING
, RVALS(cid_rvals
), 0x0,
3224 "Source Channel Identifier", HFILL
}
3227 { "Destination CID", "btl2cap.dcid",
3228 FT_UINT16
, BASE_HEX
| BASE_RANGE_STRING
, RVALS(cid_rvals
), 0x0,
3229 "Destination Channel Identifier", HFILL
}
3232 { "Initiator CID", "btl2cap.icid",
3233 FT_UINT16
, BASE_HEX
| BASE_RANGE_STRING
, RVALS(cid_rvals
), 0x0,
3234 "Initiator Channel Identifier", HFILL
}
3236 { &hf_btl2cap_controller
,
3237 { "Controller ID", "btl2cap.ctrl_id",
3238 FT_UINT8
, BASE_DEC
, VALS(ctrl_id_code_vals
), 0x0,
3241 { &hf_btl2cap_dcontroller
,
3242 { "Controller ID", "btl2cap.dctrl_id",
3243 FT_UINT8
, BASE_DEC
, VALS(ctrl_id_code_vals
), 0x0,
3244 "Destination Controller ID", HFILL
}
3246 { &hf_btl2cap_result
,
3247 { "Result", "btl2cap.result",
3248 FT_UINT16
, BASE_HEX
, VALS(result_vals
), 0x0,
3251 { &hf_btl2cap_move_result
,
3252 { "Move Result", "btl2cap.move_result",
3253 FT_UINT16
, BASE_HEX
, VALS(move_result_vals
), 0x0,
3256 { &hf_btl2cap_move_confirmation_result
,
3257 { "Move Result", "btl2cap.move_result",
3258 FT_UINT16
, BASE_HEX
, VALS(move_result_confirmation_vals
), 0x0,
3261 { &hf_btl2cap_status
,
3262 { "Status", "btl2cap.status",
3263 FT_UINT16
, BASE_HEX
, VALS(status_vals
), 0x0,
3266 { &hf_btl2cap_rej_reason
,
3267 { "Reason", "btl2cap.rej_reason",
3268 FT_UINT16
, BASE_HEX
, VALS(reason_vals
), 0x0,
3271 { &hf_btl2cap_sig_mtu
,
3272 { "Maximum Signalling MTU", "btl2cap.sig_mtu",
3273 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3276 { &hf_btl2cap_info_mtu
,
3277 { "Remote Entity MTU", "btl2cap.info_mtu",
3278 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3279 "Remote entity acceptable connectionless MTU", HFILL
}
3281 { &hf_btl2cap_info_flowcontrol
,
3282 { "Flow Control Mode", "btl2cap.info_flowcontrol",
3283 FT_UINT32
, BASE_DEC
, NULL
, 0x01,
3284 "Flow Control mode support", HFILL
}
3286 { &hf_btl2cap_info_retransmission
,
3287 { "Retransmission Mode", "btl2cap.info_retransmission",
3288 FT_UINT32
, BASE_DEC
, NULL
, 0x02,
3289 "Retransmission mode support", HFILL
}
3291 { &hf_btl2cap_info_bidirqos
,
3292 { "Bi-Directional QOS", "btl2cap.info_bidirqos",
3293 FT_UINT32
, BASE_DEC
, NULL
, 0x04,
3294 "Bi-Directional QOS support", HFILL
}
3296 { &hf_btl2cap_info_enh_retransmission
,
3297 { "Enhanced Retransmission Mode", "btl2cap.info_enh_retransmission",
3298 FT_UINT32
, BASE_DEC
, NULL
, 0x08,
3299 "Enhanced Retransmission mode support", HFILL
}
3301 { &hf_btl2cap_info_streaming
,
3302 { "Streaming Mode", "btl2cap.info_streaming",
3303 FT_UINT32
, BASE_DEC
, NULL
, 0x10,
3304 "Streaming mode support", HFILL
}
3306 { &hf_btl2cap_info_fcs
,
3307 { "FCS", "btl2cap.info_fcs",
3308 FT_UINT32
, BASE_DEC
, NULL
, 0x20,
3309 "FCS support", HFILL
}
3311 { &hf_btl2cap_info_flow_spec
,
3312 { "Extended Flow Specification for BR/EDR", "btl2cap.info_flow_spec",
3313 FT_UINT32
, BASE_DEC
, NULL
, 0x40,
3314 "Extended Flow Specification for BR/EDR support", HFILL
}
3316 { &hf_btl2cap_info_fixedchan
,
3317 { "Fixed Channels", "btl2cap.info_fixedchan",
3318 FT_UINT32
, BASE_DEC
, NULL
, 0x80,
3319 "Fixed Channels support", HFILL
}
3321 { &hf_btl2cap_info_window
,
3322 { "Extended Window Size", "btl2cap.info_window",
3323 FT_UINT32
, BASE_DEC
, NULL
, 0x0100,
3324 "Extended Window Size support", HFILL
}
3326 { &hf_btl2cap_info_unicast
,
3327 { "Unicast Connectionless Data Reception", "btl2cap.info_unicast",
3328 FT_UINT32
, BASE_DEC
, NULL
, 0x0200,
3329 "Unicast Connectionless Data Reception support", HFILL
}
3331 { &hf_btl2cap_info_fixedchans
,
3332 { "Fixed Channels", "btl2cap.info_fixedchans",
3333 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3336 { &hf_btl2cap_info_fixedchans_null
,
3337 { "Null identifier", "btl2cap.info_fixedchans_null",
3338 FT_UINT32
, BASE_DEC
, NULL
, 0x1,
3341 { &hf_btl2cap_info_fixedchans_signal
,
3342 { "L2CAP signaling channel", "btl2cap.info_fixedchans_signal",
3343 FT_UINT32
, BASE_DEC
, NULL
, 0x2,
3346 { &hf_btl2cap_info_fixedchans_connless
,
3347 { "Connectionless reception", "btl2cap.info_fixedchans_connless",
3348 FT_UINT32
, BASE_DEC
, NULL
, 0x4,
3351 { &hf_btl2cap_info_fixedchans_amp_man
,
3352 { "AMP Manager protocol", "btl2cap.info_fixedchans_amp_man",
3353 FT_UINT32
, BASE_DEC
, NULL
, 0x8,
3356 { &hf_btl2cap_info_fixedchans_rfu
,
3357 { "Reserved for future use", "btl2cap.info_fixedchans_rfu",
3358 FT_UINT32
, BASE_DEC
, NULL
, 0x00000070,
3361 { &hf_btl2cap_info_fixedchans_smp
,
3362 { "BR/EDR Security Manager", "btl2cap.info_fixedchans_smp",
3363 FT_UINT32
, BASE_DEC
, NULL
, 0x00000080,
3366 { &hf_btl2cap_info_fixedchans_amp_test
,
3367 { "AMP Test Manager", "btl2cap.info_fixedchans_amp_test",
3368 FT_UINT32
, BASE_DEC
, NULL
, 0x80000000,
3371 { &hf_btl2cap_info_type
,
3372 { "Information Type", "btl2cap.info_type",
3373 FT_UINT16
, BASE_HEX
, VALS(info_type_vals
), 0x0,
3374 "Type of implementation-specific information", HFILL
}
3376 { &hf_btl2cap_info_result
,
3377 { "Result", "btl2cap.info_result",
3378 FT_UINT16
, BASE_HEX
, VALS(info_result_vals
), 0x0,
3379 "Information about the success of the request", HFILL
}
3381 { &hf_btl2cap_info_extfeatures
,
3382 { "Extended Features", "btl2cap.info_extfeatures",
3383 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3384 "Extended Features Mask", HFILL
}
3386 { &hf_btl2cap_flags_reserved
,
3387 { "Reserved", "btl2cap.flags.reserved",
3388 FT_UINT16
, BASE_HEX
, NULL
, 0xFFFE,
3391 { &hf_btl2cap_flags_continuation
,
3392 { "Continuation Flag", "btl2cap.flags.continuation",
3393 FT_BOOLEAN
, 16, NULL
, 0x0001,
3396 { &hf_btl2cap_configuration_result
,
3397 { "Result", "btl2cap.conf_result",
3398 FT_UINT16
, BASE_HEX
, VALS(configuration_result_vals
), 0x0,
3399 "Configuration Result", HFILL
}
3401 { &hf_btl2cap_option_type
,
3402 { "Type", "btl2cap.option_type",
3403 FT_UINT8
, BASE_HEX
, VALS(option_type_vals
), 0x0,
3404 "Type of option", HFILL
}
3406 { &hf_btl2cap_option_length
,
3407 { "Length", "btl2cap.option_length",
3408 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3409 "Number of octets in option payload", HFILL
}
3411 { &hf_btl2cap_option_mtu
,
3412 { "MTU", "btl2cap.option_mtu",
3413 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3414 "Maximum Transmission Unit", HFILL
}
3416 { &hf_btl2cap_option_flushTO
,
3417 { "Flush Timeout (ms)", "btl2cap.option_flushto",
3418 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3419 "Flush Timeout in milliseconds", HFILL
}
3421 { &hf_btl2cap_option_flush_to_us
,
3422 { "Flush Timeout (us)", "btl2cap.option_flushto",
3423 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3424 "Flush Timeout (microseconds)", HFILL
}
3426 { &hf_btl2cap_option_sdu_size
,
3427 { "Maximum SDU Size", "btl2cap.option_sdu_size",
3428 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3431 { &hf_btl2cap_option_sdu_arrival_time
,
3432 { "SDU Inter-arrival Time (us)", "btl2cap.option_sdu_arrival_time",
3433 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3434 "SDU Inter-arrival Time (microseconds)", HFILL
}
3436 { &hf_btl2cap_option_identifier
,
3437 { "Identifier", "btl2cap.option_ident",
3438 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3439 "Flow Specification Identifier", HFILL
}
3441 { &hf_btl2cap_option_access_latency
,
3442 { "Access Latency (us)", "btl2cap.option_access_latency",
3443 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3444 "Access Latency (microseconds)", HFILL
}
3446 { &hf_btl2cap_option_flags
,
3447 { "Flags", "btl2cap.option_flags",
3448 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3449 "Flags - must be set to 0 (Reserved for future use)", HFILL
}
3451 { &hf_btl2cap_option_service_type
,
3452 { "Service Type", "btl2cap.option_servicetype",
3453 FT_UINT8
, BASE_HEX
, VALS(option_servicetype_vals
), 0x0,
3454 "Level of service required", HFILL
}
3456 { &hf_btl2cap_option_tokenrate
,
3457 { "Token Rate (bytes/s)", "btl2cap.option_tokenrate",
3458 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3459 "Rate at which traffic credits are granted (bytes/s)", HFILL
}
3461 { &hf_btl2cap_option_tokenbucketsize
,
3462 { "Token Bucket Size (bytes)", "btl2cap.option_tokenbsize",
3463 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3464 "Size of the token bucket (bytes)", HFILL
}
3466 { &hf_btl2cap_option_peakbandwidth
,
3467 { "Peak Bandwidth (bytes/s)", "btl2cap.option_peakbandwidth",
3468 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3469 "Limit how fast packets may be sent (bytes/s)", HFILL
}
3471 { &hf_btl2cap_option_latency
,
3472 { "Latency (microseconds)", "btl2cap.option_latency",
3473 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3474 "Maximal acceptable delay (microseconds)", HFILL
}
3476 { &hf_btl2cap_option_delayvariation
,
3477 { "Delay Variation (microseconds)", "btl2cap.option_delayvar",
3478 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3479 "Difference between maximum and minimum delay (microseconds)", HFILL
}
3481 { &hf_btl2cap_option_retransmissionmode
,
3482 { "Mode", "btl2cap.retransmissionmode",
3483 FT_UINT8
, BASE_HEX
, VALS(option_retransmissionmode_vals
), 0x0,
3484 "Retransmission/Flow Control mode", HFILL
}
3486 { &hf_btl2cap_option_txwindow
,
3487 { "TxWindow", "btl2cap.txwindow",
3488 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3489 "Retransmission window size", HFILL
}
3491 { &hf_btl2cap_option_maxtransmit
,
3492 { "MaxTransmit", "btl2cap.maxtransmit",
3493 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3494 "Maximum I-frame retransmissions", HFILL
}
3496 { &hf_btl2cap_option_retransmittimeout
,
3497 { "Retransmit timeout (ms)", "btl2cap.retransmittimeout",
3498 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3499 "Retransmission timeout (milliseconds)", HFILL
}
3501 { &hf_btl2cap_option_monitortimeout
,
3502 { "Monitor Timeout (ms)", "btl2cap.monitortimeout",
3503 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3504 "S-frame transmission interval (milliseconds)", HFILL
}
3506 { &hf_btl2cap_option_mps
,
3507 { "MPS", "btl2cap.mps",
3508 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3509 "Maximum PDU Payload Size", HFILL
}
3511 { &hf_btl2cap_option_fcs
,
3512 { "FCS", "btl2cap.option_fcs",
3513 FT_UINT16
, BASE_HEX
, VALS(option_fcs_vals
), 0x0,
3514 "Frame Check Sequence", HFILL
}
3516 { &hf_btl2cap_option_window
,
3517 { "Extended Window Size", "btl2cap.option_window",
3518 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3521 { &hf_btl2cap_option
,
3522 { "Configuration Parameter Option", "btl2cap.conf_param_option",
3523 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3526 { &hf_btl2cap_control_sar
,
3527 { "Segmentation and reassembly", "btl2cap.control_sar",
3528 FT_UINT16
, BASE_HEX
, VALS(control_sar_vals
), 0xC000,
3531 { &hf_btl2cap_control_reqseq
,
3532 { "ReqSeq", "btl2cap.control_reqseq",
3533 FT_UINT16
, BASE_DEC
, NULL
, 0x3F00,
3534 "Request Sequence Number", HFILL
}
3536 { &hf_btl2cap_control_txseq
,
3537 { "TxSeq", "btl2cap.control_txseq",
3538 FT_UINT16
, BASE_DEC
, NULL
, 0x007E,
3539 "Transmitted Sequence Number", HFILL
}
3541 { &hf_btl2cap_control_retransmissiondisable
,
3542 { "R", "btl2cap.control_retransmissiondisable",
3543 FT_UINT16
, BASE_HEX
, NULL
, 0x0080,
3544 "Retransmission Disable", HFILL
}
3546 { &hf_btl2cap_control_supervisory
,
3547 { "S", "btl2cap.control_supervisory",
3548 FT_UINT16
, BASE_HEX
, VALS(control_supervisory_vals
), 0x000C,
3549 "Supervisory Function", HFILL
}
3551 { &hf_btl2cap_control_type
,
3552 { "Frame Type", "btl2cap.control_type",
3553 FT_UINT16
, BASE_HEX
, VALS(control_type_vals
), 0x0001,
3556 { &hf_btl2cap_control
,
3557 { "Control field", "btl2cap.control",
3558 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3562 { "FCS", "btl2cap.fcs",
3563 FT_UINT16
, BASE_HEX
, NULL
, 0,
3564 "Frame Check Sequence", HFILL
}
3566 { &hf_btl2cap_sdulength
,
3567 { "SDU Length", "btl2cap.sdulength",
3568 FT_UINT16
, BASE_DEC
, NULL
, 0,
3571 { &hf_btl2cap_reassembled_in
,
3572 { "This SDU is reassembled in frame", "btl2cap.reassembled_in",
3573 FT_FRAMENUM
, BASE_NONE
, NULL
, 0,
3574 "This SDU is reassembled in frame #", HFILL
}
3576 { &hf_btl2cap_continuation_to
,
3577 { "This is a continuation to the SDU in frame", "btl2cap.continuation_to",
3578 FT_FRAMENUM
, BASE_NONE
, NULL
, 0,
3579 "This is a continuation to the SDU in frame #", HFILL
}
3581 { &hf_btl2cap_min_interval
,
3582 { "Min. Interval", "btl2cap.min_interval",
3583 FT_UINT16
, BASE_DEC
, NULL
, 0,
3586 { &hf_btl2cap_max_interval
,
3587 { "Max. Interval", "btl2cap.max_interval",
3588 FT_UINT16
, BASE_DEC
, NULL
, 0,
3591 { &hf_btl2cap_peripheral_latency
,
3592 { "Peripheral Latency", "btl2cap.peripheral_latency",
3593 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_ll_connection_event
), 0,
3596 { &hf_btl2cap_timeout_multiplier
,
3597 { "Timeout Multiplier", "btl2cap.timeout_multiplier",
3598 FT_UINT16
, BASE_DEC
, NULL
, 0,
3601 { &hf_btl2cap_conn_param_result
,
3602 { "Move Result", "btl2cap.move_result",
3603 FT_UINT16
, BASE_HEX
, VALS(conn_param_result_vals
), 0x0,
3606 { &hf_btl2cap_le_result
,
3607 { "LE Result", "btl2cap.le_result",
3608 FT_UINT16
, BASE_HEX
, VALS(le_result_vals
), 0x0,
3611 { &hf_btl2cap_credits
,
3612 { "Credits", "btl2cap.credits",
3613 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3614 "L2CAP Channel Identifier", HFILL
}
3616 { &hf_btl2cap_initial_credits
,
3617 { "Initial Credits", "btl2cap.initial_credits",
3618 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3619 "L2CAP Channel Identifier", HFILL
}
3621 { &hf_btl2cap_le_psm
,
3622 { "LE PSM", "btl2cap.le_psm",
3623 FT_UINT16
, BASE_HEX
| BASE_RANGE_STRING
, RVALS(le_psm_rvals
), 0x0,
3624 "Protocol/Service Multiplexer", HFILL
}
3627 { "Data", "btl2cap.data",
3628 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3631 { &hf_btl2cap_service
,
3632 { "Service", "btl2cap.service",
3633 FT_UINT16
, BASE_HEX
| BASE_EXT_STRING
, &bluetooth_uuid_vals_ext
, 0x0,
3636 { &hf_btl2cap_connect_in_frame
,
3637 { "Connect in frame", "btl2cap.connect_in",
3638 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
3641 { &hf_btl2cap_disconnect_in_frame
,
3642 { "Disconnect in frame", "btl2cap.disconnect_in",
3643 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
3646 { &hf_btl2cap_le_sdu_fragments
,
3647 { "SDU fragments", "btl2cap.le_sdu.fragments",
3648 FT_NONE
, BASE_NONE
, NULL
, 0x00,
3651 { &hf_btl2cap_le_sdu_fragment
,
3652 { "SDU fragment", "btl2cap.le_sdu.fragment",
3653 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3656 { &hf_btl2cap_le_sdu_fragment_overlap
,
3657 { "SDU fragment overlap", "btl2cap.le_sdu.fragment.overlap",
3658 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3661 { &hf_btl2cap_le_sdu_fragment_overlap_conflicts
,
3662 { "SDU fragment overlapping with conflicting data", "btl2cap.le_sdu.fragment.overlap.conflicts",
3663 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3666 { &hf_btl2cap_le_sdu_fragment_multiple_tails
,
3667 { "SDU has multiple tail fragments", "btl2cap.le_sdu.fragment.multiple_tails",
3668 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3671 { &hf_btl2cap_le_sdu_fragment_too_long_fragment
,
3672 { "SDU fragment too long", "btl2cap.le_sdu.fragment.too_long_fragment",
3673 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3676 { &hf_btl2cap_le_sdu_fragment_error
,
3677 { "SDU defragmentation error", "btl2cap.le_sdu.fragment.error",
3678 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3681 { &hf_btl2cap_le_sdu_fragment_count
,
3682 { "SDU fragment count", "btl2cap.le_sdu.fragment.count",
3683 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3686 { &hf_btl2cap_le_sdu_reassembled_in
,
3687 { "Reassembled in", "btl2cap.le_sdu.reassembled.in",
3688 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3691 { &hf_btl2cap_le_sdu_reassembled_length
,
3692 { "Reassembled SDU length", "btl2cap.le_sdu.reassembled.length",
3693 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3696 { &hf_btl2cap_le_sdu_length
,
3697 { "SDU Length", "btl2cap.le_sdu_length",
3698 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
3704 /* Setup protocol subtree array */
3705 static int *ett
[] = {
3708 &ett_btl2cap_option
,
3709 &ett_btl2cap_extfeatures
,
3710 &ett_btl2cap_fixedchans
,
3711 &ett_btl2cap_control
,
3712 &ett_btl2cap_le_sdu_fragment
,
3713 &ett_btl2cap_le_sdu_fragments
3716 static ei_register_info ei
[] = {
3717 { &ei_btl2cap_parameter_mismatch
, { "btl2cap.parameter_mismatch", PI_PROTOCOL
, PI_WARN
, "Parameter mismatch", EXPFILL
}},
3718 { &ei_btl2cap_sdulength_bad
, { "btl2cap.sdulength.bad", PI_MALFORMED
, PI_WARN
, "SDU length bad", EXPFILL
}},
3719 { &ei_btl2cap_length_bad
, { "btl2cap.length.bad", PI_MALFORMED
, PI_WARN
, "Length too short", EXPFILL
}},
3720 { &ei_btl2cap_unknown_command_code
, { "btl2cap.unknown_command_code", PI_PROTOCOL
, PI_WARN
, "Unknown Command Code", EXPFILL
}},
3723 /* Decode As handling */
3724 static build_valid_func btl2cap_cid_da_build_value
[1] = {btl2cap_cid_value
};
3725 static decode_as_value_t btl2cap_cid_da_values
= {btl2cap_cid_prompt
, 1, btl2cap_cid_da_build_value
};
3726 static decode_as_t btl2cap_cid_da
= {"btl2cap", "btl2cap.cid", 1, 0, &btl2cap_cid_da_values
, NULL
, NULL
,
3727 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
3729 static build_valid_func btl2cap_psm_da_build_value
[1] = {btl2cap_psm_value
};
3730 static decode_as_value_t btl2cap_psm_da_values
= {btl2cap_psm_prompt
, 1, btl2cap_psm_da_build_value
};
3731 static decode_as_t btl2cap_psm_da
= {"btl2cap", "btl2cap.psm", 1, 0, &btl2cap_psm_da_values
, NULL
, NULL
,
3732 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
3734 /* Register the protocol name and description */
3735 proto_btl2cap
= proto_register_protocol("Bluetooth L2CAP Protocol", "BT L2CAP", "btl2cap");
3737 register_dissector("btl2cap", dissect_btl2cap
, proto_btl2cap
);
3739 /* subdissector code */
3740 l2cap_psm_dissector_table
= register_dissector_table("btl2cap.psm", "BT L2CAP PSM", proto_btl2cap
, FT_UINT16
, BASE_HEX
);
3741 l2cap_cid_dissector_table
= register_dissector_table("btl2cap.cid", "BT L2CAP CID", proto_btl2cap
, FT_UINT16
, BASE_HEX
);
3743 /* Required function calls to register the header fields and subtrees used */
3744 proto_register_field_array(proto_btl2cap
, hf
, array_length(hf
));
3745 proto_register_subtree_array(ett
, array_length(ett
));
3746 expert_btl2cap
= expert_register_protocol(proto_btl2cap
);
3747 expert_register_field_array(expert_btl2cap
, ei
, array_length(ei
));
3749 cmd_ident_to_psm_table
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3750 cid_to_psm_table
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3752 register_decode_as(&btl2cap_cid_da
);
3753 register_decode_as(&btl2cap_psm_da
);
3755 reassembly_table_register(&btl2cap_le_sdu_reassembly_table
,
3756 &addresses_reassembly_table_functions
);
3761 proto_reg_handoff_btl2cap(void)
3766 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3771 * indent-tabs-mode: nil
3774 * vi: set shiftwidth=4 tabstop=8 expandtab:
3775 * :indentSize=4:tabSize=8:noTabs=true: