2 * Routines for Bluetooth RFCOMM protocol dissection
3 * and RFCOMM based profile dissection:
4 * - Dial-Up Networking Profile (DUN)
5 * - Serial Port Profile (SPP)
6 * - Global Navigation Satellite System (GNSS)
8 * Copyright 2002, Wolfgang Hansmann <hansmann@cs.uni-bonn.de>
10 * Refactored for wireshark checkin
11 * Ronnie Sahlberg 2006
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * SPDX-License-Identifier: GPL-2.0-or-later
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/expert.h>
26 #include <epan/decode_as.h>
27 #include <epan/proto_data.h>
29 #include "packet-bluetooth.h"
30 #include "packet-btsdp.h"
31 #include "packet-btl2cap.h"
32 #include "packet-btrfcomm.h"
37 static int hf_frame_type
;
40 static int hf_channel
;
41 static int hf_direction
;
42 static int hf_priority
;
43 static int hf_error_recovery_mode
;
44 static int hf_max_frame_size
;
45 static int hf_max_retrans
;
46 static int hf_fc_credits
;
48 static int hf_mcc_pn_parameters
;
53 static int hf_mcc_types
;
54 static int hf_mcc_len
;
57 static int hf_mcc_cmd
;
59 static int hf_msc_parameters
;
61 static int hf_msc_rtc
;
62 static int hf_msc_rtr
;
66 static int hf_msc_break_bits
;
70 static int hf_dun_at_cmd
;
71 static int hf_spp_data
;
72 static int hf_gnss_data
;
74 static int hf_mcc_dlci
;
75 static int hf_mcc_channel
;
76 static int hf_mcc_direction
;
77 static int hf_mcc_const_1
;
79 static int hf_mcc_pn_dlci
;
80 static int hf_mcc_pn_channel
;
81 static int hf_mcc_pn_direction
;
82 static int hf_mcc_pn_zeros_padding
;
84 static int hf_acknowledgement_timer_t1
;
85 static int hf_address
;
86 static int hf_control
;
88 /* Initialize the protocol and registered fields */
90 static int proto_btdun
;
91 static int proto_btspp
;
92 static int proto_btgnss
;
94 /* Initialize the subtree pointers */
95 static int ett_btrfcomm
;
96 static int ett_btrfcomm_ctrl
;
98 static int ett_control
;
100 static int ett_ctrl_pn_ci
;
101 static int ett_ctrl_pn_v24
;
103 static int ett_mcc_dlci
;
105 static int ett_btdun
;
106 static int ett_btspp
;
107 static int ett_btgnss
;
109 static expert_field ei_btrfcomm_mcc_length_bad
;
111 static dissector_handle_t btrfcomm_handle
;
112 static dissector_handle_t btdun_handle
;
113 static dissector_handle_t btspp_handle
;
114 static dissector_handle_t btgnss_handle
;
116 static dissector_table_t rfcomm_dlci_dissector_table
;
118 static wmem_tree_t
*service_directions
;
123 } service_direction_t
;
127 char* payload_proto_name
;
128 dissector_handle_t payload_proto
;
129 } uat_rfcomm_channels_t
;
131 static bool rfcomm_channels_enabled
;
132 static uat_t
*uat_rfcomm_channels
;
133 static uat_rfcomm_channels_t
*rfcomm_channels
;
134 static unsigned num_rfcomm_channels
;
136 UAT_DEC_CB_DEF(rfcomm_channels
, channel
, uat_rfcomm_channels_t
)
137 UAT_DISSECTOR_DEF(rfcomm_channels
, payload_proto
, payload_proto
, payload_proto_name
, uat_rfcomm_channels_t
)
139 static uat_field_t uat_rfcomm_channels_fields
[] = {
140 UAT_FLD_DEC(rfcomm_channels
, channel
, "RFCOMM Channel",
142 UAT_FLD_DISSECTOR(rfcomm_channels
, payload_proto
, "Payload dissector",
143 "Dissector name used to decode RFCOMM channel"),
147 static dissector_handle_t ppp_handle
;
149 static const value_string vs_ctl_pn_i
[] = {
150 {0x0, "use UIH Frames"},
151 #if 0 /* specified by 07.10, but not used by RFCOMM */
152 {0x1, "use UI Frames"},
153 {0x2, "use I Frames"},
158 static const value_string vs_ctl_pn_cl
[] = {
160 {0x0, "no credit based flow control scheme"},
161 {0xe, "support of credit based flow control scheme (resp)"},
162 {0xf, "support of credit based flow control scheme (req)"},
163 #if 0 /* specified by 07.10. Redefined by RFCOMM */
164 {0x0, "type 1 (unstructured octet stream)"},
165 {0x1, "type 2 (unstructured octet stream with flow control)"},
166 {0x2, "type 3 (uninterruptible framed data)"},
167 {0x3, "type 4 (interruptible framed data)"},
173 static const value_string vs_frame_type
[] = {
175 {0x2f, "Set Asynchronous Balanced Mode (SABM)"},
176 {0x63, "Unnumbered Acknowledgement (UA)"},
177 {0x0f, "Disconnected Mode (DM)"},
178 {0x43, "Disconnect (DISC)"},
179 {0xef, "Unnumbered Information with Header check (UIH)"},
180 #if 0 /* specified by 07.10, but not used by RFCOMM */
181 {0x03, "Unnumbered Information (UI)"},
187 static const value_string vs_frame_type_short
[] = {
194 #if 0 /* specified by 07.10, but not used by RFCOMM */
200 #define FRAME_TYPE_SABM 0x2F
201 #define FRAME_TYPE_UIH 0xEF
203 static const value_string vs_ctl
[] = {
205 {0x20, "DLC Parameter Negotiation (PN)"},
206 {0x08, "Test Command (Test)"},
207 {0x28, "Flow Control On Command (FCon)"},
208 {0x18, "Flow Control Off Command (FCoff)"},
209 {0x38, "Modem Status Command (MSC)"},
210 {0x04, "Non Supported Command Response (NSC)"},
211 {0x24, "Remote Port Negotiation Command (RPN)"},
212 {0x14, "Remote Line Status Command (RLS)"},
213 #if 0 /* Specified by 07.10, but not used by RFCOMM */
214 {0x10, "Power Saving Control (PSC)"},
215 {0x30, "Multiplexer close down (CLD)"},
216 {0x34, "Service Negotiation Command (SNC)"},
219 {0x80, "DLC parameter negotiation (PN)"},
220 {0x20, "Test Command (Test)"},
221 {0xa0, "Flow Control On Command (FCon)"},
222 {0x60, "Flow Control Off Command (FCoff)"},
223 {0xe0, "Modem Status Command (MSC)"},
224 {0x10, "Non Supported Command Response (NSC)"},
225 {0x90, "Remote Port Negotiation Command (RPN)"},
226 {0x50, "Remote Line Status Command (RLS)"},
227 {0x40, "Power Saving Control (PSC)"},
228 {0xc0, "Multiplexer close down (CLD)"},
229 {0xd0, "Service Negotiation Command (SNC)"},
234 static const value_string vs_ea
[] = {
235 {1, "Last field octet"},
236 {0, "More field octets following"},
240 void proto_register_btrfcomm(void);
241 void proto_reg_handoff_btrfcomm(void);
242 void proto_register_btdun(void);
243 void proto_reg_handoff_btdun(void);
244 void proto_register_btspp(void);
245 void proto_reg_handoff_btspp(void);
246 void proto_register_btgnss(void);
247 void proto_reg_handoff_btgnss(void);
249 #define PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL 0
251 static void btrfcomm_directed_channel_prompt(packet_info
*pinfo
, char* result
)
255 value_data
= (uint8_t *) p_get_proto_data(pinfo
->pool
, pinfo
, proto_btrfcomm
, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL
);
257 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "RFCOMM Channel %d (direction: %u) as", (unsigned) (*value_data
) >> 1, (unsigned) (*value_data
) & 1);
259 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Unknown RFCOMM Channel");
262 static void *btrfcomm_directed_channel_value(packet_info
*pinfo
)
266 value_data
= (uint8_t *) p_get_proto_data(pinfo
->pool
, pinfo
, proto_btrfcomm
, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL
);
269 return GUINT_TO_POINTER((unsigned long)*value_data
);
274 static dissector_handle_t
275 find_proto_by_channel(unsigned channel
) {
278 for (i_channel
= 0; i_channel
< num_rfcomm_channels
; ++i_channel
) {
279 if (rfcomm_channels
[i_channel
].channel
== channel
) {
280 return rfcomm_channels
[i_channel
].payload_proto
;
287 get_le_multi_byte_value(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, uint32_t *val_ptr
, int hf_index
)
289 uint8_t byte
, bc
= 0;
291 int start_offset
= offset
;
294 byte
= tvb_get_uint8(tvb
, offset
);
296 val
|= ((byte
>> 1) & 0xff) << (bc
++ * 7);
297 } while (((byte
& 0x1) == 0) && (bc
<= 4));
302 proto_tree_add_uint(tree
, hf_index
, tvb
, start_offset
, offset
- start_offset
, val
);
310 dissect_ctrl_pn(proto_tree
*t
, tvbuff_t
*tvb
, int offset
, uint8_t *mcc_channel
)
314 proto_tree
*dlci_tree
;
315 proto_item
*dlci_item
;
320 proto_tree_add_item(t
, hf_mcc_pn_zeros_padding
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
323 mcc_dlci
= tvb_get_uint8(tvb
, offset
) & 0x3f;
324 *mcc_channel
= mcc_dlci
>> 1;
326 dlci_item
= proto_tree_add_item(t
, hf_mcc_pn_dlci
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
327 proto_item_append_text(dlci_item
, " (Direction: %d, Channel: %u)", mcc_dlci
& 0x01, *mcc_channel
);
329 dlci_tree
= proto_item_add_subtree(dlci_item
, ett_mcc_dlci
);
330 proto_tree_add_item(dlci_tree
, hf_mcc_pn_channel
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
331 proto_tree_add_item(dlci_tree
, hf_mcc_pn_direction
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
334 flags
= tvb_get_uint8(tvb
, offset
);
336 ti
= proto_tree_add_none_format(t
, hf_mcc_pn_parameters
, tvb
, offset
, 1, "I1-I4: 0x%x, C1-C4: 0x%x", flags
& 0xf, (flags
>> 4) & 0xf);
337 st
= proto_item_add_subtree(ti
, ett_ctrl_pn_ci
);
339 proto_tree_add_item(st
, hf_pn_c14
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
340 proto_tree_add_item(st
, hf_pn_i14
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
344 proto_tree_add_item(t
, hf_priority
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
348 item
= proto_tree_add_item(t
, hf_acknowledgement_timer_t1
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
349 proto_item_append_text(item
, "(%d ms)", (uint32_t)tvb_get_uint8(tvb
, offset
) * 100);
353 proto_tree_add_item(t
, hf_max_frame_size
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
357 proto_tree_add_item(t
, hf_max_retrans
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
360 /* error recovery mode */
361 proto_tree_add_item(t
, hf_error_recovery_mode
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
368 dissect_ctrl_msc(proto_tree
*t
, tvbuff_t
*tvb
, int offset
, int length
, uint8_t *mcc_channel
)
373 proto_tree
*dlci_tree
;
374 proto_item
*dlci_item
;
379 mcc_dlci
= tvb_get_uint8(tvb
, offset
) >> 2;
380 *mcc_channel
= mcc_dlci
>> 1;
382 dlci_item
= proto_tree_add_item(t
, hf_mcc_dlci
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
383 proto_item_append_text(dlci_item
, " (Direction: %d, Channel: %u)", mcc_dlci
& 0x01, *mcc_channel
);
385 dlci_tree
= proto_item_add_subtree(dlci_item
, ett_mcc_dlci
);
386 proto_tree_add_item(dlci_tree
, hf_mcc_channel
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
387 proto_tree_add_item(dlci_tree
, hf_mcc_direction
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
389 proto_tree_add_item(t
, hf_mcc_const_1
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
390 proto_tree_add_item(t
, hf_mcc_ea
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
394 start_offset
= offset
;
395 status
= tvb_get_uint8(tvb
, offset
);
396 it
= proto_tree_add_none_format(t
, hf_msc_parameters
, tvb
, offset
, 1, "V.24 Signals: FC = %d, RTC = %d, RTR = %d, IC = %d, DV = %d", (status
>> 1) & 1,
397 (status
>> 2) & 1, (status
>> 3) & 1,
398 (status
>> 6) & 1, (status
>> 7) & 1);
399 st
= proto_item_add_subtree(it
, ett_ctrl_pn_v24
);
401 proto_tree_add_item(st
, hf_msc_fc
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
402 proto_tree_add_item(st
, hf_msc_rtc
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
403 proto_tree_add_item(st
, hf_msc_rtr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
404 proto_tree_add_item(st
, hf_msc_ic
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
405 proto_tree_add_item(st
, hf_msc_dv
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
409 proto_tree_add_item(t
, hf_msc_break_bits
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
410 proto_tree_add_item(t
, hf_msc_l
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
414 proto_item_set_len(it
, offset
- start_offset
);
420 dissect_btrfcomm_address(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
, uint8_t *ea_flagp
, uint8_t *cr_flagp
, uint8_t *dlcip
)
423 proto_tree
*addr_tree
;
424 proto_tree
*dlci_tree
= NULL
;
425 proto_item
*dlci_item
= NULL
;
426 uint8_t dlci
, cr_flag
, ea_flag
, flags
, channel
;
428 flags
= tvb_get_uint8(tvb
, offset
);
430 ea_flag
= flags
& 0x01;
435 cr_flag
= (flags
& 0x02) ? 1 : 0;
445 ti
= proto_tree_add_none_format(tree
, hf_address
, tvb
, offset
, 1, "Address: E/A flag: %d, C/R flag: %d, Direction: %d, Channel: %u", ea_flag
, cr_flag
, dlci
& 0x01, dlci
>> 1);
446 addr_tree
= proto_item_add_subtree(ti
, ett_addr
);
448 dlci_item
= proto_tree_add_item(addr_tree
, hf_dlci
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
450 proto_item_append_text(dlci_item
, " (Direction: %d, Channel: %u)", dlci
& 0x01, channel
);
452 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_btrfcomm
, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL
) == NULL
) {
455 value_data
= wmem_new(wmem_file_scope(), uint8_t);
458 p_add_proto_data(pinfo
->pool
, pinfo
, proto_btrfcomm
, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL
, value_data
);
461 dlci_tree
= proto_item_add_subtree(dlci_item
, ett_dlci
);
462 proto_tree_add_item(dlci_tree
, hf_channel
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
463 proto_tree_add_item(dlci_tree
, hf_direction
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
465 proto_tree_add_item(addr_tree
, hf_cr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
466 proto_tree_add_item(addr_tree
, hf_ea
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
473 dissect_btrfcomm_control(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, uint8_t *pf_flagp
, uint8_t *frame_typep
)
476 proto_tree
*hctl_tree
;
477 uint8_t frame_type
, pf_flag
, flags
;
479 flags
= tvb_get_uint8(tvb
, offset
);
481 pf_flag
= (flags
& 0x10) ? 1 : 0;
486 frame_type
= flags
& 0xef;
488 *frame_typep
= frame_type
;
491 ti
= proto_tree_add_none_format(tree
, hf_control
, tvb
, offset
, 1, "Control: Frame type: %s (0x%x), P/F flag: %d",
492 val_to_str_const(frame_type
, vs_frame_type
, "Unknown"), frame_type
, pf_flag
);
493 hctl_tree
= proto_item_add_subtree(ti
, ett_control
);
495 proto_tree_add_item(hctl_tree
, hf_pf
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
496 proto_tree_add_item(hctl_tree
, hf_frame_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
505 dissect_btrfcomm_payload_length(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, uint16_t *frame_lenp
)
508 int start_offset
= offset
;
510 frame_len
= tvb_get_uint8(tvb
, offset
);
513 if (frame_len
& 0x01) {
514 frame_len
>>= 1; /* 0 - 127 */
516 frame_len
>>= 1; /* 128 - ... */
517 frame_len
|= (tvb_get_uint8(tvb
, offset
)) << 7;
521 proto_tree_add_uint(tree
, hf_len
, tvb
, start_offset
, offset
- start_offset
, frame_len
);
524 *frame_lenp
= frame_len
;
531 dissect_btrfcomm_MccType(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, uint8_t *mcc_cr_flagp
, uint8_t *mcc_ea_flagp
, uint32_t *mcc_typep
)
533 int start_offset
= offset
;
535 proto_tree
*mcc_tree
;
536 uint8_t flags
, mcc_cr_flag
, mcc_ea_flag
;
539 flags
= tvb_get_uint8(tvb
, offset
);
541 mcc_cr_flag
= (flags
& 0x2) ? 1 : 0;
543 *mcc_cr_flagp
= mcc_cr_flag
;
546 mcc_ea_flag
= flags
& 0x1;
548 *mcc_ea_flagp
= mcc_ea_flag
;
551 offset
= get_le_multi_byte_value(tvb
, offset
, tree
, &mcc_type
, -1);
552 mcc_type
= (mcc_type
>> 1) & 0x3f; /* shift c/r flag off */
554 *mcc_typep
= mcc_type
;
557 ti
= proto_tree_add_none_format(tree
, hf_mcc_types
, tvb
, start_offset
, offset
- start_offset
,
558 "Type: %s (0x%x), C/R flag = %d, E/A flag = %d",
559 val_to_str_const(mcc_type
, vs_ctl
, "Unknown"),
560 mcc_type
, mcc_cr_flag
, mcc_ea_flag
);
561 mcc_tree
= proto_item_add_subtree(ti
, ett_mcc
);
563 proto_tree_add_item(mcc_tree
, hf_mcc_cmd
, tvb
, start_offset
, offset
- start_offset
, ENC_LITTLE_ENDIAN
);
564 proto_tree_add_item(mcc_tree
, hf_mcc_cr
, tvb
, start_offset
, 1, ENC_LITTLE_ENDIAN
);
565 proto_tree_add_item(mcc_tree
, hf_mcc_ea
, tvb
, start_offset
, 1, ENC_LITTLE_ENDIAN
);
571 dissect_btrfcomm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
574 proto_tree
*rfcomm_tree
;
577 uint8_t dlci
, cr_flag
, ea_flag
;
578 uint8_t frame_type
, pf_flag
;
580 btl2cap_data_t
*l2cap_data
;
581 service_info_t
*service_info
= NULL
;
583 /* Reject the packet if data is NULL */
586 l2cap_data
= (btl2cap_data_t
*) data
;
588 ti
= proto_tree_add_item(tree
, proto_btrfcomm
, tvb
, offset
, tvb_captured_length(tvb
), ENC_NA
);
589 rfcomm_tree
= proto_item_add_subtree(ti
, ett_btrfcomm
);
591 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RFCOMM");
593 switch (pinfo
->p2p_dir
) {
595 col_set_str(pinfo
->cinfo
, COL_INFO
, "Sent ");
598 col_set_str(pinfo
->cinfo
, COL_INFO
, "Rcvd ");
601 col_set_str(pinfo
->cinfo
, COL_INFO
, "UnknownDirection ");
606 offset
= dissect_btrfcomm_address(tvb
, pinfo
, offset
, rfcomm_tree
, &ea_flag
, &cr_flag
, &dlci
);
607 /* pf and frame type */
608 offset
= dissect_btrfcomm_control(tvb
, offset
, rfcomm_tree
, &pf_flag
, &frame_type
);
610 offset
= dissect_btrfcomm_payload_length(tvb
, offset
, rfcomm_tree
, &frame_len
);
612 if (dlci
&& (frame_len
|| (frame_type
== FRAME_TYPE_UIH
) || (frame_type
== FRAME_TYPE_SABM
))) {
613 wmem_tree_key_t key
[10];
614 uint32_t k_interface_id
;
615 uint32_t k_adapter_id
;
617 uint32_t k_direction
;
618 uint32_t k_bd_addr_oui
;
619 uint32_t k_bd_addr_id
;
620 uint32_t k_service_type
;
621 uint32_t k_frame_number
;
625 service_direction_t
*service_direction
;
626 wmem_tree_t
*subtree
;
628 k_interface_id
= l2cap_data
->interface_id
;
629 k_adapter_id
= l2cap_data
->adapter_id
;
630 k_chandle
= l2cap_data
->chandle
;
631 k_psm
= l2cap_data
->psm
;
632 k_channel
= dlci
>> 1;
633 k_frame_number
= pinfo
->num
;
637 key
[0].key
= &k_interface_id
;
639 key
[1].key
= &k_adapter_id
;
641 key
[2].key
= &k_chandle
;
645 key
[4].key
= &k_dlci
;
647 if (!pinfo
->fd
->visited
&& frame_type
== FRAME_TYPE_SABM
) {
651 subtree
= (wmem_tree_t
*) wmem_tree_lookup32_array(service_directions
, key
);
652 service_direction
= (subtree
) ? (service_direction_t
*) wmem_tree_lookup32_le(subtree
, k_frame_number
) : NULL
;
653 if (service_direction
&& service_direction
->end_in
== bluetooth_max_disconnect_in_frame
) {
654 service_direction
->end_in
= k_frame_number
;
658 key
[5].key
= &k_frame_number
;
662 service_direction
= wmem_new(wmem_file_scope(), service_direction_t
);
663 service_direction
->direction
= (pinfo
->p2p_dir
== P2P_DIR_RECV
) ? P2P_DIR_SENT
: P2P_DIR_RECV
;
664 service_direction
->end_in
= bluetooth_max_disconnect_in_frame
;
666 wmem_tree_insert32_array(service_directions
, key
, service_direction
);
668 key
[4].key
= &k_channel
;
672 subtree
= (wmem_tree_t
*) wmem_tree_lookup32_array(service_directions
, key
);
673 service_direction
= (subtree
) ? (service_direction_t
*) wmem_tree_lookup32_le(subtree
, k_frame_number
) : NULL
;
674 if (service_direction
&& service_direction
->end_in
> k_frame_number
) {
675 k_direction
= service_direction
->direction
;
678 k_direction
= (l2cap_data
->is_local_psm
) ? P2P_DIR_RECV
: P2P_DIR_SENT
;
680 k_direction
= (l2cap_data
->is_local_psm
) ? P2P_DIR_SENT
: P2P_DIR_RECV
;
683 k_psm
= SDP_PSM_DEFAULT
;
684 if (k_direction
== P2P_DIR_RECV
) {
685 k_bd_addr_oui
= l2cap_data
->remote_bd_addr_oui
;
686 k_bd_addr_id
= l2cap_data
->remote_bd_addr_id
;
691 k_service_type
= BTSDP_RFCOMM_PROTOCOL_UUID
;
696 key
[3].key
= &k_direction
;
698 key
[4].key
= &k_bd_addr_oui
;
700 key
[5].key
= &k_bd_addr_id
;
702 key
[6].key
= &k_service_type
;
704 key
[7].key
= &k_channel
;
706 key
[8].key
= &k_frame_number
;
710 service_info
= btsdp_get_service_info(key
);
712 if (service_info
&& service_info
->interface_id
== l2cap_data
->interface_id
&&
713 service_info
->adapter_id
== l2cap_data
->adapter_id
&&
714 service_info
->sdp_psm
== SDP_PSM_DEFAULT
&&
715 ((service_info
->direction
== P2P_DIR_RECV
&&
716 service_info
->bd_addr_oui
== l2cap_data
->remote_bd_addr_oui
&&
717 service_info
->bd_addr_id
== l2cap_data
->remote_bd_addr_id
) ||
718 (service_info
->direction
!= P2P_DIR_RECV
&&
719 service_info
->bd_addr_oui
== 0 &&
720 service_info
->bd_addr_id
== 0)) &&
721 service_info
->type
== BTSDP_RFCOMM_PROTOCOL_UUID
&&
722 service_info
->channel
== (dlci
>> 1)) {
725 service_info
= wmem_new0(pinfo
->pool
, service_info_t
);
729 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s Channel=%u ",
730 val_to_str_const(frame_type
, vs_frame_type_short
, "Unknown"), dlci
>> 1);
731 if (dlci
&& (frame_type
== FRAME_TYPE_SABM
) && service_info
) {
732 if (service_info
->uuid
.size
==16)
733 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(UUID128: %s) ", print_bluetooth_uuid(pinfo
->pool
, &service_info
->uuid
));
735 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%s) ",
736 val_to_str_ext_const(service_info
->uuid
.bt_uuid
, &bluetooth_uuid_vals_ext
, "Unknown"));
740 if ((frame_type
== FRAME_TYPE_UIH
) && dlci
&& pf_flag
) {
741 col_append_str(pinfo
->cinfo
, COL_INFO
, "UID ");
743 /* add credit based flow control byte */
744 proto_tree_add_item(rfcomm_tree
, hf_fc_credits
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
749 fcs_offset
= offset
+ frame_len
;
751 /* multiplexer control command */
752 if (!dlci
&& frame_len
) {
754 proto_tree
*ctrl_tree
;
755 proto_tree
*dlci_tree
;
756 proto_item
*dlci_item
;
757 uint32_t mcc_type
, length
;
758 uint8_t mcc_cr_flag
, mcc_ea_flag
;
761 int start_offset
= offset
;
763 mcc_ti
= proto_tree_add_item(rfcomm_tree
, hf_mcc
, tvb
, offset
, 1, ENC_NA
);
764 ctrl_tree
= proto_item_add_subtree(mcc_ti
, ett_btrfcomm_ctrl
);
767 offset
= dissect_btrfcomm_MccType(tvb
, offset
, ctrl_tree
, &mcc_cr_flag
, &mcc_ea_flag
, &mcc_type
);
770 offset
= get_le_multi_byte_value(tvb
, offset
, ctrl_tree
, &length
, hf_mcc_len
);
772 if (length
> (uint32_t) tvb_reported_length_remaining(tvb
, offset
)) {
773 expert_add_info_format(pinfo
, ctrl_tree
, &ei_btrfcomm_mcc_length_bad
, "Huge MCC length: %u", length
);
778 case 0x20: /* DLC Parameter Negotiation */
779 dissect_ctrl_pn(ctrl_tree
, tvb
, offset
, &mcc_channel
);
781 case 0x24: /* Remote Port Negotiation */
782 mcc_dlci
= tvb_get_uint8(tvb
, offset
) >> 2;
783 mcc_channel
= mcc_dlci
>> 1;
785 dlci_item
= proto_tree_add_item(ctrl_tree
, hf_mcc_dlci
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
786 proto_item_append_text(dlci_item
, " (Direction: %d, Channel: %u)", mcc_dlci
& 0x01, mcc_channel
);
788 dlci_tree
= proto_item_add_subtree(dlci_item
, ett_mcc_dlci
);
789 proto_tree_add_item(dlci_tree
, hf_mcc_channel
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
790 proto_tree_add_item(dlci_tree
, hf_mcc_direction
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
792 proto_tree_add_item(ctrl_tree
, hf_mcc_const_1
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
793 proto_tree_add_item(ctrl_tree
, hf_mcc_ea
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
796 case 0x38: /* Modem Status Command */
797 dissect_ctrl_msc(ctrl_tree
, tvb
, offset
, length
, &mcc_channel
);
803 if (mcc_channel
> 0) {
804 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "-> %d ", mcc_channel
);
807 col_append_str(pinfo
->cinfo
, COL_INFO
, "MPX_CTRL ");
810 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str_const(mcc_type
, vs_ctl
, "Unknown"));
815 proto_item_set_len(mcc_ti
, offset
- start_offset
);
818 /* try to find a higher layer dissector that has registered to handle data
819 * for this kind of service, if none is found dissect it as raw "data"
821 if (dlci
&& frame_len
) {
822 dissector_handle_t decode_by_dissector
;
824 btrfcomm_data_t
*rfcomm_data
;
826 next_tvb
= tvb_new_subset_length(tvb
, offset
, frame_len
);
828 rfcomm_data
= (btrfcomm_data_t
*) wmem_new(pinfo
->pool
, btrfcomm_data_t
);
829 rfcomm_data
->interface_id
= l2cap_data
->interface_id
;
830 rfcomm_data
->adapter_id
= l2cap_data
->adapter_id
;
831 rfcomm_data
->chandle
= l2cap_data
->chandle
;
832 rfcomm_data
->cid
= l2cap_data
->cid
;
833 rfcomm_data
->is_local_psm
= l2cap_data
->is_local_psm
;
834 rfcomm_data
->dlci
= dlci
;
835 rfcomm_data
->remote_bd_addr_oui
= l2cap_data
->remote_bd_addr_oui
;
836 rfcomm_data
->remote_bd_addr_id
= l2cap_data
->remote_bd_addr_id
;
838 if (service_info
&& service_info
->uuid
.size
!= 0 &&
839 p_get_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
) == NULL
) {
842 value_data
= wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo
->pool
, &service_info
->uuid
));
844 p_add_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
, value_data
);
847 if (!dissector_try_uint_with_data(rfcomm_dlci_dissector_table
, (uint32_t) dlci
,
848 next_tvb
, pinfo
, tree
, true, rfcomm_data
)) {
849 if (service_info
&& (service_info
->uuid
.size
== 0 ||
850 !dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &service_info
->uuid
),
851 next_tvb
, pinfo
, tree
, true, rfcomm_data
))) {
852 decode_by_dissector
= find_proto_by_channel(dlci
>> 1);
853 if (rfcomm_channels_enabled
&& decode_by_dissector
) {
854 call_dissector_with_data(decode_by_dissector
, next_tvb
, pinfo
, tree
, rfcomm_data
);
856 /* unknown service, let the data dissector handle it */
857 call_data_dissector(next_tvb
, pinfo
, tree
);
863 proto_tree_add_item(rfcomm_tree
, hf_fcs
, tvb
, fcs_offset
, 1, ENC_LITTLE_ENDIAN
);
870 uat_rfcomm_channels_copy_cb(void *dest
, const void *source
, size_t len _U_
)
872 const uat_rfcomm_channels_t
* o
= (const uat_rfcomm_channels_t
*)source
;
873 uat_rfcomm_channels_t
* d
= (uat_rfcomm_channels_t
*)dest
;
875 d
->channel
= o
->channel
;
876 d
->payload_proto
= o
->payload_proto
;
877 d
->payload_proto_name
= g_strdup(o
->payload_proto_name
);
883 uat_rfcomm_channels_free_cb(void *r
)
885 uat_rfcomm_channels_t
*rec
= (uat_rfcomm_channels_t
*)r
;
886 g_free(rec
->payload_proto_name
);
890 proto_register_btrfcomm(void)
893 expert_module_t
*expert_btrfcomm
;
895 static hf_register_info hf
[] = {
897 { "DLCI", "btrfcomm.dlci",
898 FT_UINT8
, BASE_HEX
, NULL
, 0xFC,
899 "RFCOMM Data Link Connection Identifier", HFILL
}
902 { "Channel", "btrfcomm.channel",
903 FT_UINT8
, BASE_DEC
, NULL
, 0xF8,
904 "RFCOMM Channel", HFILL
}
907 {"Direction", "btrfcomm.direction",
908 FT_UINT8
, BASE_HEX
, NULL
, 0x04,
912 { "Priority", "btrfcomm.priority",
913 FT_UINT8
, BASE_DEC
, NULL
, 0x3f,
916 { &hf_max_frame_size
,
917 { "Max Frame Size", "btrfcomm.max_frame_size",
918 FT_UINT16
, BASE_DEC
, NULL
, 0,
919 "Maximum Frame Size", HFILL
}
922 { "Maximum number of retransmissions", "btrfcomm.max_retrans",
923 FT_UINT8
, BASE_DEC
, NULL
, 0,
926 { &hf_error_recovery_mode
,
927 { "Error Recovery Mode", "btrfcomm.error_recovery_mode",
928 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
932 { "EA Flag", "btrfcomm.ea",
933 FT_UINT8
, BASE_HEX
, VALS(vs_ea
), 0x01,
934 "EA flag (should be always 1)", HFILL
}
937 { "C/R Flag", "btrfcomm.cr",
938 FT_BOOLEAN
, 8, TFS(&tfs_command_response
), 0x02,
939 "Command/Response flag", HFILL
}
942 { "Multiplexer Control Command", "btrfcomm.mcc",
943 FT_NONE
, BASE_NONE
, NULL
, 0x00,
946 { &hf_mcc_pn_parameters
,
947 { "Parameters", "btrfcomm.mcc.pn_parameters",
948 FT_NONE
, BASE_NONE
, NULL
, 0x00,
952 { "Types", "btrfcomm.mcc.types",
953 FT_NONE
, BASE_NONE
, NULL
, 0x00,
957 { "EA Flag", "btrfcomm.mcc.ea",
958 FT_UINT8
, BASE_HEX
, VALS(vs_ea
), 0x01,
959 "RFCOMM MCC EA flag", HFILL
}
962 { "C/R Flag", "btrfcomm.mcc.cr",
963 FT_BOOLEAN
, 8, TFS(&tfs_command_response
), 0x02,
964 "Command/Response flag", HFILL
}
967 { "Ones padding", "btrfcomm.mcc.padding",
968 FT_UINT8
, BASE_HEX
, NULL
, 0x02,
972 { "MCC DLCI", "btrfcomm.mcc.dlci",
973 FT_UINT8
, BASE_HEX
, NULL
, 0xFC,
974 "RFCOMM MCC Data Link Connection Identifier", HFILL
}
977 { "MCC Channel", "btrfcomm.mcc.channel",
978 FT_UINT8
, BASE_DEC
, NULL
, 0xF8,
979 "RFCOMM MCC Channel", HFILL
}
982 { "MCC Direction", "btrfcomm.mcc.direction",
983 FT_UINT8
, BASE_HEX
, NULL
, 0x04,
984 "RFCOMM MCC Direction", HFILL
}
987 { "MCC DLCI", "btrfcomm.mcc.dlci",
988 FT_UINT8
, BASE_HEX
, NULL
, 0x3F,
989 "RFCOMM MCC Data Link Connection Identifier", HFILL
}
991 { &hf_mcc_pn_channel
,
992 { "MCC Channel", "btrfcomm.mcc.channel",
993 FT_UINT8
, BASE_DEC
, NULL
, 0x3E,
994 "RFCOMM MCC Channel", HFILL
}
996 { &hf_mcc_pn_direction
,
997 { "MCC Direction", "btrfcomm.mcc.direction",
998 FT_UINT8
, BASE_HEX
, NULL
, 0x01,
999 "RFCOMM MCC Direction", HFILL
}
1001 { &hf_mcc_pn_zeros_padding
,
1002 { "Zeros padding", "btrfcomm.mcc.padding",
1003 FT_UINT8
, BASE_HEX
, NULL
, 0xC0,
1004 "RFCOMM MSC Zeros padding", HFILL
}
1007 { "MCC Command Type", "btrfcomm.mcc.cmd",
1008 FT_UINT8
, BASE_HEX
, VALS(vs_ctl
), 0xFC,
1012 { "Frame type", "btrfcomm.frame_type",
1013 FT_UINT8
, BASE_HEX
, VALS(vs_frame_type
), 0xEF,
1016 { &hf_acknowledgement_timer_t1
,
1017 { "Acknowledgement Timer T1", "btrfcomm.acknowledgement_timer_t1",
1018 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
1022 { "P/F flag", "btrfcomm.pf",
1023 FT_UINT8
, BASE_HEX
, NULL
, 0x10,
1024 "Poll/Final bit", HFILL
}
1027 { "Type of frame", "btrfcomm.pn.i",
1028 FT_UINT8
, BASE_HEX
, VALS(vs_ctl_pn_i
), 0x0F,
1029 "Type of information frames used for that particular DLCI",
1033 { "Convergence layer", "btrfcomm.pn.cl",
1034 FT_UINT8
, BASE_HEX
, VALS(vs_ctl_pn_cl
), 0xF0,
1035 "Convergence layer used for that particular DLCI", HFILL
}
1038 { "Payload length", "btrfcomm.len",
1039 FT_UINT16
, BASE_DEC
, NULL
, 0,
1040 "Frame length", HFILL
}
1043 { "MCC Length", "btrfcomm.mcc.len",
1044 FT_UINT16
, BASE_DEC
, NULL
, 0,
1045 "Length of MCC data", HFILL
}
1048 { "Frame Check Sequence", "btrfcomm.fcs",
1049 FT_UINT8
, BASE_HEX
, NULL
, 0,
1050 "Checksum over frame", HFILL
}
1052 { &hf_msc_parameters
,
1053 { "Parameters", "btrfcomm.mcc.msc_parameters",
1054 FT_NONE
, BASE_NONE
, NULL
, 0x00,
1058 { "Flow Control (FC)", "btrfcomm.msc.fc",
1059 FT_UINT8
, BASE_HEX
, NULL
, 0x02,
1063 { "Ready To Communicate (RTC)", "btrfcomm.msc.rtc",
1064 FT_UINT8
, BASE_HEX
, NULL
, 0x04,
1068 { "Ready To Receive (RTR)", "btrfcomm.msc.rtr",
1069 FT_UINT8
, BASE_HEX
, NULL
, 0x08,
1073 { "Incoming Call Indicator (IC)", "btrfcomm.msc.ic",
1074 FT_UINT8
, BASE_HEX
, NULL
, 0x40,
1078 { "Data Valid (DV)", "btrfcomm.msc.dv",
1079 FT_UINT8
, BASE_HEX
, NULL
, 0x80,
1083 { "Length of break in units of 200ms", "btrfcomm.msc.bl",
1084 FT_UINT8
, BASE_DEC
, NULL
, 0xF0,
1087 { &hf_msc_break_bits
,
1088 { "Break Bits", "btrfcomm.msc.break_bits",
1089 FT_UINT8
, BASE_DEC
, NULL
, 0xE0,
1093 { "Address", "btrfcomm.address",
1094 FT_NONE
, BASE_NONE
, NULL
, 0x00,
1098 { "Control", "btrfcomm.control",
1099 FT_NONE
, BASE_NONE
, NULL
, 0x00,
1103 { "Credits", "btrfcomm.credits",
1104 FT_UINT8
, BASE_DEC
, NULL
, 0,
1105 "Flow control: number of UIH frames allowed to send", HFILL
}
1110 /* Setup protocol subtree array */
1111 static int *ett
[] = {
1123 static ei_register_info ei
[] = {
1124 { &ei_btrfcomm_mcc_length_bad
, { "btrfcomm.mcc_length_bad", PI_MALFORMED
, PI_ERROR
, "Huge MCC length", EXPFILL
}},
1127 /* Decode As handling */
1128 static build_valid_func btrfcomm_directed_channel_da_build_value
[1] = {btrfcomm_directed_channel_value
};
1129 static decode_as_value_t btrfcomm_directed_channel_da_values
= {btrfcomm_directed_channel_prompt
, 1, btrfcomm_directed_channel_da_build_value
};
1130 static decode_as_t btrfcomm_directed_channel_da
= {"btrfcomm", "btrfcomm.dlci", 1, 0, &btrfcomm_directed_channel_da_values
, NULL
, NULL
,
1131 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
1133 /* Register the protocol name and description */
1134 proto_btrfcomm
= proto_register_protocol("Bluetooth RFCOMM Protocol", "BT RFCOMM", "btrfcomm");
1135 btrfcomm_handle
= register_dissector("btrfcomm", dissect_btrfcomm
, proto_btrfcomm
);
1137 /* Required function calls to register the header fields and subtrees used */
1138 proto_register_field_array(proto_btrfcomm
, hf
, array_length(hf
));
1139 proto_register_subtree_array(ett
, array_length(ett
));
1140 expert_btrfcomm
= expert_register_protocol(proto_btrfcomm
);
1141 expert_register_field_array(expert_btrfcomm
, ei
, array_length(ei
));
1143 service_directions
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1145 rfcomm_dlci_dissector_table
= register_dissector_table("btrfcomm.dlci", "BT RFCOMM Directed Channel", proto_btrfcomm
, FT_UINT16
, BASE_DEC
);
1147 module
= prefs_register_protocol_subtree("Bluetooth", proto_btrfcomm
, NULL
);
1148 prefs_register_static_text_preference(module
, "rfcomm.version",
1149 "Bluetooth Protocol RFCOMM version: 1.1", "Version of protocol supported by this dissector.");
1151 prefs_register_bool_preference(module
, "rfcomm.decode_by.enabled",
1152 "Enable Force Decode by Channel",
1153 "Turn on/off decode by next rules",
1154 &rfcomm_channels_enabled
);
1156 uat_rfcomm_channels
= uat_new("Force Decode by Channel",
1157 sizeof(uat_rfcomm_channels_t
),
1161 &num_rfcomm_channels
,
1162 UAT_AFFECTS_DISSECTION
,
1164 uat_rfcomm_channels_copy_cb
,
1166 uat_rfcomm_channels_free_cb
,
1169 uat_rfcomm_channels_fields
);
1171 prefs_register_uat_preference(module
, "rfcomm.channels",
1172 "Force Decode by channel",
1173 "Decode by channel",
1174 uat_rfcomm_channels
);
1176 register_decode_as(&btrfcomm_directed_channel_da
);
1180 proto_reg_handoff_btrfcomm(void)
1182 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_RFCOMM
, btrfcomm_handle
);
1183 dissector_add_for_decode_as("btl2cap.cid", btrfcomm_handle
);
1186 /* Bluetooth Dial-Up Networking (DUN) profile dissection */
1188 dissect_btdun(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1195 length
= tvb_captured_length(tvb
);
1197 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DUN");
1199 ti
= proto_tree_add_item(tree
, proto_btdun
, tvb
, 0, tvb_captured_length(tvb
), ENC_NA
);
1200 st
= proto_item_add_subtree(ti
, ett_btdun
);
1203 for(i
= 0; i
< length
&& is_at_cmd
; i
++) {
1204 is_at_cmd
= tvb_get_uint8(tvb
, i
) < 0x7d;
1208 /* presumably an AT command */
1209 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s \"%s\"",
1210 (pinfo
->p2p_dir
== P2P_DIR_SENT
) ? "Sent" : "Rcvd",
1211 tvb_format_text(pinfo
->pool
, tvb
, 0, length
));
1213 proto_tree_add_item(st
, hf_dun_at_cmd
, tvb
, 0, tvb_reported_length(tvb
), ENC_ASCII
|ENC_NA
);
1216 /* ... or raw PPP */
1218 call_dissector(ppp_handle
, tvb
, pinfo
, tree
);
1220 /* TODO: remove the above 'if' and this 'else-body' when "ppp_raw_hdlc" is available, requires that it is
1221 made non-anonymous in ppp dissector to use */
1222 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PPP");
1223 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s <PPP frame>", (pinfo
->p2p_dir
== P2P_DIR_SENT
) ? "Sent" : "Rcvd");
1225 call_data_dissector(tvb
, pinfo
, tree
);
1229 return tvb_reported_length(tvb
);
1233 proto_register_btdun(void)
1235 static hf_register_info hf
[] = {
1237 { "AT Cmd", "btdun.atcmd",
1238 FT_STRING
, BASE_NONE
, NULL
, 0,
1239 "AT Command", HFILL
}
1243 /* Setup protocol subtree array */
1244 static int *ett
[] = {
1248 proto_btdun
= proto_register_protocol("Bluetooth DUN Packet", "BT DUN", "btdun");
1249 btdun_handle
= register_dissector("btdun", dissect_btdun
, proto_btdun
);
1251 /* Required function calls to register the header fields and subtrees used */
1252 proto_register_field_array(proto_btdun
, hf
, array_length(hf
));
1253 proto_register_subtree_array(ett
, array_length(ett
));
1257 proto_reg_handoff_btdun(void)
1259 dissector_add_string("bluetooth.uuid", "1103", btdun_handle
);
1261 dissector_add_for_decode_as("btrfcomm.dlci", btdun_handle
);
1263 ppp_handle
= find_dissector_add_dependency("ppp_raw_hdlc", proto_btdun
);
1266 /* Bluetooth Serial Port profile (SPP) dissection */
1268 dissect_btspp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1274 unsigned length
= tvb_captured_length(tvb
);
1276 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SPP");
1278 ti
= proto_tree_add_item(tree
, proto_btspp
, tvb
, 0, tvb_captured_length(tvb
), ENC_NA
);
1279 st
= proto_item_add_subtree(ti
, ett_btspp
);
1281 length
= MIN(length
, 60);
1283 for(i
= 0; i
< length
&& ascii_only
; i
++) {
1284 ascii_only
= tvb_get_uint8(tvb
, i
) < 0x80;
1288 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s \"%s%s\"",
1289 (pinfo
->p2p_dir
== P2P_DIR_SENT
) ? "Sent" : "Rcvd",
1290 tvb_format_text(pinfo
->pool
, tvb
, 0, length
),
1291 (tvb_captured_length(tvb
) > length
) ? "..." : "");
1294 proto_tree_add_item(st
, hf_spp_data
, tvb
, 0, tvb_reported_length(tvb
), ENC_NA
);
1296 return tvb_reported_length(tvb
);
1300 proto_register_btspp(void)
1302 static hf_register_info hf
[] = {
1304 { "Data", "btspp.data",
1305 FT_BYTES
, BASE_NONE
, NULL
, 0,
1310 /* Setup protocol subtree array */
1311 static int *ett
[] = {
1315 proto_btspp
= proto_register_protocol("Bluetooth SPP Packet", "BT SPP", "btspp");
1316 btspp_handle
= register_dissector("btspp", dissect_btspp
, proto_btspp
);
1318 /* Required function calls to register the header fields and subtrees used */
1319 proto_register_field_array(proto_btspp
, hf
, array_length(hf
));
1320 proto_register_subtree_array(ett
, array_length(ett
));
1324 proto_reg_handoff_btspp(void)
1326 dissector_add_string("bluetooth.uuid", "1101", btspp_handle
);
1328 dissector_add_for_decode_as("btrfcomm.dlci", btspp_handle
);
1332 /* Bluetooth Global Navigation Satellite System profile (GNSS) dissection */
1334 dissect_btgnss(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1336 proto_item
*main_item
;
1337 proto_tree
*main_tree
;
1339 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "GNSS");
1341 main_item
= proto_tree_add_item(tree
, proto_btgnss
, tvb
, 0, tvb_captured_length(tvb
), ENC_NA
);
1342 main_tree
= proto_item_add_subtree(main_item
, ett_btgnss
);
1344 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s %s",
1345 (pinfo
->p2p_dir
== P2P_DIR_SENT
) ? "Sent" : "Rcvd",
1346 tvb_format_text(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
)));
1348 /* GNSS using NMEA-0183 protocol, but it is not available */
1349 proto_tree_add_item(main_tree
, hf_gnss_data
, tvb
, 0, tvb_reported_length(tvb
), ENC_NA
| ENC_ASCII
);
1351 return tvb_reported_length(tvb
);
1355 proto_register_btgnss(void)
1357 static hf_register_info hf
[] = {
1359 { "Data", "btgnss.data",
1360 FT_STRING
, BASE_NONE
, NULL
, 0,
1365 static int *ett
[] = {
1369 proto_btgnss
= proto_register_protocol("Bluetooth GNSS Profile", "BT GNSS", "btgnss");
1370 btgnss_handle
= register_dissector("btgnss", dissect_btgnss
, proto_btgnss
);
1372 proto_register_field_array(proto_btgnss
, hf
, array_length(hf
));
1373 proto_register_subtree_array(ett
, array_length(ett
));
1377 proto_reg_handoff_btgnss(void)
1379 dissector_add_string("bluetooth.uuid", "1135", btgnss_handle
);
1380 dissector_add_string("bluetooth.uuid", "1136", btgnss_handle
);
1382 dissector_add_for_decode_as("btrfcomm.dlci", btgnss_handle
);
1386 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1391 * indent-tabs-mode: nil
1394 * vi: set shiftwidth=4 tabstop=8 expandtab:
1395 * :indentSize=4:tabSize=8:noTabs=true: