diff -Nur ethereal-0.9.7/Makefile.am ethereal-0.9.7-patched/Makefile.am --- ethereal-0.9.7/Makefile.am 2002-09-29 21:10:05.000000000 +0200 +++ ethereal-0.9.7-patched/Makefile.am 2002-10-09 17:58:31.000000000 +0200 @@ -372,7 +372,16 @@ packet-yppasswd.c \ packet-ypserv.c \ packet-ypxfr.c \ - packet-zebra.c + packet-zebra.c \ + packet-affix-hci.c \ + packet-bthci-cmd.c \ + packet-bthci-evt.c \ + packet-btacl.c \ + packet-btsco.c \ + packet-btl2cap.c \ + packet-btbnep.c \ + packet-btrfcomm.c \ + packet-btsdp.c if HAVE_PLUGINS plugin_src = \ @@ -579,7 +588,8 @@ packet-ypbind.h \ packet-yppasswd.h \ packet-ypserv.h \ - packet-ypxfr.h + packet-ypxfr.h \ + packet-bthci-cmd.h ETHEREAL_COMMON_SRC = \ afn.c \ diff -Nur ethereal-0.9.7/packet-affix-hci.c ethereal-0.9.7-patched/packet-affix-hci.c --- ethereal-0.9.7/packet-affix-hci.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-affix-hci.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,202 @@ +/* packet-affix-hci.c + * Routines for the Affix HCI dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include + +/* Initialize the protocol and registered fields */ +static int proto_affix_hci = -1; +static int hf_affix_hci_type = -1; + +/* Initialize the subtree pointers */ +static gint ett_affix_hci = -1; + + + +static const value_string affix_hci_type_vals[] = { + {1, "HCI Command"}, + {2, "ACL Data"}, + {3, "SCO Data"}, + {4, "HCI Event"}, +}; + + +/* Code to actually dissect the packets */ +static void +dissect_affix_hci(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + + guint16 ptype, rtype; + tvbuff_t *next_tvb; + tvbuff_t *affix_hci_tvb; + dissector_handle_t bthci_cmd_handle, bthci_evt_handle; + dissector_handle_t btacl_handle, btsco_handle; + + proto_item *ti; + proto_tree *affix_hci_tree; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "affix_hci"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + + ptype = tvb_get_ntohs(tvb, 0); + rtype = tvb_get_guint8(tvb, 16); + + if (ptype == 0) { /* Packet has been received */ + pinfo->p2p_dir = P2P_DIR_RECV; + if (rtype == 2) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Incoming ACL"); + } + if (rtype == 3) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Incoming SCO"); + } + if (rtype == 4) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Event"); + } + } + else if (ptype == 4) { /* Packet has been sent */ + pinfo->p2p_dir = P2P_DIR_SENT; + if (rtype == 1) { /* Command */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Command"); + } + else if (rtype == 2) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Outgoing ACL"); + } + else if (rtype == 3) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Outgoing SCO"); + } + + } + + affix_hci_tvb = tvb_new_subset(tvb, 16, -1, -1); + next_tvb = tvb_new_subset(tvb, 17, -1, -1); + + ti = proto_tree_add_item(tree, proto_affix_hci, affix_hci_tvb, 0, -1, FALSE); + affix_hci_tree = proto_item_add_subtree(ti, ett_affix_hci); + + proto_tree_add_item(affix_hci_tree, hf_affix_hci_type, + affix_hci_tvb, 0, 1, TRUE); + + if (rtype == 1) { /* Command */ + bthci_cmd_handle = find_dissector("bthci_cmd"); + call_dissector(bthci_cmd_handle, next_tvb, pinfo, tree); + } + else if (rtype == 2) { /* ACL */ + btacl_handle = find_dissector("btacl"); + call_dissector(btacl_handle, next_tvb, pinfo, tree); + } + else if (rtype == 3) { /* SCO */ + btsco_handle = find_dissector("btsco"); + call_dissector(btsco_handle, next_tvb, pinfo, tree); + } + if (rtype == 4) { /* Event */ + bthci_evt_handle = find_dissector("bthci_evt"); + call_dissector(bthci_evt_handle, next_tvb, pinfo, tree); + } +} + + +/* Register the protocol with Ethereal */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_affix_hci(void) +{ + +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_affix_hci_type, + { "HCI Packet Type", "affix.type", + FT_UINT8, BASE_HEX, VALS(affix_hci_type_vals), 0x0, + "HCI Packet Type" } + }, + }; + +/* Setup protocol subtree array */ + static gint *ett[] = { + &ett_affix_hci, + }; + +/* Register the protocol name and description */ + proto_affix_hci = proto_register_protocol("Affix HCI", + "Affix_HCI", "affix_hci"); + + register_dissector("affix_hci", dissect_affix_hci, proto_affix_hci); + + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_affix_hci, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_bthci(void) +{ + dissector_handle_t affix_hci_handle; + + affix_hci_handle = find_dissector("affix_hci"); +} + + diff -Nur ethereal-0.9.7/packet-btacl.c ethereal-0.9.7-patched/packet-btacl.c --- ethereal-0.9.7/packet-btacl.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btacl.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,374 @@ +/* packet-btacl.c + * Routines for the Bluetooth ACL dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include + +/* Initialize the protocol and registered fields */ +static int proto_btacl = -1; +static int hf_btacl_chandle = -1; +static int hf_btacl_pb_flag = -1; +static int hf_btacl_bc_flag = -1; +static int hf_btacl_length = -1; +static int hf_btacl_data = -1; + +/* Initialize the subtree pointers */ +static gint ett_btacl = -1; + + +static const value_string pb_flag_vals[] = { + {1, "Continuing Fragment"}, + {2, "Start Fragment"}, +}; + +static const value_string bc_flag_vals[] = { + {0, "Point-To-Point"}, + {1, "Active Broadcast"}, + {2, "Piconet Broadcast"}, +}; + +typedef struct { + guint16 handle; + struct l2cap_packet *l2p; +} handle_info; +#define HANDLE_TABLE_SIZE 20 + +static handle_info handle_table[HANDLE_TABLE_SIZE]; + +struct l2cap_packet { + guint8 data [65540]; + guint32 packet_len; + guint32 recvd_len; +}; + +static struct l2cap_packet *add_l2p(guint16 handle) { + handle_info *t = handle_table; + int i; + + for (i=0; i> 12; + + + /* determine if packet is fragmented */ + if (pb_flag == 1) { /* Continuing fragment */ + fragmented = TRUE; + } + else if (pb_flag == 2) { /* Start fragment */ + if (length < 2) { + fragmented = TRUE; + } + else { + l2cap_length = tvb_get_letohs(tvb, 4); + fragmented = ((l2cap_length + 4) != length); + } + } + else { /* unknown pb_flag */ + fragmented = FALSE; + } + + + if (!fragmented) { + /* call L2CAP dissector */ + next_tvb = tvb_new_subset(tvb, 4, -1, -1); + btl2cap_handle = find_dissector("btl2cap"); + call_dissector(btl2cap_handle, next_tvb, pinfo, tree); + } + else { + proto_tree_add_item(btacl_tree, hf_btacl_data, tvb, 4, -1, TRUE); + + if (pinfo->fd->flags.visited == 0) { /* This is the first pass */ + + chandle = tvb_get_letohs(tvb, 0) & 0x0FFF; + + /* same connection handle but differnet direction needs to be + distinguished, therefore we set the highest bit of the + handle for outgoing packets */ + if (pinfo->p2p_dir == P2P_DIR_RECV) { + handle = chandle; + } + else { + handle = chandle + 0x8000; + } + + + l2p = NULL; + if (pb_flag == 2) { /* Start Fragment */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_str(pinfo->cinfo, COL_INFO, " (Start Fragment)"); + + if (get_l2p(handle)) { /* Error: There is still data for the same handle */ + fprintf(stderr, "Incomplete L2CAP packet detected: packet no. %d\n", pinfo->fd->num); + del_l2p(handle); + } + + /* Start reassembly */ + if ((l2p = add_l2p(handle))) { + l2p->packet_len = 65540; /* Maybe we don't know the length now */ + /* So we have to set it to maximum */ + + /* memcpy the data */ + tvb_memcpy(tvb, l2p->data, 4, length); + l2p->recvd_len = length; + } + else { + fprintf(stderr, "no more handles!\n"); + } + + } + + if (pb_flag == 1) { /* Continuing Fragment */ + if (!(l2p = get_l2p(handle))) { /* Error: Cont fragment without start */ + fprintf(stderr, "Cont. fragment without start detected!\n"); + } + else { /* OK: Continue reassembly */ + + /* memcpy the data */ + tvb_memcpy(tvb, (l2p->data)+l2p->recvd_len, 4, length); + l2p->recvd_len += length; + } + } + + + if (l2p) { + if (l2p->recvd_len > 1) { /* We have collected enough bytes */ + l2p->packet_len = ((l2p->data)[0])+256*((l2p->data)[1])+4; + } + + if (l2p->recvd_len > l2p->packet_len) { + fprintf(stderr, "Packet too long!\n"); + del_l2p(handle); + l2p = NULL; + } + + else if (l2p->recvd_len == l2p->packet_len) { + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_str(pinfo->cinfo, COL_INFO, " (End Fragment)"); + + reassembled_packet = malloc(sizeof(struct l2cap_packet)); + memcpy(reassembled_packet, l2p, sizeof(struct l2cap_packet)); + l2p = reassembled_packet; + + p_add_proto_data(pinfo->fd, proto_btacl, reassembled_packet); + + del_l2p(handle); + } + + else { /* Packet is not complete */ + l2p = NULL; + if (pb_flag == 1) { + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_str(pinfo->cinfo, COL_INFO, " (Continuation Fragment)"); + } + } + } + } + else { /* This is an additional pass */ + l2p = p_get_proto_data(pinfo->fd, proto_btacl); /* Is there a reassembled packet saved ? */ + } + + if (l2p) { + next_tvb = tvb_new_real_data(l2p->data, l2p->packet_len, + l2p->packet_len); + tvb_set_child_real_data_tvbuff(tvb, next_tvb); + add_new_data_source(pinfo, next_tvb, "Reassembled L2CAP"); + + /* call L2CAP dissector */ + btl2cap_handle = find_dissector("btl2cap"); + call_dissector(btl2cap_handle, next_tvb, pinfo, tree); + } + + } + +} + + +/* Register the protocol with Ethereal */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_btacl(void) +{ + +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_btacl_chandle, + { "Connection Handle", "btacl.chandle", + FT_UINT16, BASE_HEX, NULL, 0x0FFF, + "Connection Handle" } + }, + { &hf_btacl_pb_flag, + { "PB Flag", "btacl.pb_flag", + FT_UINT16, BASE_BIN, VALS(pb_flag_vals), 0x3000, + "Packet Boundary Flag" } + }, + { &hf_btacl_bc_flag, + { "BC Flag", "btacl.bc_flag", + FT_UINT16, BASE_BIN, VALS(bc_flag_vals), 0xC000, + "Broadcast Flag" } + }, + { &hf_btacl_length, + { "Data Total Length", "btacl.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Data Total Length" } + }, + { &hf_btacl_data, + { "Data", "btacl.data", + FT_NONE, BASE_NONE, NULL, 0x0, + "Data" } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_btacl, + }; + +/* Register the protocol name and description */ + proto_btacl = proto_register_protocol("Bluetooth ACL Packet", + "ACL", "btacl"); + + register_dissector("btacl", dissect_btacl, proto_btacl); + + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_btacl, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_init_routine(l2cap_defragment_init); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_btacl(void) +{ + dissector_handle_t btacl_handle; + + btacl_handle = find_dissector("btacl"); + +} + + diff -Nur ethereal-0.9.7/packet-btbnep.c ethereal-0.9.7-patched/packet-btbnep.c --- ethereal-0.9.7/packet-btbnep.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btbnep.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,724 @@ +/* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ + +/* packet-btbnep.c + * Routines for the Bluetooth BNEP dissection + * Copyright 2002, Wolfgang Hansmann + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include +#include + +#include "packet-btbnep.h" + +extern dissector_table_t ethertype_dissector_table; + +/* Initialize the protocol and registered fields */ +static int proto_btbnep = -1; + +static int hf_btbnep_type = -1; +static int hf_btbnep_extflag = -1; + +static int hf_btbnep_exthdr_type = 1; +static int hf_btbnep_exthdr_extflag = 1; +static int hf_btbnep_exthdr_len = 1; + +static int hf_btbnep_cmd_type = 1; + +static int hf_btbnep_conn_resp_msg = -1; + +static int hf_btbnep_src = -1; +static int hf_btbnep_dst = -1; +static int hf_btbnep_proto = -1; + +static int hf_btbnep_src_uuid = -1; +static int hf_btbnep_dst_uuid = -1; + +static int hf_btbnep_pset_list_len = -1; + +static int hf_btbnep_pres_msg = -1; +static int hf_btbnep_mres_msg = -1; + +/* Initialize the subtree pointers */ + +static gint ett_btbnep = -1; +static gint ett_btbnep_ethgen = -1; +static gint ett_btbnep_eth = 1; +static gint ett_btbnep_ethdst = 1; +static gint ett_btbnep_ethsrc = 1; +static gint ett_btbnep_exthdr = 1; +static gint ett_btbnep_cmd = 1; + +static dissector_handle_t data_handle; +static dissector_handle_t llc_handle; +static dissector_handle_t ipx_handle; + +static const value_string vs_extension_type[] = { + {0x0, "Control Extension Header"}, + {0x0, NULL} +}; + +static const value_string vs_type[] = { + {BTBNEP_TYPE_GENERAL_ETHERNET, "General Ethernet"}, + {BTBNEP_TYPE_CONTROL, "Control Packet"}, + {BTBNEP_TYPE_COMPRESSED_ETHERNET, "Compressed Ethernet"}, + {BTBNEP_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY, + "Compressed Ethernet Source only"}, + {BTBNEP_TYPE_COMPRESSED_ETHERNET_DEST_ONLY, + "Compressed Ethernet Destination only"}, + {0x0, NULL} +}; + +static const value_string vs_control_type[] = { + {BTBNEP_CONTROL_CMD_NOT_UNDERSTOOD, "Command not understood"}, + {BTBNEP_SETUP_CONN_REQ_MSG, "Setup Connection Request"}, + {BTBNEP_SETUP_CONN_RESP_MSG, "Setup Connection Response"}, + {BTBNEP_FILTER_NET_TYPE_SET_MSG, "Filter Net Type Set"}, + {BTBNEP_FILTER_NET_TYPE_RESP_MSG, "Filter Net Type Response"}, + {BTBNEP_FILTER_MULTI_ADDR_SET_MSG, "Multicast Addr. Set"}, + {BTBNEP_FILTER_MULTI_ADDR_RESP_MSG, "Multicast Addr. Response"}, + {0x0, NULL} +}; + +static const value_string vs_conn_resp_msg[] = { + {BTBNEP_CONN_MSG_SUCCESS, "Operation Successful"}, + {BTBNEP_CONN_MSG_INV_DST_UUID, "Operation Failed: Invalid Dest. Service UUID"}, + {BTBNEP_CONN_MSG_INV_SRC_UUID, "Operation Failed: Invalid Src. Service UUID"}, + {BTBNEP_CONN_MSG_INV_UUID_SIZE, "Operation Failed: Invalid Service UUID Size"}, + {BTBNEP_CONN_MSG_CONN_NOT_ALLOWED, "Operation Failed: Connection not allowed"}, + {0x0, NULL} +}; + +static const value_string vs_proto_filter_resp_msg[] = { + {BTBNEP_FLT_SUCCESS, "Operation Successful"}, + {BTBNEP_FLT_UNSUPPORTED, "Unsupported Request"}, + {BTBNEP_FLT_INV_RANGE, "Operation Failed: Invalid " + "Networking Protocol Range"}, + {BTBNEP_FLT_LIMIT_REACHED, "Operation Failed: Max. " + "Protocol Filter Limit Reached"}, + {BTBNEP_CONN_MSG_CONN_NOT_ALLOWED, "Operation Failed: " + "Unable to fulfill request due to security reasons"}, + {0x0, NULL} +}; + +static const value_string vs_mc_filter_resp_msg[] = { + {BTBNEP_MC_SUCCESS, "Operation Successful"}, + {BTBNEP_MC_UNSUPPORTED, "Unsupported Request"}, + {BTBNEP_MC_INV_RANGE, "Operation Failed: Invalid Multicast Addr. Range"}, + {BTBNEP_MC_LIMIT_REACHED, "Operation Failed: Max. Multicast Address " + "Filter Limit reached"}, + {BTBNEP_MC_SEC_NOT_ALLOWED, "Operation Failed: Unable to fulfill " + "request due to security reasons"}, + {0x0, NULL} +}; + + +static const value_string vs_extension_flag[] = { + {0, "Last Extension Header"}, + {1, "More Extension Headers following"}, + {0, NULL} +}; + +static int dissect_type_ethfull(tvbuff_t *tvb, proto_tree *tree, int off, + guint16 *ethertype) { + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 14) { + proto_tree_add_text(tree, tvb, off, len, "Garbled General " + "Ethernet Packet Type Header"); + return -1; + } + + proto_tree_add_item(tree, hf_btbnep_dst, tvb, off, 6, FALSE); + proto_tree_add_item(tree, hf_btbnep_src, tvb, off + 6, 6, FALSE); + proto_tree_add_item(tree, hf_btbnep_proto, tvb, off + 12, 2, FALSE); + + *ethertype = tvb_get_ntohs(tvb, off + 12); + + return 14; +} + + +static int dissect_type_eth(tvbuff_t *tvb, proto_tree *tree, int off, + guint16 *ethertype) { + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, len, "Garbled Compressed " + "Ethernet Packet Type Header"); + return -1; + } + proto_tree_add_item(tree, hf_btbnep_proto, tvb, off, 2, FALSE); + + *ethertype = tvb_get_ntohs(tvb, off); + + return 2; +} + + +static int dissect_type_ethsrc(tvbuff_t *tvb, proto_tree *tree, int off, + guint16 *ethertype) { + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 8) { + proto_tree_add_text(tree, tvb, off, len, "Garbled Compressed " + "Ethernet Source only Packet Type Header"); + return -1; + } + + proto_tree_add_item(tree, hf_btbnep_src, tvb, off, 6, FALSE); + proto_tree_add_item(tree, hf_btbnep_proto, tvb, off + 6, 2, FALSE); + + *ethertype = tvb_get_ntohs(tvb, off + 6); + + return 8; +} + + +static int dissect_type_ethdst(tvbuff_t *tvb, proto_tree *tree, int off, + guint16 *ethertype) { + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 8) { + proto_tree_add_text(tree, tvb, off, len, "Garbled Compressed " + "Ethernet Destination only Packet Type Header"); + return -1; + } + + proto_tree_add_item(tree, hf_btbnep_dst, tvb, off, 6, FALSE); + proto_tree_add_item(tree, hf_btbnep_proto, tvb, off + 6, 2, FALSE); + + *ethertype = tvb_get_ntohs(tvb, off + 6); + + return 8; +} + + +static int dissect_extension(tvbuff_t *tvb, proto_tree *tree, int off) { + + proto_tree *st; + proto_item *it; + int len, size; + guint8 type; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, len, "Garbled Extension Header"); + return -1; + } + + type = tvb_get_guint8(tvb, off); + + it = proto_tree_add_text(tree, tvb, off, 1, "Extension header"); + st = proto_item_add_subtree(it, ett_btbnep_exthdr); + + proto_tree_add_item(st, hf_btbnep_exthdr_type, tvb, off, 1, FALSE); + proto_tree_add_item(st, hf_btbnep_exthdr_extflag, tvb, off, 1, FALSE); + proto_tree_add_item(st, hf_btbnep_exthdr_len, tvb, off + 1, 1, FALSE); + + len = tvb_get_guint8(tvb, off + 1); + proto_item_set_len(it, len + 2); + + switch(type & 0x7f) { + case 0x0: + size = dissect_type_control(tvb, st, off + 2); + proto_item_append_text(it, " (Command extension)"); + if (size == -1) + return -1; + break; + default: + proto_item_append_text(it, " (Unknown Extension type 0x%x)", + type & 0x7f); + } + return 2 + len; +} + + +static int dissect_ctr_err(tvbuff_t *tvb, proto_tree *tree, int off) { + + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 1) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + proto_tree_add_text(tree, tvb, off, 1, "Unknown opcode was: 0x%x", + tvb_get_guint8(tvb, off)); + return 1; +} + + +static int dissect_ctr_conreq(tvbuff_t *tvb, proto_tree *tree, int off) { + + gint uuid_size; + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 1) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + uuid_size = tvb_get_guint8(tvb, off); + proto_tree_add_text(tree, tvb, off, 1, "UUID Size: %d", + uuid_size); + if (len < 1 + uuid_size * 2) { + proto_tree_add_text(tree, tvb, off + 1, -1, "Garbled"); + return -1; + } + proto_tree_add_bytes(tree, hf_btbnep_dst_uuid, tvb, off + 1, uuid_size, + tvb_get_ptr(tvb, off + 1, uuid_size)); + proto_tree_add_bytes(tree, hf_btbnep_src_uuid, tvb, off + 1 + uuid_size, + uuid_size, + tvb_get_ptr(tvb, off + 1 + uuid_size, uuid_size)); + + return 1 + 2 * uuid_size; +} + + +static int dissect_ctr_conres(tvbuff_t *tvb, proto_tree *tree, int off) { + + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + proto_tree_add_item(tree, hf_btbnep_conn_resp_msg, tvb, off, 2, 0); + return 2; +} + + +static int dissect_ctr_pset(tvbuff_t *tvb, proto_tree *tree, int off) { + + int i, len, off_tmp; + guint16 list_length; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + + list_length = tvb_get_ntohs(tvb, off); + proto_tree_add_uint(tree, hf_btbnep_pset_list_len, tvb, + off, 2, list_length); + if (len < 2 + list_length || (list_length % 4) != 0) { + proto_tree_add_text(tree, tvb, off + 2, -1, "Garbled"); + return -1; + } + + for (off_tmp = off + 2, i = 0; i < list_length; i += 4, off_tmp += 4) { + proto_tree_add_text(tree, tvb, off_tmp, 4, + "Allowed Protocol Range: 0x%x - 0x%x", + tvb_get_ntohs(tvb, off_tmp), + tvb_get_ntohs(tvb, off_tmp + 2)); + } + + return 2 + list_length; +} + + +static int dissect_ctr_pres(tvbuff_t *tvb, proto_tree *tree, int off) { + + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + + proto_tree_add_uint(tree, hf_btbnep_pres_msg, tvb, off, 2, + tvb_get_ntohs(tvb, off)); + + return 2; +} + + +static int dissect_ctr_mset(tvbuff_t *tvb, proto_tree *tree, int off) { + + int i, len, off_tmp; + guint16 list_length; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + + list_length = tvb_get_ntohs(tvb, off); + + proto_tree_add_uint(tree, hf_btbnep_pset_list_len, tvb, + off, 2, list_length); + if (len < 2 + list_length || (list_length % 12) != 0) { + proto_tree_add_text(tree, tvb, off + 2, -1, "Garbled"); + return -1; + } + + for (off_tmp = off + 2, i = 0; i < list_length; i += 12, off_tmp += 12) { + + char buf1[32], buf2[32]; + + strncpy(buf1, ether_to_str(tvb_get_ptr(tvb, off_tmp, 6)), 32); + strncpy(buf2, ether_to_str(tvb_get_ptr(tvb, off_tmp + 6, 6)), 32); + buf1[31] = buf2[31] = 0; + + proto_tree_add_text(tree, tvb, off_tmp, 12, + "Allowed Multicast Range: %s - %s", buf1, buf2); + } + return 2 + list_length; +} + + +static int dissect_ctr_mres(tvbuff_t *tvb, proto_tree *tree, int off) { + + int len; + + len = tvb_length_remaining(tvb, off); + if (len < 2) { + proto_tree_add_text(tree, tvb, off, -1, "Garbled"); + return -1; + } + + proto_tree_add_uint(tree, hf_btbnep_mres_msg, tvb, off, 2, + tvb_get_ntohs(tvb, off)); + return 2; +} + + +static int dissect_type_control(tvbuff_t *tvb, proto_tree *tree, int off) { + + proto_tree *st; + proto_item *it; + int len, size; + guint8 type; + + len = tvb_length_remaining(tvb, off); + if (len < 1) { + proto_tree_add_text(tree, tvb, off, len, "Garbled Compressed " + "Command Packet"); + return -1; + } + + it = proto_tree_add_item(tree, hf_btbnep_cmd_type, tvb, off, 1, FALSE); + st = proto_item_add_subtree(it, ett_btbnep_cmd); + + type = tvb_get_guint8(tvb, off); + + off++; + + switch(type) { + case BTBNEP_CONTROL_CMD_NOT_UNDERSTOOD: + size = dissect_ctr_err(tvb, st, off); + break; + case BTBNEP_SETUP_CONN_REQ_MSG: + size = dissect_ctr_conreq(tvb, st, off); + break; + case BTBNEP_SETUP_CONN_RESP_MSG: + size = dissect_ctr_conres(tvb, st, off); + break; + case BTBNEP_FILTER_NET_TYPE_SET_MSG: + size = dissect_ctr_pset(tvb, st, off); + break; + case BTBNEP_FILTER_NET_TYPE_RESP_MSG: + size = dissect_ctr_pres(tvb, st, off); + break; + case BTBNEP_FILTER_MULTI_ADDR_SET_MSG: + size = dissect_ctr_mset(tvb, st, off); + break; + case BTBNEP_FILTER_MULTI_ADDR_RESP_MSG: + size = dissect_ctr_mres(tvb, st, off); + break; + default: + /* TODO: display error */ + size = -1; + } + if (size == -1) + return -1; + + proto_item_set_len(it, 1 + size); + return size + 1; +} + +/* Code to actually dissect the packets */ + +static void dissect_btbnep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + gchar *col_info = ""; + proto_item *ti, *ti_type; + proto_tree *st, *st_type; + guint8 type, off = 1, size, extflag; + guint16 ethertype = 0; + tvbuff_t *next_tvb; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "BNEP"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + if (tvb_length_remaining(tvb, 0) < 1) + return; + + ti = proto_tree_add_item(tree, proto_btbnep, tvb, 0, -1, FALSE); + st = proto_item_add_subtree(ti, ett_btbnep); + + ti_type = proto_tree_add_text(st, tvb, 0, 1, "Type: "); + st_type = proto_item_add_subtree(ti_type, ett_btbnep); + + proto_tree_add_item(st_type, hf_btbnep_type, tvb, 0, 1, TRUE); + proto_tree_add_item(st_type, hf_btbnep_extflag, tvb, 0, 1, TRUE); + + type = tvb_get_guint8(tvb, 0); + extflag = type & 0x80; + type = type & 0x7f; + + col_info = val_to_str(type & 0x7f, VALS(vs_type), "%s"); + if (!col_info) + col_info = "(Unknown)"; + + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_fstr(pinfo->cinfo, COL_INFO, col_info); + proto_item_append_text(ti, " (%s)", col_info); + proto_item_append_text(ti_type, "%s (0x%x), Extension flag: %d", + col_info, type, extflag ? 1 : 0); + + switch (type) { + case BTBNEP_TYPE_GENERAL_ETHERNET: + size = dissect_type_ethfull(tvb, st, off, ðertype); + break; + case BTBNEP_TYPE_CONTROL: + size = dissect_type_control(tvb, st, off); + break; + case BTBNEP_TYPE_COMPRESSED_ETHERNET: + size = dissect_type_eth(tvb, st, off, ðertype); + break; + case BTBNEP_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY: + size = dissect_type_ethsrc(tvb, st, off, ðertype); + break; + case BTBNEP_TYPE_COMPRESSED_ETHERNET_DEST_ONLY: + size = dissect_type_ethdst(tvb, st, off, ðertype); + break; + default: + /* error */ + size = -1; + } + + if (size < 2) + return; + + off += size; + + while (extflag) { + + size = dissect_extension(tvb, st, off); + if (size < 1) + break; + + extflag = tvb_get_guint8(tvb, off) & 0x80; + off += size; + } + + /* set length of ti */ + + next_tvb = tvb_new_subset(tvb, off, -1, -1); + proto_item_set_len(ti, off); + + if (ethertype) { + if (ethertype <= IEEE_802_3_MAX_LEN) { + + if (tvb_get_ntohs(next_tvb, off) == 0xffff) + call_dissector(ipx_handle, next_tvb, pinfo, tree); + else + call_dissector(llc_handle, next_tvb, pinfo, tree); + + } else { + + if (!dissector_try_port(ethertype_dissector_table, + (guint32) ethertype, + next_tvb, pinfo, tree)) + call_dissector(data_handle, next_tvb, pinfo, tree); + } + } +} + + + +void proto_register_btbnep(void) +{ + static hf_register_info hf[] = { + {&hf_btbnep_type, + {"Type", "btbnep.type", + FT_UINT8, BASE_HEX, &vs_type, 0x7f, + "BNEP Packet Type", HFILL} + }, + {&hf_btbnep_extflag, + {"Extension flag", "btbnep.extflag", + FT_UINT8, BASE_HEX, NULL, 0x80, + "Extension flag", HFILL} + }, + {&hf_btbnep_src, + {"Source MAC", "btbnep.src", + FT_ETHER, BASE_NONE, NULL, 0x0, "Source MAC", HFILL} + }, + {&hf_btbnep_dst, + {"Destination MAC", "btbnep.dst", + FT_ETHER, BASE_NONE, NULL, 0x0, "Destination MAC", HFILL} + }, + {&hf_btbnep_proto, + {"Protocol type", "btbnep.proto", + FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, + "Protocol Type", HFILL} + }, + {&hf_btbnep_cmd_type, + {"Command type", "btbnep.cmdtype", + FT_UINT8, BASE_HEX, VALS(vs_control_type), 0x0, + "Command Type", HFILL} + }, + {&hf_btbnep_exthdr_type, + {"Extension Type", "btbnep.ext_type", + FT_UINT8, BASE_HEX, VALS(vs_extension_type), 0x7f, + "Extension Type", HFILL} + }, + {&hf_btbnep_exthdr_extflag, + {"Extension Flag", "btbnep.ext_flag", + FT_UINT8, BASE_HEX, VALS(vs_extension_flag), 0x80, + "Extension Flag", HFILL} + }, + {&hf_btbnep_exthdr_len, + {"Extension Length", "btbnep.ext_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Extension Length", HFILL} + }, + {&hf_btbnep_src_uuid, + {"Source Service UUID", "btbnep.SS_uuid", + FT_BYTES, BASE_HEX, NULL, 0x0, "Source Service UUID (hex)", + HFILL} + }, + {&hf_btbnep_dst_uuid, + {"Destination Service UUID", "btbnep.DS_uuid", + FT_BYTES, BASE_HEX, NULL, 0x0, "Destination Service UUID " + "(hex)", HFILL} + }, + {&hf_btbnep_conn_resp_msg, + {"Response Message", "btbnep.cresp_mess", + FT_UINT16, BASE_HEX, VALS(vs_conn_resp_msg), 0x0, + "Response Message", HFILL} + }, + {&hf_btbnep_pset_list_len, + {"List Length", "btbnep.list_length", + FT_UINT16, BASE_DEC, NULL, 0x0, "List Length", HFILL} + }, + {&hf_btbnep_pres_msg, + {"Response Message", "btbnep.presp_mess", + FT_UINT16, BASE_HEX, VALS(vs_proto_filter_resp_msg), + 0x0, "Response Message", HFILL} + }, + {&hf_btbnep_mres_msg, + {"Response Message", "btbnep.mresp_mess", + FT_UINT16, BASE_HEX, VALS(vs_mc_filter_resp_msg), + 0x0, "Response Message", HFILL} + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_btbnep, + &ett_btbnep_ethgen, + &ett_btbnep_eth, + &ett_btbnep_ethdst, + &ett_btbnep_ethsrc, + &ett_btbnep_exthdr, + &ett_btbnep_cmd + }; + +/* Register the protocol name and description */ + + proto_btbnep = proto_register_protocol("Bluetooth BNEP Packet", + "BNEP", "btbnep"); + + register_dissector("btbnep", dissect_btbnep, proto_btbnep); + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_btbnep, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_btbnep(void) +{ + dissector_handle_t btbnep_handle; + + btbnep_handle = find_dissector("btbnep"); + dissector_add("btl2cap.psm", 0x000f, btbnep_handle); + + data_handle = find_dissector("data"); + ipx_handle = find_dissector("ipx"); + llc_handle = find_dissector("llc"); +} + + + + + + + + + + + + diff -Nur ethereal-0.9.7/packet-btbnep.h ethereal-0.9.7-patched/packet-btbnep.h --- ethereal-0.9.7/packet-btbnep.h 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btbnep.h 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,57 @@ +#ifndef ETHEREAL_PACKET_BTBNEP_H +#define ETHEREAL_PACKET_BTBNEP_H + +/* packet types */ + +#define BTBNEP_TYPE_GENERAL_ETHERNET 0 +#define BTBNEP_TYPE_CONTROL 1 +#define BTBNEP_TYPE_COMPRESSED_ETHERNET 2 +#define BTBNEP_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY 3 +#define BTBNEP_TYPE_COMPRESSED_ETHERNET_DEST_ONLY 4 + +/* command types */ + +#define BTBNEP_CONTROL_CMD_NOT_UNDERSTOOD 0 +#define BTBNEP_SETUP_CONN_REQ_MSG 1 +#define BTBNEP_SETUP_CONN_RESP_MSG 2 +#define BTBNEP_FILTER_NET_TYPE_SET_MSG 3 +#define BTBNEP_FILTER_NET_TYPE_RESP_MSG 4 +#define BTBNEP_FILTER_MULTI_ADDR_SET_MSG 5 +#define BTBNEP_FILTER_MULTI_ADDR_RESP_MSG 6 + +/* setup connection response messages */ + +#define BTBNEP_CONN_MSG_SUCCESS 0 +#define BTBNEP_CONN_MSG_INV_DST_UUID 1 +#define BTBNEP_CONN_MSG_INV_SRC_UUID 2 +#define BTBNEP_CONN_MSG_INV_UUID_SIZE 3 +#define BTBNEP_CONN_MSG_CONN_NOT_ALLOWED 4 + +/* protocol filter response messages */ + +#define BTBNEP_FLT_SUCCESS 0 +#define BTBNEP_FLT_UNSUPPORTED 1 +#define BTBNEP_FLT_INV_RANGE 2 +#define BTBNEP_FLT_LIMIT_REACHED 3 +#define BTBNEP_FLT_SEC_NOT_ALLOWED 4 + +/* multicast filter response messages */ + +#define BTBNEP_MC_SUCCESS 0 +#define BTBNEP_MC_UNSUPPORTED 1 +#define BTBNEP_MC_INV_RANGE 2 +#define BTBNEP_MC_LIMIT_REACHED 3 +#define BTBNEP_MC_SEC_NOT_ALLOWED 4 + + + +static int dissect_type_control(tvbuff_t *, proto_tree *, int); + +#endif /* ETHEREAL_PACKET_BTBNEP_H */ + + + + + + + diff -Nur ethereal-0.9.7/packet-bthci-cmd.c ethereal-0.9.7-patched/packet-bthci-cmd.c --- ethereal-0.9.7/packet-bthci-cmd.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-bthci-cmd.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,1445 @@ +/* packet-bthci-cmd.c + * Routines for the Bluetooth HCI Command dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include + +#include + +/* Initialize the protocol and registered fields */ +static int proto_bthci_cmd = -1; +static int hf_bthci_cmd_opcode = -1; +static int hf_bthci_cmd_ogf = -1; +static int hf_bthci_cmd_ocf = -1; +static int hf_bthci_cmd_param_length = -1; +static int hf_bthci_cmd_params = -1; +static int hf_bthci_cmd_lap = -1; +static int hf_bthci_cmd_inq_length = -1; +static int hf_bthci_cmd_num_responses = -1; +static int hf_bthci_cmd_encrypt_mode = -1; +static int hf_bthci_cmd_bd_addr = -1; +static int hf_bthci_cmd_packet_type_dm1 = -1; +static int hf_bthci_cmd_packet_type_dm3 = -1; +static int hf_bthci_cmd_packet_type_dm5 = -1; +static int hf_bthci_cmd_packet_type_dh1 = -1; +static int hf_bthci_cmd_packet_type_dh3 = -1; +static int hf_bthci_cmd_packet_type_dh5 = -1; +static int hf_bthci_cmd_clock_offset = -1; +static int hf_bthci_cmd_clock_offset_valid = -1; +static int hf_bthci_cmd_allow_role_switch = -1; +static int hf_bthci_cmd_page_scan_mode = -1; +static int hf_bthci_cmd_page_scan_repetition_mode = -1; +static int hf_bthci_cmd_page_scan_period_mode = -1; +static int hf_bthci_cmd_status = -1; +static int hf_bthci_cmd_max_period_length = -1; +static int hf_bthci_cmd_min_period_length = -1; +static int hf_bthci_cmd_connection_handle = -1; +static int hf_bthci_cmd_reason = -1; +static int hf_bthci_cmd_num_link_keys = -1; +static int hf_bthci_cmd_link_key = -1; +static int hf_bthci_cmd_packet_type_hv1 = -1; +static int hf_bthci_cmd_packet_type_hv2 = -1; +static int hf_bthci_cmd_packet_type_hv3 = -1; +static int hf_bthci_cmd_role = -1; +static int hf_bthci_cmd_pin_code_length = -1; +static int hf_bthci_cmd_pin_code = -1; +static int hf_bthci_cmd_pin_type = -1; +static int hf_bthci_cmd_encryption_enable = -1; +static int hf_bthci_cmd_key_flag = -1; +static int hf_bthci_cmd_max_interval_hold = -1; +static int hf_bthci_cmd_min_interval_hold = -1; +static int hf_bthci_cmd_max_interval_sniff = -1; +static int hf_bthci_cmd_min_interval_sniff = -1; +static int hf_bthci_cmd_sniff_attempt = -1; +static int hf_bthci_cmd_timeout = -1; +static int hf_bthci_cmd_max_interval_beacon = -1; +static int hf_bthci_cmd_min_interval_beacon = -1; +static int hf_bthci_cmd_flags = -1; +static int hf_bthci_cmd_service_type = -1; +static int hf_bthci_cmd_token_rate = -1; +static int hf_bthci_cmd_peak_bandwidth = -1; +static int hf_bthci_cmd_latency = -1; +static int hf_bthci_cmd_delay_variation = -1; +static int hf_bthci_cmd_link_policy_setting_switch = -1; +static int hf_bthci_cmd_link_policy_setting_hold = -1; +static int hf_bthci_cmd_link_policy_setting_sniff = -1; +static int hf_bthci_cmd_link_policy_setting_park = -1; +static int hf_bthci_cmd_filter_type = -1; +static int hf_bthci_cmd_inquiry_result_filter_condition_type = -1; +static int hf_bthci_cmd_connection_setup_filter_condition_type = -1; +static int hf_bthci_cmd_class_of_device = -1; +static int hf_bthci_cmd_class_of_device_mask = -1; +static int hf_bthci_cmd_auto_acc_flag = -1; +static int hf_bthci_cmd_read_all_flag = -1; +static int hf_bthci_cmd_delete_all_flag = -1; +static int hf_bthci_cmd_authentication_enable = -1; +static int hf_bthci_cmd_input_coding = -1; +static int hf_bthci_cmd_input_data_format = -1; +static int hf_bthci_cmd_input_sample_size = -1; +static int hf_bthci_cmd_linear_pcm_bit_pos = -1; +static int hf_bthci_cmd_air_coding_format = -1; +static int hf_bthci_cmd_num_broadcast_retransmissions = -1; +static int hf_bthci_cmd_hold_mode_act_page = -1; +static int hf_bthci_cmd_hold_mode_act_inquiry = -1; +static int hf_bthci_cmd_hold_mode_act_periodic = -1; +static int hf_bthci_cmd_scan_enable = -1; +static int hf_bthci_cmd_interval = -1; +static int hf_bthci_cmd_window = -1; +static int hf_bthci_cmd_local_name = -1; +static int hf_bthci_cmd_num_curr_iac = -1; +static int hf_bthci_cmd_iac_lap = -1; +static int hf_bthci_cmd_evt_mask_01 = -1; +static int hf_bthci_cmd_evt_mask_02 = -1; +static int hf_bthci_cmd_evt_mask_03 = -1; +static int hf_bthci_cmd_evt_mask_04 = -1; +static int hf_bthci_cmd_evt_mask_05 = -1; +static int hf_bthci_cmd_evt_mask_06 = -1; +static int hf_bthci_cmd_evt_mask_07 = -1; +static int hf_bthci_cmd_evt_mask_08 = -1; +static int hf_bthci_cmd_evt_mask_09 = -1; +static int hf_bthci_cmd_evt_mask_0a = -1; +static int hf_bthci_cmd_evt_mask_0b = -1; +static int hf_bthci_cmd_evt_mask_0c = -1; +static int hf_bthci_cmd_evt_mask_0d = -1; +static int hf_bthci_cmd_evt_mask_0e = -1; +static int hf_bthci_cmd_evt_mask_0f = -1; +static int hf_bthci_cmd_evt_mask_10 = -1; +static int hf_bthci_cmd_evt_mask_11 = -1; +static int hf_bthci_cmd_evt_mask_12 = -1; +static int hf_bthci_cmd_evt_mask_13 = -1; +static int hf_bthci_cmd_evt_mask_14 = -1; +static int hf_bthci_cmd_evt_mask_15 = -1; +static int hf_bthci_cmd_evt_mask_16 = -1; +static int hf_bthci_cmd_evt_mask_17 = -1; +static int hf_bthci_cmd_evt_mask_18 = -1; +static int hf_bthci_cmd_evt_mask_19 = -1; +static int hf_bthci_cmd_evt_mask_1a = -1; +static int hf_bthci_cmd_evt_mask_1b = -1; +static int hf_bthci_cmd_evt_mask_1c = -1; +static int hf_bthci_cmd_evt_mask_1d = -1; +static int hf_bthci_cmd_evt_mask_1e = -1; +static int hf_bthci_cmd_evt_mask_1f = -1; +static int hf_bthci_cmd_evt_mask_20 = -1; +static int hf_bthci_cmd_sco_flow_control = -1; +static int hf_bthci_cmd_num_handles = -1; +static int hf_bthci_cmd_num_compl_packets = -1; +static int hf_bthci_cmd_flow_contr_enable = -1; +static int hf_bthci_cmd_host_data_packet_length_acl = -1; +static int hf_bthci_cmd_host_data_packet_length_sco = -1; +static int hf_bthci_cmd_host_total_num_acl_data_packets = -1; +static int hf_bthci_cmd_host_total_num_sco_data_packets = -1; +static int hf_bthci_cmd_power_level_type = -1; + +/* Initialize the subtree pointers */ +static gint ett_bthci_cmd = -1; +static gint ett_opcode = -1; + +void +dissect_link_control_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 cmd_ocf) +{ + proto_item *item; + guint32 clock; + + switch(cmd_ocf) { + case 0x0001: /* Inquiry */ + proto_tree_add_item(tree, hf_bthci_cmd_lap, tvb, 3, 3, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_inq_length, tvb, 6, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_num_responses, tvb, 7, 1, TRUE); + break; + + case 0x0002: /* Inquiry Cancel */ + /* no parameters */ + break; + + case 0x0003: /* Periodic Inquiry Mode */ + proto_tree_add_item(tree, hf_bthci_cmd_max_period_length, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_min_period_length, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_lap, tvb, 7, 3, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_inq_length, tvb, 10, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_num_responses, tvb, 11, 1, TRUE); + break; + + case 0x0004: /* Exit Periodic Inquiry Mode */ + /* no parameters */ + break; + + case 0x0005: /* Create Connection */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dm1, tvb, 9, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dh1, tvb, 9, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dm3, tvb, 9, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dh3, tvb, 9, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dm5, tvb, 9, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dh5, tvb, 9, 2, TRUE); + + proto_tree_add_item(tree, hf_bthci_cmd_page_scan_repetition_mode, tvb, 11, 1, TRUE); + + proto_tree_add_item(tree, hf_bthci_cmd_page_scan_mode, tvb, 12, 1, TRUE); + + item = proto_tree_add_item(tree, hf_bthci_cmd_clock_offset, tvb, 13, 2, TRUE); + clock = tvb_get_letohs(tvb, 13) & 32767; /* only bit0-14 are valid */ + proto_item_append_text(item, " (%g ms)", 1.25*clock); + proto_tree_add_item(tree, hf_bthci_cmd_clock_offset_valid , tvb, 13, 2, TRUE); + + proto_tree_add_item(tree, hf_bthci_cmd_allow_role_switch, tvb, 15, 1, TRUE); + break; + + case 0x0006: /* Disconnect */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_reason, tvb, 5, 1, TRUE); + break; + + case 0x0007: /* Add SCO Connection */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_hv1, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_hv2, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_hv3, tvb, 5, 2, TRUE); + break; + + case 0x0009: /* Accept Connection Request */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_role, tvb, 9, 1, TRUE); + break; + + case 0x000a: /* Reject Connection Request */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_reason, tvb, 9, 1, TRUE); + break; + + case 0x000b: /* Link Key Request Reply */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_link_key, tvb, 9, 16, TRUE); + break; + + case 0x000c: /* Link Key Request Negative Reply */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + break; + + case 0x000d: /* PIN Code Request Reply */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_pin_code_length ,tvb, 9, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_pin_code ,tvb, 10, 16, TRUE); + break; + + case 0x000e: /* PIN Code Request Negative Reply */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + break; + + case 0x000f: /* Change Connection Packet Type */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dm1, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dh1, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dm3, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dh3, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dm5, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_dh5, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_hv1, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_hv2, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_packet_type_hv3, tvb, 5, 2, TRUE); + break; + + case 0x0011: /* Authentication Request */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + break; + + case 0x0013: /* Set Connection Encryption */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_encryption_enable, tvb, 5, 1, TRUE); + break; + + case 0x0017: /* Master Link Key */ + proto_tree_add_item(tree, hf_bthci_cmd_key_flag, tvb, 3, 1, TRUE); + break; + + case 0x0019: /* Remote Name Request */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_page_scan_repetition_mode, tvb, 9, 1, TRUE); + + proto_tree_add_item(tree, hf_bthci_cmd_page_scan_mode, tvb, 10, 1, TRUE); + + item = proto_tree_add_item(tree, hf_bthci_cmd_clock_offset, tvb, 11, 2, TRUE); + clock = tvb_get_letohs(tvb, 11) & 32767; /* only bit0-14 are valid */ + proto_item_append_text(item, " (%g ms)", 1.25*clock); + proto_tree_add_item(tree, hf_bthci_cmd_clock_offset_valid , tvb, 11, 2, TRUE); + break; + + case 0x0015: /* Change Connection Link Key */ + case 0x001b: /* Read Remote Supported Features */ + case 0x001d: /* Read Remote Version Information */ + case 0x001f: /* Read Clock Offset*/ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + break; + + default: + proto_tree_add_item(tree, hf_bthci_cmd_params, tvb, 3, -1, TRUE); + break; + } +} + +void +dissect_link_policy_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 cmd_ocf) +{ + proto_item *item; + guint16 timeout; + + switch(cmd_ocf) { + + case 0x0001: /* Hold Mode */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_max_interval_hold, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_min_interval_hold, tvb, 7, 2, TRUE); + break; + + case 0x0003: /* sniff mode */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_max_interval_sniff, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_min_interval_sniff, tvb, 7, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_sniff_attempt, tvb, 9, 2, TRUE); + item = proto_tree_add_item(tree, hf_bthci_cmd_timeout, tvb, 11, 2, TRUE); + timeout = tvb_get_letohs(tvb, 11); + if (timeout>0) + proto_item_append_text(item, " (%g msec)", (2*timeout-1)*0.625); + else + proto_item_append_text(item, " (0 msec)"); + break; + + case 0x0005: /* Park Mode */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_max_interval_beacon, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_min_interval_beacon, tvb, 7, 2, TRUE); + break; + + case 0x0007: /* QoS Setup */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_flags, tvb, 5, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_service_type, tvb, 6, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_token_rate, tvb, 7, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_peak_bandwidth, tvb, 11, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_latency, tvb, 15, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_delay_variation, tvb, 19, 4, TRUE); + break; + + case 0x000b: /* Switch Role */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_role, tvb, 9, 1, TRUE); + break; + + case 0x000d: /* Write Link Policy Settings */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_link_policy_setting_switch, tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_link_policy_setting_hold , tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_link_policy_setting_sniff , tvb, 5, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_link_policy_setting_park , tvb, 5, 2, TRUE); + break; + + case 0x0004: /* Exit Sniff Mode */ + case 0x0006: /* Exit Park Mode */ + case 0x0009: /* Role Discovery */ + case 0x000c: /* Read Link Policy Settings */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + break; + + default: + proto_tree_add_item(tree, hf_bthci_cmd_params, tvb, 3, -1, TRUE); + break; + + } +} + +void +dissect_host_controller_baseband_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 cmd_ocf) +{ + proto_item *item; + guint16 timeout; + guint8 filter_type, filter_condition_type, num8; + int i; + + switch(cmd_ocf) { + + case 0x0001: /* Set Event Mask */ + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_01, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_02, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_03, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_04, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_05, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_06, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_07, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_08, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_09, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_0a, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_0b, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_0c, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_0d, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_0e, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_0f, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_10, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_11, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_12, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_13, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_14, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_15, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_16, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_17, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_18, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_19, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_1a, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_1b, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_1c, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_1d, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_1e, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_1f, tvb, 3, 4, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_evt_mask_20, tvb, 3, 4, TRUE); + break; + + case 0x0005: /* Set Event Filter */ + proto_tree_add_item(tree, hf_bthci_cmd_filter_type, tvb, 3, 1, TRUE); + filter_type = tvb_get_guint8(tvb, 3); + switch (filter_type) { + + case 0x01: /* Inquiry Result Filter */ + proto_tree_add_item(tree, hf_bthci_cmd_inquiry_result_filter_condition_type, + tvb, 4, 1, TRUE); + filter_condition_type = tvb_get_guint8(tvb, 4); + switch (filter_condition_type) { + case 0x01: + proto_tree_add_item(tree, hf_bthci_cmd_class_of_device, tvb, 5, 3, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_class_of_device_mask, tvb, 8, 3, TRUE); + break; + + case 0x02: + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 5, 6, TRUE); + break; + + default: + break; + + } + break; + + case 0x02: /* Connection Setup Filter */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_setup_filter_condition_type, + tvb, 4, 1, TRUE); + filter_condition_type = tvb_get_guint8(tvb, 4); + switch (filter_condition_type) { + case 0x00: + proto_tree_add_item(tree, hf_bthci_cmd_auto_acc_flag, tvb, 5, 1, TRUE); + break; + + case 0x01: + proto_tree_add_item(tree, hf_bthci_cmd_class_of_device, tvb, 5, 3, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_class_of_device_mask, tvb, 8, 3, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_auto_acc_flag, tvb, 11, 1, TRUE); + break; + + case 0x02: + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 5, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_auto_acc_flag, tvb, 11, 1, TRUE); + break; + + default: + break; + + } + break; + + default: + break; + + } + + break; + + case 0x000a: /* Write PIN Type */ + proto_tree_add_item(tree, hf_bthci_cmd_pin_type, tvb, 3, 1, TRUE); + break; + + case 0x000d: /* Read Stored Link Key */ + proto_tree_add_item(tree, hf_bthci_cmd_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_read_all_flag, tvb, 9, 1, TRUE); + break; + + case 0x0011: /* Write Stored Link Key */ + proto_tree_add_item(tree, hf_bthci_cmd_num_link_keys, tvb, 3, 1, TRUE); + num8 = tvb_get_guint8(tvb, 3); + for (i=0; i 0) + proto_item_append_text(item, " slots (%g msec)", timeout*0.625); + else + proto_item_append_text(item, " Illegal Page Timeout"); + break; + + case 0x001a: /* Write Scan Anable */ + proto_tree_add_item(tree, hf_bthci_cmd_scan_enable, + tvb, 3, 1, TRUE); + break; + + case 0x0020: /* Write Authentication Enable */ + proto_tree_add_item(tree, hf_bthci_cmd_authentication_enable, + tvb, 3, 1, TRUE); + break; + + case 0x0022: /* Write Encryption Mode */ + proto_tree_add_item(tree, hf_bthci_cmd_encrypt_mode, tvb, 3, 1, TRUE); + break; + + case 0x0024: /* Write Class of Device */ + proto_tree_add_item(tree, hf_bthci_cmd_class_of_device, + tvb, 3, 3, TRUE); + break; + + case 0x0026: /* Write Voice Setting */ + proto_tree_add_item(tree, hf_bthci_cmd_input_coding, + tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_input_data_format, + tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_input_sample_size, + tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_linear_pcm_bit_pos, + tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_air_coding_format, + tvb, 3, 2, TRUE); + break; + + case 0x0028: /* Write Automatic Flush Timeout */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, 3, 2, TRUE); + item = proto_tree_add_item(tree, hf_bthci_cmd_timeout, tvb, 5, 2, TRUE); + timeout = tvb_get_letohs(tvb, 5); + if (timeout>0) + proto_item_append_text(item, " slots (%g msec)", timeout*0.625); + else + proto_item_append_text(item, " (= No Automatic Flush )"); + break; + + case 0x002a: /* Write Num of Broadcast Retransmissions */ + proto_tree_add_item(tree, hf_bthci_cmd_num_broadcast_retransmissions, + tvb, 3, 1, TRUE); + break; + + case 0x002c: /* Write Hold Mode Activity */ + proto_tree_add_item(tree, hf_bthci_cmd_hold_mode_act_page, + tvb, 3, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_hold_mode_act_inquiry, + tvb, 3, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_hold_mode_act_periodic, + tvb, 3, 1, TRUE); + break; + + case 0x002d: /* Read Transmit Power Level */ + proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, + tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_power_level_type, + tvb, 5, 1, TRUE); + break; + + case 0x002f: /* Write SCO Flow Control Enable */ + proto_tree_add_item(tree, hf_bthci_cmd_sco_flow_control, + tvb, 3, 1, TRUE); + break; + + case 0x0031: /* Set Host Controller To Host Flow Control */ + proto_tree_add_item(tree, hf_bthci_cmd_flow_contr_enable, + tvb, 3, 1, TRUE); + break; + + case 0x0033: /* Host Buffer Size */ + proto_tree_add_item(tree, hf_bthci_cmd_host_data_packet_length_acl, + tvb, 3, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_host_data_packet_length_sco, + tvb, 5, 1, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_host_total_num_acl_data_packets, + tvb, 6, 2, TRUE); + proto_tree_add_item(tree, hf_bthci_cmd_host_total_num_sco_data_packets, + tvb, 8, 2, TRUE); + break; + + case 0x0035: /* Host Number Of Completed Packets */ + proto_tree_add_item(tree, hf_bthci_cmd_num_handles, + tvb, 3, 1, TRUE); + num8 = tvb_get_guint8(tvb, 3); + for (i=0; i0) + proto_item_append_text(item, " slots (%g msec)", timeout*0.625); + else + proto_item_append_text(item, " (= No Link Supervision Timeout)"); + break; + + case 0x003a: /* Write Current IAC LAP */ + proto_tree_add_item(tree, hf_bthci_cmd_num_curr_iac, tvb, 3, 1, TRUE); + num8 = tvb_get_guint8(tvb, 3); + for (i=0; i> 2; + + ti_opcode = proto_tree_add_item(bthci_cmd_tree, hf_bthci_cmd_opcode, tvb, 0, 2, TRUE); + opcode_tree = proto_item_add_subtree(ti_opcode, ett_opcode); + + proto_tree_add_item(opcode_tree, hf_bthci_cmd_ogf, tvb, 0, 2, TRUE); + proto_tree_add_item(opcode_tree, hf_bthci_cmd_ocf, tvb, 0, 2, TRUE); + + proto_tree_add_item(bthci_cmd_tree, hf_bthci_cmd_param_length, tvb, 2, 1, TRUE); + param_length = tvb_get_guint8(tvb, 2); + + if ((check_col(pinfo->cinfo, COL_INFO))) + col_add_fstr(pinfo->cinfo, COL_INFO, "Command: %s", val_to_str(opcode, cmd_opcode_vals, NULL)); + + proto_item_append_text(ti_cmd," - %s", val_to_str(opcode, cmd_opcode_vals, NULL)); + + if (param_length > 0) { + switch (ogf) { + + case 0x01: /* Link Control Command */ + dissect_link_control_cmd(tvb, pinfo, bthci_cmd_tree, ocf); + break; + + case 0x02: /* Link Policy Command */ + dissect_link_policy_cmd(tvb, pinfo, bthci_cmd_tree, ocf); + break; + + case 0x03: /* Host Controller & Baseband Command */ + dissect_host_controller_baseband_cmd(tvb, pinfo, bthci_cmd_tree, ocf); + break; + + case 0x04: /* Informational Parameter Command */ + dissect_informational_parameters_cmd(tvb, pinfo, bthci_cmd_tree, ocf); + break; + + case 0x05: /* Status Parameter Command */ + dissect_status_parameters_cmd(tvb, pinfo, bthci_cmd_tree, ocf); + break; + + case 0x06: /* Testing Command */ + dissect_testing_cmd(tvb, pinfo, bthci_cmd_tree, ocf); + break; + +/* case 0x0c22:*/ /* Write Encryption Mode */ +/* proto_tree_add_item(bthci_cmd_tree, hf_bthci_cmd_encrypt_mode, tvb, 3, 1, TRUE); + break; +*/ + default: + proto_tree_add_item(bthci_cmd_tree, hf_bthci_cmd_params, tvb, 3, -1, TRUE); + break; + } + } + +} + + +/* Register the protocol with Ethereal */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_bthci_cmd(void) +{ + +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_bthci_cmd_opcode, + { "Command Opcode", "bthci_cmd.opcode", + FT_UINT16, BASE_HEX, VALS(cmd_opcode_vals), 0x0, + "HCI Command Opcode" } + }, + { &hf_bthci_cmd_ogf, + { "ogf", "bthci_cmd.ogf", + FT_UINT16, BASE_HEX, VALS(ogf_vals), 0xfc00, + "Opcode Group Field" } + }, + { &hf_bthci_cmd_ocf, + { "ocf", "bthci_cmd.ocf", + FT_UINT16, BASE_HEX, NULL, 0x03ff, + "Opcode Command Field" } + }, + { &hf_bthci_cmd_param_length, + { "Parameter Total Length", "bthci_cmd.param_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Parameter Total Length" } + }, + { &hf_bthci_cmd_params, + { "Command Parameter", "bthci_cmd.params", + FT_NONE, BASE_NONE, NULL, 0x0, + "Command Parameter" } + }, + { &hf_bthci_cmd_lap, + { "LAP", "bthci_cmd.lap", + FT_UINT24, BASE_HEX, NULL, 0x0, + "LAP for the inquiry access code" } + }, + { &hf_bthci_cmd_inq_length, + { "Inquiry Length", "bthci_cmd.inq_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Inquiry Length (*1.28s)" } + }, + { &hf_bthci_cmd_num_responses, + { "Num Responses", "bthci_cmd.num_responses", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Responses" } + }, + { &hf_bthci_cmd_encrypt_mode, + { "Encryption Mode", "bthci_cmd.encrypt_mode", + FT_UINT8, BASE_HEX, VALS(encrypt_mode_vals), 0x0, + "Encryption Mode" } + }, + { &hf_bthci_cmd_bd_addr, + { "BD_ADDR", "bthci_cmd.bd_addr", + FT_ETHER, BASE_HEX, NULL, 0x0, + "Bluetooth Device Address"} + }, + { &hf_bthci_cmd_packet_type_dm1, + { "Packet Type DM1", "bthci_cmd.packet_type_dm1", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0008, + "Packet Type DM1" } + }, + { &hf_bthci_cmd_packet_type_dh1, + { "Packet Type DH1", "bthci_cmd.packet_type_dh1", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0010, + "Packet Type DH1" } + }, + { &hf_bthci_cmd_packet_type_dm3, + { "Packet Type DM3", "bthci_cmd.packet_type_dm3", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0400, + "Packet Type DM3" } + }, + { &hf_bthci_cmd_packet_type_dh3, + { "Packet Type DH3", "bthci_cmd.packet_type_dh3", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0800, + "Packet Type DH3" } + }, + { &hf_bthci_cmd_packet_type_dm5, + { "Packet Type DM5", "bthci_cmd.packet_type_dm5", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x4000, + "Packet Type DM5" } + }, + { &hf_bthci_cmd_packet_type_dh5, + { "Packet Type DH5", "bthci_cmd.packet_type_dh5", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x8000, + "Packet Type DH5" } + }, + { &hf_bthci_cmd_page_scan_mode, + { "Page Scan Mode", "bthci_cmd.page_scan_mode", + FT_UINT8, BASE_HEX, VALS(cmd_page_scan_modes), 0x0, + "Page Scan Mode" } + }, + { &hf_bthci_cmd_page_scan_repetition_mode, + { "Page Scan Repetition Mode", "bthci_cmd.page_scan_repetition_mode", + FT_UINT8, BASE_HEX, VALS(cmd_page_scan_repetition_modes), 0x0, + "Page Scan Repetition Mode" } + }, + { &hf_bthci_cmd_page_scan_period_mode, + { "Page Scan Period Mode", "bthci_cmd.page_scan_period_mode", + FT_UINT8, BASE_HEX, VALS(cmd_page_scan_period_modes), 0x0, + "Page Scan Period Mode" } + }, + { &hf_bthci_cmd_clock_offset, + { "Clock Offset", "bthci_cmd.clock_offset", + FT_UINT8, BASE_HEX, NULL, 0x7FFFF, + "Bit 2-16 of the Clock Offset between CLKmaster-CLKslave" } + }, + { &hf_bthci_cmd_clock_offset_valid, + { "Clock_Offset_Valid_Flag", "bthci_cmd.clock_offset_valid", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x8000, + "Indicates if clock offset is valid" } + }, + { &hf_bthci_cmd_allow_role_switch, + { "Allow Role Switch", "bthci_cmd.allow_role_switch", + FT_UINT8, BASE_HEX, VALS(cmd_role_switch_modes), 0x0, + "Allow Role Switch" } + }, + { &hf_bthci_cmd_status, + { "Status", "bthci_cmd.status", + FT_UINT8, BASE_HEX, VALS(cmd_status_vals), 0x0, + "Status" } + }, + + { &hf_bthci_cmd_max_period_length, + { "Max Period Length", "bthci_cmd.max_period_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Maximum amount of time specified between consecutive inquiries." } + }, + { &hf_bthci_cmd_min_period_length, + { "Min Period Length", "bthci_cmd.min_period_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Minimum amount of time specified between consecutive inquiries." } + }, + { &hf_bthci_cmd_connection_handle, + { "Connection Handle", "bthci_cmd.connection_handle", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Connection Handle" } + }, + { &hf_bthci_cmd_reason, + { "Reason", "bthci_cmd.reason", + FT_UINT8, BASE_HEX, VALS(cmd_status_vals), 0x0, + "Reason" } + }, + { &hf_bthci_cmd_num_link_keys, + { "Number of Link Keys", "bthci_cmd_num_link_keys", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Link Keys" } + }, + { &hf_bthci_cmd_link_key, + { "Link Key", "bthci_cmd.link_key", + FT_BYTES, BASE_HEX, NULL, 0x0, + "Link Key for the associated BD_ADDR" } + }, + { &hf_bthci_cmd_packet_type_hv1, + { "Packet Type HV1", "bthci_cmd.packet_type_hv1", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0020, + "Packet Type HV1" } + }, + { &hf_bthci_cmd_packet_type_hv2, + { "Packet Type HV2", "bthci_cmd.packet_type_hv2", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0040, + "Packet Type HV2" } + }, + { &hf_bthci_cmd_packet_type_hv3, + { "Packet Type HV3", "bthci_cmd.packet_type_hv3", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0080, + "Packet Type HV3" } + }, + { &hf_bthci_cmd_role, + { "Role", "bthci_cmd.role", + FT_UINT8, BASE_HEX, VALS(cmd_role_vals), 0x0, + "Role" } + }, + { &hf_bthci_cmd_pin_code_length, + { "PIN Code Length", "bthci_cmd.pin_code_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "PIN Code Length" } + }, + { &hf_bthci_cmd_pin_code, + { "PIN Code Length", "bthci_cmd.pin_code_length", + FT_BYTES, BASE_HEX, NULL, 0x0, + "PIN Code Length" } + }, + { &hf_bthci_cmd_encryption_enable, + { "Encryption Enable", "bthci_cmd.encryption_enable", + FT_UINT8, BASE_HEX, VALS(cmd_encryption_enable), 0x0, + "Encryption Enable" } + }, + { &hf_bthci_cmd_key_flag, + { "Key Flag", "bthci_cmd.key_flag", + FT_UINT8, BASE_HEX, VALS(cmd_key_flag), 0x0, + "Key Flag" } + }, + { &hf_bthci_cmd_max_interval_hold, + { "Hold Mode Max Interval", "bthci_cmd.hold_mode_max_int", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Maximal acceptable number of Baseband slots to wait in Hold Mode." } + }, + { &hf_bthci_cmd_min_interval_hold, + { "Hold Mode Min Interval", "bthci_cmd.hold_mode_min_int", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Minimum acceptable number of Baseband slots to wait in Hold Mode." } + }, + { &hf_bthci_cmd_max_interval_sniff, + { "Sniff Max Interval", "bthci_cmd.sniff_max_int", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Maximal acceptable number of Baseband slots between each sniff period." } + }, + { &hf_bthci_cmd_min_interval_sniff, + { "Sniff Min Interval", "bthci_cmd.sniff_min_int", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Minimum acceptable number of Baseband slots between each sniff period." } + }, + { &hf_bthci_cmd_sniff_attempt, + { "Sniff Attempt", "bthci_cmd.sniff_attempt", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Number of Baseband receive slots for sniff attempt." } + }, + { &hf_bthci_cmd_timeout, + { "Timeout", "bthci_cmd.timeout", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Number of Baseband slots for timeout." } + }, + { &hf_bthci_cmd_max_interval_beacon, + { "Beacon Max Interval", "bthci_cmd.beacon_max_int", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Maximal acceptable number of Baseband slots between consecutive beacons." } + }, + { &hf_bthci_cmd_min_interval_beacon, + { "Beacon Min Interval", "bthci_cmd.beacon_min_int", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Minimum acceptable number of Baseband slots between consecutive beacons." } + }, + { &hf_bthci_cmd_flags, + { "Flags", "bthci_cmd.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Flags" } + }, + { &hf_bthci_cmd_service_type, + { "Service Type", "bthci_cmd.service_type", + FT_UINT8, BASE_HEX, VALS(cmd_service_types), 0x0, + "Service Type" } + }, + { &hf_bthci_cmd_token_rate, + { "Available Token Rate", "bthci_cmd.token_rate", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Token Rate, in bytes per second" } + }, + { &hf_bthci_cmd_peak_bandwidth, + { "Peak Bandwidth", "bthci_cmd.peak_bandwidth", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Peak Bandwidth, in bytes per second" } + }, + { &hf_bthci_cmd_latency, + { "Latecy", "bthci_cmd.latency", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Latency, in microseconds" } + }, + { &hf_bthci_cmd_delay_variation, + { "Delay Variation", "bthci_cmd.delay_variation", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Delay Variation, in microseconds" } + }, + { &hf_bthci_cmd_link_policy_setting_switch, + { "Enable Master Slave Switch", "bthci_cmd.link_policy_switch", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0001, + "Enable Master Slave Switch" } + }, + { &hf_bthci_cmd_link_policy_setting_hold, + { "Enable Hold Mode", "bthci_cmd.link_policy_hold", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0002, + "Enable Hold Mode" } + }, + { &hf_bthci_cmd_link_policy_setting_sniff, + { "Enable Sniff Mode", "bthci_cmd.link_policy_sniff", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0004, + "Enable Sniff Mode" } + }, + { &hf_bthci_cmd_link_policy_setting_park, + { "Enable Park Mode", "bthci_cmd.link_policy_park", + FT_UINT16, BASE_BIN, VALS(cmd_boolean), 0x0008, + "Enable Park Mode" } + }, + { &hf_bthci_cmd_filter_type, + { "Filter Type", "bthci_cmd.filter_type", + FT_UINT8, BASE_HEX, VALS(cmd_filter_types), 0x0, + "Filter Type" } + }, + { &hf_bthci_cmd_inquiry_result_filter_condition_type, + { "Filter Condition Type", "bthci_cmd.filter_condition_type", + FT_UINT8, BASE_HEX, VALS(cmd_inquiry_result_filter_condition_types), 0x0, + "Filter Condition Type" } + }, + { &hf_bthci_cmd_connection_setup_filter_condition_type, + { "Filter Condition Type", "bthci_cmd.filter_condition_type", + FT_UINT8, BASE_HEX, VALS(cmd_connection_setup_filter_condition_types), 0x0, + "Filter Condition Type" } + }, + { &hf_bthci_cmd_class_of_device, + { "Class of Device", "bthci_cmd.class_of_device", + FT_UINT24, BASE_HEX, NULL, 0x0, + "Class of Device" } + }, + { &hf_bthci_cmd_class_of_device_mask, + { "Class of Device Mask", "bthci_cmd.class_of_device_mask", + FT_UINT24, BASE_BIN, NULL, 0x0, + "Bit Mask used to determine which bits of the Class of Device parameter are of interest." } + }, + { &hf_bthci_cmd_auto_acc_flag, + { "Auto Accept Flag", "bthci_cmd.auto_accept_flag", + FT_UINT8, BASE_HEX, VALS(cmd_auto_acc_flag_values), 0x0, + "Class of Device of Interest" } + }, + { &hf_bthci_cmd_read_all_flag, + { "Read All Flag", "bthci_cmd.read_all_flag", + FT_UINT8, BASE_HEX, VALS(cmd_read_all_flag_values), 0x0, + "Read All Flag" } + }, + { &hf_bthci_cmd_delete_all_flag, + { "Delete All Flag", "bthci_cmd.delete_all_flag", + FT_UINT8, BASE_HEX, VALS(cmd_delete_all_flag_values), 0x0, + "Delete All Flag" } + }, + { &hf_bthci_cmd_authentication_enable, + { "Authentication Enable", "bthci_cmd.auth_enable", + FT_UINT8, BASE_HEX, VALS(cmd_authentication_enable_values), 0x0, + "Authentication Enable" } + }, + { &hf_bthci_cmd_input_coding, + { "Input Coding", "bthci_cmd.input_coding", + FT_UINT16, BASE_BIN, VALS(cmd_input_coding_values), 0x0300, + "Authentication Enable" } + }, + { &hf_bthci_cmd_input_data_format, + { "Input Data Format", "bthci_cmd.input_data_format", + FT_UINT16, BASE_BIN, VALS(cmd_input_data_format_values), 0x00c0, + "Input Data Format" } + }, + { &hf_bthci_cmd_input_sample_size, + { "Input Sample Size", "bthci_cmd.input_sample_size", + FT_UINT16, BASE_BIN, VALS(cmd_input_sample_size_values), 0x0020, + "Input Sample Size" } + }, + { &hf_bthci_cmd_linear_pcm_bit_pos, + { "Linear PCM Bit Pos", "bthci_cmd.lin_pcm_bit_pos", + FT_UINT16, BASE_BIN, NULL, 0x001c, + "# bit pos. that MSB of sample is away from starting at MSB" } + }, + { &hf_bthci_cmd_air_coding_format, + { "Air Coding Format", "bthci_cmd.air_coding_format", + FT_UINT16, BASE_BIN, VALS(cmd_air_coding_format_values), 0x0003, + "Air Coding Format" } + }, + { &hf_bthci_cmd_num_broadcast_retransmissions, + { "Num Broadcast Retran", "bthci_cmd.num_broad_retran", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Broadcast Retransmissions" } + }, + { &hf_bthci_cmd_hold_mode_act_page, + { "Suspend Page Scan", "bthci_cmd.hold_mode_page", + FT_UINT8, BASE_BIN, VALS(cmd_boolean), 0x1, + "Device can enter low power state" } + }, + { &hf_bthci_cmd_hold_mode_act_inquiry, + { "Suspend Inquiry Scan", "bthci_cmd.hold_mode_inquiry", + FT_UINT8, BASE_BIN, VALS(cmd_boolean), 0x2, + "Device can enter low power state" } + }, + { &hf_bthci_cmd_hold_mode_act_periodic, + { "Suspend Periodic Inquiries", "bthci_cmd.hold_mode_periodic", + FT_UINT8, BASE_BIN, VALS(cmd_boolean), 0x4, + "Device can enter low power state" } + }, + { &hf_bthci_cmd_scan_enable, + { "Scan Enable", "bthci_cmd.scan_enable", + FT_UINT8, BASE_HEX, VALS(cmd_scan_enable_values), 0x0, + "Scan Enable" } + }, + { &hf_bthci_cmd_interval, + { "Interval", "bthci_cmd.interval", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Interval" } + }, + { &hf_bthci_cmd_window, + { "Interval", "bthci_cmd.window", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Window" } + }, + { &hf_bthci_cmd_local_name, + { "Remote Name", "bthci_cmd.local_name", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Userfriendly descriptive name for the device" } + }, + { &hf_bthci_cmd_num_curr_iac, + { "Number of Current IAC", "bthci_cmd.num_curr_iac", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of IACs which are currently in use" } + }, + { &hf_bthci_cmd_iac_lap, + { "IAC LAP", "bthci_cmd.num_curr_iac", + FT_UINT24, BASE_HEX, NULL, 0x0, + "LAP(s)used to create IAC" } + }, + { &hf_bthci_cmd_evt_mask_01, + { "Inquiry Complete ", "bthci_cmd.evt_mask_01", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000001, + "Inquiry Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_02, + { "Inquiry Result ", "bthci_cmd.evt_mask_02", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000002, + "Inquiry Result Bit" } + }, + { &hf_bthci_cmd_evt_mask_03, + { "Connect Complete ", "bthci_cmd.evt_mask_03", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000004, + "Connection Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_04, + { "Connect Request ", "bthci_cmd.evt_mask_04", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000008, + "Connect Request Bit" } + }, + { &hf_bthci_cmd_evt_mask_05, + { "Disconn Complete ", "bthci_cmd.evt_mask_05", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000010, + "Disconn Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_06, + { "Auth Complete ", "bthci_cmd.evt_mask_06", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000020, + "Auth Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_07, + { "Remote Name Req Complete ", "bthci_cmd.evt_mask_07", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000040, + "Remote Name Req Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_08, + { "Encrypt Change ", "bthci_cmd.evt_mask_08", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000080, + "Encrypt Change Bit" } + }, + { &hf_bthci_cmd_evt_mask_09, + { "Change Connection Link Key Complete", "bthci_cmd.evt_mask_09", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000100, + "Change Connection Link Key Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_0a, + { "Master Link Key Complete ", "bthci_cmd.evt_mask_0a", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000200, + "Master Link Key Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_0b, + { "Read Remote Supported Features ", "bthci_cmd.evt_mask_0b", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000400, + "Read Remote Supported Features Bit" } + }, + { &hf_bthci_cmd_evt_mask_0c, + { "Read Remote Ver Info Complete ", "bthci_cmd.evt_mask_0c", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00000800, + "Read Remote Ver Info Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_0d, + { "QoS Setup Complete ", "bthci_cmd.evt_mask_0d", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00001000, + "QoS Setup Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_0e, + { "Command Complete ", "bthci_cmd.evt_mask_0e", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00002000, + "Command Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_0f, + { "Command Status ", "bthci_cmd.evt_mask_0f", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00004000, + "Command Status Bit" } + }, + { &hf_bthci_cmd_evt_mask_10, + { "Hardware Error ", "bthci_cmd.evt_mask_10", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00008000, + "Hardware Error Bit" } + }, + { &hf_bthci_cmd_evt_mask_11, + { "Flush Occurred ", "bthci_cmd.evt_mask_11", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00010000, + "Flush Occurred Bit" } + }, + { &hf_bthci_cmd_evt_mask_12, + { "Role Change ", "bthci_cmd.evt_mask_12", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00020000, + "Role Change Bit" } + }, + { &hf_bthci_cmd_evt_mask_13, + { "Number of Completed Packets ", "bthci_cmd.evt_mask_13", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00040000, + "Number of Completed Packets Bit" } + }, + { &hf_bthci_cmd_evt_mask_14, + { "Mode Change ", "bthci_cmd.evt_mask_14", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00080000, + "Mode Change Bit" } + }, + { &hf_bthci_cmd_evt_mask_15, + { "Return Link Keys ", "bthci_cmd.evt_mask_15", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00100000, + "Return Link Keys Bit" } + }, + { &hf_bthci_cmd_evt_mask_16, + { "PIN Code Request ", "bthci_cmd.evt_mask_16", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00200000, + "PIN Code Request Bit" } + }, + { &hf_bthci_cmd_evt_mask_17, + { "Link Key Request ", "bthci_cmd.evt_mask_17", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00400000, + "Link Key Request Bit" } + }, + { &hf_bthci_cmd_evt_mask_18, + { "Link Key Notification ", "bthci_cmd.evt_mask_18", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x00800000, + "Link Key Notification Bit" } + }, + { &hf_bthci_cmd_evt_mask_19, + { "Loopback Command ", "bthci_cmd.evt_mask_19", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x01000000, + "Loopback Command Bit" } + }, + { &hf_bthci_cmd_evt_mask_1a, + {"Data Buffer Overflow " , "bthci_cmd.evt_mask_1a", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x02000000, + "Data Buffer Overflow Bit" } + }, + { &hf_bthci_cmd_evt_mask_1b, + { "Max Slots Change ", "bthci_cmd.evt_mask_1b", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x04000000, + "Max Slots Change Bit" } + }, + { &hf_bthci_cmd_evt_mask_1c, + { "Read Clock Offset Complete ", "bthci_cmd.evt_mask_1c", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x08000000, + "Read Clock Offset Complete Bit" } + }, + { &hf_bthci_cmd_evt_mask_1d, + { "Connection Packet Type Changed ", "bthci_cmd.evt_mask_1d", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x10000000, + "Connection Packet Type Changed Bit" } + }, + { &hf_bthci_cmd_evt_mask_1e, + { "QoS Violation ", "bthci_cmd.evt_mask_1e", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x20000000, + "QoS Violation Bit" } + }, + { &hf_bthci_cmd_evt_mask_1f, + { "Page Scan Mode Change ", "bthci_cmd.evt_mask_1f", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x40000000, + "Page Scan Mode Change Bit" } + }, + { &hf_bthci_cmd_evt_mask_20, + { "Page Scan Repetition Mode Change ", "bthci_cmd.evt_mask_20", + FT_UINT32, BASE_HEX, VALS(cmd_boolean), 0x80000000, + "Page Scan Repetition Mode Change Bit" } + }, + { &hf_bthci_cmd_sco_flow_control, + { "SCO Flow Control","bthci_cmd.flow_control", + FT_UINT8, BASE_HEX, VALS(cmd_en_disabled), 0x0, + "SCO Flow Control" } + }, + { &hf_bthci_cmd_num_handles, + { "Number of Handles", "bthci_cmd.num_handles", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Handles" } + }, + + { &hf_bthci_cmd_num_compl_packets, + { "Number of Completed Packets", "bthci_cmd.num_compl_packets", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Number of Completed HCI Data Packets" } + }, + { &hf_bthci_cmd_flow_contr_enable, + { "Flow Control Enable", "bthci_cmd.flow_contr_enable", + FT_UINT8, BASE_HEX, VALS(cmd_flow_contr_enable), 0x0, + "Flow Control Enable" } + }, + { &hf_bthci_cmd_host_data_packet_length_acl, + {"Host ACL Data Packet Length (bytes)", "bthci_cmd.max_data_length_acl", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Max Host ACL Data Packet length of data portion host is able to accept" } + }, + { &hf_bthci_cmd_host_data_packet_length_sco, + {"Host SCO Data Packet Length (bytes)", "bthci_cmd.max_data_length_sco", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Max Host SCO Data Packet length of data portion host is able to accept" } + }, + { &hf_bthci_cmd_host_total_num_acl_data_packets, + {"Host Total Num ACL Data Packets", "bthci_cmd.max_data_num_acl", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Total Number of HCI ACL Data Packets that can be stored in the data buffers of the Host" } + }, + { &hf_bthci_cmd_host_total_num_sco_data_packets, + {"Host Total Num SCO Data Packets", "bthci_cmd.max_data_num_sco", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Total Number of HCI SCO Data Packets that can be stored in the data buffers of the Host" } + }, + { &hf_bthci_cmd_power_level_type, + {"Type", "bthci_cmd.power_level_type", + FT_UINT8, BASE_HEX, VALS(cmd_power_level_types), 0x0, + "Type"} + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_bthci_cmd, + &ett_opcode, + }; + +/* Register the protocol name and description */ + proto_bthci_cmd = proto_register_protocol("Bluetooth HCI Command", + "HCI_CMD", "bthci_cmd"); + + register_dissector("bthci_cmd", dissect_bthci_cmd, proto_bthci_cmd); + + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_bthci_cmd, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_bthci_cmd(void) +{ + dissector_handle_t bthci_cmd_handle; + + bthci_cmd_handle = find_dissector("bthci_cmd"); + +} + + diff -Nur ethereal-0.9.7/packet-bthci-cmd.h ethereal-0.9.7-patched/packet-bthci-cmd.h --- ethereal-0.9.7/packet-bthci-cmd.h 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-bthci-cmd.h 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,367 @@ +/* packet-bthci-cmd.h + * Definitionsfor the Bluetooth HCI Command dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef __PACKET_BTHCI_CMD_H__ +#define __PACKET_BTHCI_CMD_H__ + +static const value_string cmd_opcode_vals[] = { + {0x0000, "No Operation"}, + {0x0401, "Inquiry"}, + {0x0402, "Inquiry Cancel"}, + {0x0403, "Periodic Inquiry Mode"}, + {0x0404, "Exit Periodic Inquiry Mode"}, + {0x0405, "Create Connection"}, + {0x0406, "Disconnect"}, + {0x0407, "Add SCO Connection"}, + {0x0409, "Accept Connection Request"}, + {0x040a, "Reject Connection Request"}, + {0x040b, "Link Key Request Reply"}, + {0x040c, "Link Key Request Negative Reply"}, + {0x040d, "PIN Code Request Reply"}, + {0x040e, "PIN Code Request Negative Reply"}, + {0x040f, "Change Connection Packet Type"}, + {0x0411, "Authentication Requested"}, + {0x0413, "Set Connection Encryption"}, + {0x0415, "Change Connection Link Key"}, + {0x0417, "Master Link Key"}, + {0x0419, "Remote Name Request"}, + {0x041b, "Read Remote Supported Features"}, + {0x041d, "Read Remote Version Information"}, + {0x041f, "Read Clock offset"}, + {0x0801, "Hold Mode"}, + {0x0803, "Sniff Mode"}, + {0x0804, "Exit Sniff Mode"}, + {0x0805, "Park Mode"}, + {0x0806, "Exit Park Mode"}, + {0x0807, "QoS Setup"}, + {0x0809, "Role Discovery"}, + {0x080b, "Switch Role"}, + {0x080c, "Read Link Policy Settings"}, + {0x080d, "Write Link Policy Settings"}, + {0x0c01, "Set Event Mask"}, + {0x0c03, "Reset"}, + {0x0c05, "Set Event Filter"}, + {0x0c08, "Flush"}, + {0x0c09, "Read PIN Type "}, + {0x0c0a, "Write PIN Type"}, + {0x0c0b, "Create New Unit Key"}, + {0x0c0d, "Read Stored Link Key"}, + {0x0c11, "Write Stored Link Key"}, + {0x0c12, "Delete Stored Link Key"}, + {0x0c13, "Change Local Name"}, + {0x0c14, "Read Local Name"}, + {0x0c15, "Read Connection Accept Timeout"}, + {0x0c16, "Write Connection Accept Timeout"}, + {0x0c17, "Read Page Timeout"}, + {0x0c18, "Write Page Timeout"}, + {0x0c19, "Read Scan Enable"}, + {0x0c1a, "Write Scan Enable"}, + {0x0c1b, "Read Page Scan Activity"}, + {0x0c1c, "Write Page Scan Activity"}, + {0x0c1d, "Read Inquiry Scan Activity"}, + {0x0c1e, "Write Inquiry Scan Activity"}, + {0x0c1f, "Read Authentication Enable"}, + {0x0c20, "Write Authentication Enable"}, + {0x0c21, "Read Encryption Mode"}, + {0x0c22, "Write Encryption Mode"}, + {0x0c23, "Read Class of Device"}, + {0x0c24, "Write Class of Device"}, + {0x0c25, "Read Voice Setting"}, + {0x0c26, "Write Voice Setting"}, + {0x0c27, "Read Automatic Flush Timeout"}, + {0x0c28, "Write Automatic Flush Timeout"}, + {0x0c29, "Read Num Broadcast Retransmissions"}, + {0x0c2a, "Write Num Broadcast Retransmissions"}, + {0x0c2b, "Read Hold Mode Activity "}, + {0x0c2c, "Write Hold Mode Activity"}, + {0x0c2d, "Read Transmit Power Level"}, + {0x0c2e, "Read SCO Flow Control Enable"}, + {0x0c2f, "Write SCO Flow Control Enable"}, + {0x0c31, "Set Host Controller To Host Flow Control"}, + {0x0c33, "Host Buffer Size"}, + {0x0c35, "Host Number of Completed Packets"}, + {0x0c36, "Read Link Supervision Timeout"}, + {0x0c37, "Write Link Supervision Timeout"}, + {0x0c38, "Read Number of Supported IAC"}, + {0x0c39, "Read Current IAC LAP"}, + {0x0c3a, "Write Current IAC LAP"}, + {0x0c3b, "Read Page Scan Period Mode"}, + {0x0c3c, "Write Page Scan Period Mode"}, + {0x0c3d, "Read Page Scan Mode"}, + {0x0c3e, "Write Page Scan Mode"}, + {0x1001, "Read Local Version Information"}, + {0x1003, "Read Local Supported Features"}, + {0x1005, "Read Buffer Size"}, + {0x1007, "Read Country Code"}, + {0x1009, "Read BD ADDR"}, + {0x1401, "Read Failed Contact Counter"}, + {0x1402, "Reset Failed Contact Counter"}, + {0x1403, "Get Link Quality"}, + {0x1405, "Read RSSI"}, + {0x1801, "Read Loopback Mode"}, + {0x1802, "Write Loopback Mode"}, + {0x1803, "Enable Device Under Test Mode"}, +}; + +/* + * The HCI_OGF_ values for "ogf". + */ +#define HCI_OGF_LINK_CONTROL 0x01 +#define HCI_OGF_LINK_POLICY 0x02 +#define HCI_OGF_HOST_CONTROLLER 0x03 +#define HCI_OGF_INFORMATIONAL 0x04 +#define HCI_OGF_STATUS 0x05 +#define HCI_OGF_TESTING 0x06 + +static const value_string ogf_vals[] = { + { HCI_OGF_LINK_CONTROL, "Link Control Commands" }, + { HCI_OGF_LINK_POLICY, "Link Policy Commands" }, + { HCI_OGF_HOST_CONTROLLER,"Host Controller & Baseband Commands" }, + { HCI_OGF_INFORMATIONAL, "Informational Parameters" }, + { HCI_OGF_STATUS, "Status Parameters" }, + { HCI_OGF_TESTING, "Testing Commands" }, + { 0, NULL } +}; + +static const value_string cmd_status_vals[] = { + {0x00, "Command Succeeded"}, + {0x01, "Unknown HCI Command"}, + {0x02, "No Connection"}, + {0x03, "Hardware Failure"}, + {0x04, "Page Timeout"}, + {0x05, "Authentication Failure"}, + {0x06, "Key Missing"}, + {0x07, "Memory Full"}, + {0x08, "Connection Timeout"}, + {0x09, "Max Number Of Connections"}, + {0x0A, "Max Number Of SCO Connections To A Device"}, + {0x0B, "ACL connection already exists"}, + {0x0C, "Command Disallowed"}, + {0x0D, "Host Rejected due to limited resources"}, + {0x0E, "Host Rejected due to security reasons"}, + {0x0F, "Host Rejected due to remote device is only a personal device"}, + {0x10, "Host Timeout"}, + {0x11, "Unsupported Feature or Parameter Value"}, + {0x12, "Invalid HCI Command Parameters"}, + {0x13, "Other End Terminated Connection: User Ended Connection"}, + {0x14, "Other End Terminated Connection: Low Resources"}, + {0x15, "Other End Terminated Connection: About to Power Off"}, + {0x16, "Connection Terminated by Local Host"}, + {0x17, "Repeated Attempts"}, + {0x18, "Pairing Not Allowed"}, + {0x19, "Unknown LMP PDU"}, + {0x1A, "Unsupported Remote Feature"}, + {0x1B, "SCO Offset Rejected"}, + {0x1C, "SCO Interval Rejected"}, + {0x1D, "SCO Air Mode Rejected"}, + {0x1E, "Invalid LMP Parameters"}, + {0x1F, "Unspecified Error"}, + {0x20, "Unsupported LMP Parameter Value"}, + {0x21, "Role Change Not Allowed"}, + {0x22, "LMP Response Timeout"}, + {0x23, "LMP Error Transaction Collision"}, + {0x24, "LMP PDU Not Allowed"}, + {0x25, "Encryption Mode Not Acceptable"}, + {0x26, "Unit Key Used"}, + {0x27, "QoS is Not Supported"}, + {0x28, "Instant Passed"}, + {0x29, "Pairing with Unit Key Not Supported"}, +}; + +static const value_string encrypt_mode_vals[] = { + { 0x00, "Encryption Disabled" }, + { 0x01, "Encryption only for Point-To-Point Packets" }, + { 0x02, "Encryption for Point-To-Point and Broadcast Packets" }, + { 0, NULL } +}; + +static const value_string cmd_page_scan_repetition_modes[] = { + {0x00, "R0"}, + {0x01, "R1"}, + {0x02, "R2"}, + { 0, NULL}, +}; + +static const value_string cmd_page_scan_period_modes[] = { + {0x00, "P0"}, + {0x01, "P1"}, + {0x02, "P2"}, + { 0, NULL}, +}; + +static const value_string cmd_page_scan_modes[] = { + {0x00, "Mandatory Page Scan Mode"}, + {0x01, "Optional Page Scan Mode I"}, + {0x02, "Optional Page Scan Mode II"}, + {0x03, "Optional Page Scan Mode III"}, + { 0, NULL}, +}; + +static const value_string cmd_role_switch_modes[] = { + {0x00, "Local device will be master, and will not accept a master-slave switch request." }, + {0x01, "Local device may be master, or may become slave after accepting a master slave switch." }, + { 0, NULL}, +}; + +static const value_string cmd_boolean[] = { + {0x0 , "false" }, + {0x1 , "true" }, + { 0 , NULL }, +}; + +static const value_string cmd_en_disabled[] = { + {0x00, "disabled" }, + {0x01, "enabled" }, + { 0, NULL }, +}; + +static const value_string cmd_role_vals[] = { + {0x00, "Become Master"}, + {0x01, "Remain Slave"}, + { 0, NULL}, +}; + +static const value_string cmd_encryption_enable[] = { + {0x00, "Link Level Encryption is OFF"}, + {0x01, "Link Level Encryption is ON"}, + { 0, NULL}, +}; + +static const value_string cmd_key_flag[] = { + {0x00, "Using Semi-permanent Link Key"}, + {0x01, "Using Temporary Link Key"}, + { 0, NULL}, +}; + +static const value_string cmd_service_types[] = { + {0x00, "No Traffic"}, + {0x01, "Best Effort"}, + {0x02, "Guaranteed"}, + { 0, NULL}, +}; + +static const value_string cmd_filter_types[] = { + {0x00, "Clear all Filters" }, + {0x01, "Inquiry Result" }, + {0x02, "Connection Setup" }, + { 0, NULL }, +}; + +static const value_string cmd_inquiry_result_filter_condition_types[] = { + {0x00, "A new device responded" }, + {0x01, "A device with the specified Class of Device responded" }, + {0x01, "A device with the specified BD_ADDR responded" }, + { 0, NULL}, +}; + +static const value_string cmd_connection_setup_filter_condition_types[] = { + {0x00, "Allow Connections from all devices" }, + {0x01, "Allow Connections from a device with a specific Class of Device" }, + {0x02, "Allow Connections from a device with a specific BD_ADDR" }, + { 0, NULL}, +}; + +static const value_string cmd_auto_acc_flag_values[] = { + {0x01, "Do NOT Auto accept" }, + {0x02, "Do Auto accept, role switch disabled" }, + {0x03, "Do Auto accept, role switch enabled" }, + { 0, NULL}, +}; + +static const value_string cmd_pin_types[] = { + {0x00, "Variable PIN" }, + {0x01, "Fixed PIN" }, + { 0, NULL }, +}; + +static const value_string cmd_read_all_flag_values[] = { + {0x00, "Return Link Key for speified BD_ADDR" }, + {0x01, "Return all stored Link Keys" }, + { 0, NULL }, +}; + +static const value_string cmd_delete_all_flag_values[] = { + {0x00, "Delete only Link Key for speified BD_ADDR" }, + {0x01, "Delete all stored Link Keys" }, + { 0, NULL }, +}; + +static const value_string cmd_scan_enable_values[] = { + {0x00, "No Scans enabled" }, + {0x01, "Inquiry Scan enabled/Page Scan disable" }, + {0x02, "Inquiry Scan disabled/Page Scan enabled" }, + {0x03, "Inquiry Scan enabled/Page Scan enabled" }, + { 0, NULL }, +}; + +static const value_string cmd_authentication_enable_values[] = { + {0x00, "Authentication disabled" }, + {0x01, "Authentication enabled for all connection" }, + { 0, NULL }, +}; + +static const value_string cmd_input_coding_values[] = { + {0x0, "Linear" }, + {0x1, "\xb5-law" }, + {0x2, "A-law" }, + { 0, NULL }, +}; + +static const value_string cmd_input_data_format_values[] = { + {0x0, "1's complement" }, + {0x1, "2's complement" }, + {0x2, "Sign-Magnitude" }, + { 0, NULL }, +}; + +static const value_string cmd_input_sample_size_values[] = { + {0x0, "8 bit (only for Linear PCM)" }, + {0x1, "16 bit (only for Linear PCM)" }, + { 0, NULL }, +}; + +static const value_string cmd_air_coding_format_values[] = { + {0x0, "CVSD" }, + {0x1, "\xb5-law" }, + {0x2, "A-law" }, + { 0, NULL }, +}; + +static const value_string cmd_flow_contr_enable[] = { + {0x00, "Flow control off in direction from Host Controller to Host." }, + {0x01, "ON - HCI ACL Data Packets / OFF - HCI SCO Data Packets" }, + {0x02, "OFF - HCI ACL Data Packets / ON - HCI SCO Data Packets" }, + {0x03, "ON - HCI ACL Data Packets / ON - HCI SCO Data Packets" }, + { 0, NULL }, +}; + +static const value_string cmd_power_level_types[] = { + {0x00, "Read Current Transmission Power Level" }, + {0x01, "Read Maximum Transmission Power Level" }, + { 0, NULL }, +}; + +#endif diff -Nur ethereal-0.9.7/packet-bthci-evt.c ethereal-0.9.7-patched/packet-bthci-evt.c --- ethereal-0.9.7/packet-bthci-evt.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-bthci-evt.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,1169 @@ +/* packet-bthci-evt.c + * Routines for the Bluetooth HCI Event dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include + +#include + +static dissector_handle_t hci_com_handle; + +/* Initialize the protocol and registered fields */ +static int proto_bthci_evt = -1; +static int hf_bthci_evt_code = -1; +static int hf_bthci_evt_param_length = -1; +static int hf_bthci_evt_params = -1; +static int hf_bthci_evt_num_command_packets = -1; +static int hf_bthci_evt_num_handles = -1; +static int hf_bthci_evt_connection_handle = -1; +static int hf_bthci_evt_num_compl_packets = -1; +static int hf_bthci_evt_com_opcode = -1; +static int hf_bthci_evt_ret_params = -1; +static int hf_bthci_evt_status = -1; +static int hf_bthci_evt_ocf = -1; +static int hf_bthci_evt_ogf = -1; +static int hf_bthci_evt_bd_addr = -1; +static int hf_bthci_evt_link_type = -1; +static int hf_bthci_evt_encryption_mode = -1; +static int hf_bthci_evt_class_of_device = -1; +static int hf_bthci_evt_reason = -1; +static int hf_bthci_evt_remote_name = -1; +static int hf_bthci_evt_encryption_enable = -1; +static int hf_bthci_evt_key_flag = -1; +static int hf_bthci_evt_vers_nr = -1; +static int hf_bthci_evt_comp_id = -1; +static int hf_bthci_evt_sub_vers_nr = -1; +static int hf_bthci_evt_flags = -1; +static int hf_bthci_evt_service_type = -1; +static int hf_bthci_evt_token_rate = -1; +static int hf_bthci_evt_peak_bandwidth = -1; +static int hf_bthci_evt_latency = -1; +static int hf_bthci_evt_delay_variation = -1; +static int hf_bthci_evt_hardware_code = -1; +static int hf_bthci_evt_role = -1; +static int hf_bthci_evt_curr_role = -1; +static int hf_bthci_evt_curr_mode = -1; +static int hf_bthci_evt_interval = -1; +static int hf_bthci_evt_link_key = -1; +static int hf_bthci_evt_key_type = -1; +static int hf_bthci_evt_max_slots = -1; +static int hf_bthci_evt_clock_offset = -1; +static int hf_bthci_evt_link_type_dm1 = -1; +static int hf_bthci_evt_link_type_dh1 = -1; +static int hf_bthci_evt_link_type_dm3 = -1; +static int hf_bthci_evt_link_type_dh3 = -1; +static int hf_bthci_evt_link_type_dm5 = -1; +static int hf_bthci_evt_link_type_dh5 = -1; +static int hf_bthci_evt_link_type_hv1 = -1; +static int hf_bthci_evt_link_type_hv2 = -1; +static int hf_bthci_evt_link_type_hv3 = -1; +static int hf_bthci_evt_page_scan_mode = -1; +static int hf_bthci_evt_page_scan_repetition_mode = -1; +static int hf_bthci_evt_page_scan_period_mode = -1; +static int hf_bthci_evt_lmp_feature_00 = -1; +static int hf_bthci_evt_lmp_feature_01 = -1; +static int hf_bthci_evt_lmp_feature_02 = -1; +static int hf_bthci_evt_lmp_feature_03 = -1; +static int hf_bthci_evt_lmp_feature_04 = -1; +static int hf_bthci_evt_lmp_feature_05 = -1; +static int hf_bthci_evt_lmp_feature_06 = -1; +static int hf_bthci_evt_lmp_feature_07 = -1; +static int hf_bthci_evt_lmp_feature_10 = -1; +static int hf_bthci_evt_lmp_feature_11 = -1; +static int hf_bthci_evt_lmp_feature_12 = -1; +static int hf_bthci_evt_lmp_feature_13 = -1; +static int hf_bthci_evt_lmp_feature_14 = -1; +static int hf_bthci_evt_lmp_feature_15 = -1; +static int hf_bthci_evt_lmp_feature_16 = -1; +static int hf_bthci_evt_lmp_feature_17 = -1; +static int hf_bthci_evt_lmp_feature_20 = -1; +static int hf_bthci_evt_lmp_feature_21 = -1; +static int hf_bthci_evt_lmp_feature_22 = -1; +static int hf_bthci_evt_lmp_feature_23 = -1; +static int hf_bthci_evt_lmp_feature_24 = -1; +static int hf_bthci_evt_num_keys = -1; +static int hf_bthci_evt_num_responses = -1; +static int hf_bthci_evt_link_policy_setting_switch = -1; +static int hf_bthci_evt_link_policy_setting_hold = -1; +static int hf_bthci_evt_link_policy_setting_sniff = -1; +static int hf_bthci_evt_link_policy_setting_park = -1; + +/* Initialize the subtree pointers */ +static gint ett_bthci_evt = -1; +static gint ett_opcode = -1; +static gint ett_lmp_subtree = -1; +static gint ett_ptype_subtree = -1; + + +static const value_string evt_code_vals[] = { + {0x01, "Inquiry Complete"}, + {0x02, "Inquiry Result"}, + {0x03, "Connect Complete"}, + {0x04, "Connect Request"}, + {0x05, "Disconn Complete"}, + {0x06, "Auth Complete"}, + {0x07, "Remote Name Req Complete"}, + {0x08, "Encrypt Change"}, + {0x09, "Change Connection Link Key Complete"}, + {0x0a, "Master Link Key Complete"}, + {0x0b, "Read Remote Supported Features"}, + {0x0c, "Read Remote Ver Info Complete"}, + {0x0d, "QoS Setup Complete"}, + {0x0e, "Command Complete"}, + {0x0f, "Command Status"}, + {0x10, "Hardware Error"}, + {0x11, "Flush Occurred"}, + {0x12, "Role Change"}, + {0x13, "Number of Completed Packets"}, + {0x14, "Mode Change"}, + {0x15, "Return Link Keys"}, + {0x16, "PIN Code Request"}, + {0x17, "Link Key Request"}, + {0x18, "Link Key Notification"}, + {0x19, "Loopback Command"}, + {0x1a, "Data Buffer Overflow"}, + {0x1b, "Max Slots Change"}, + {0x1c, "Read Clock Offset Complete"}, + {0x1d, "Connection Packet Type Changed"}, + {0x1e, "QoS Violation"}, + {0x1f, "Page Scan Mode Change"}, + {0x20, "Page Scan Repetition Mode Change"}, +}; + +static const value_string evt_status_vals[] = { + {0x00, "Command Succeeded"}, + {0x01, "Unknown HCI Command"}, + {0x02, "No Connection"}, + {0x03, "Hardware Failure"}, + {0x04, "Page Timeout"}, + {0x05, "Authentication Failure"}, + {0x06, "Key Missing"}, + {0x07, "Memory Full"}, + {0x08, "Connection Timeout"}, + {0x09, "Max Number Of Connections"}, + {0x0A, "Max Number Of SCO Connections To A Device"}, + {0x0B, "ACL connection already exists"}, + {0x0C, "Command Disallowed"}, + {0x0D, "Host Rejected due to limited resources"}, + {0x0E, "Host Rejected due to security reasons"}, + {0x0F, "Host Rejected due to remote device is only a personal device"}, + {0x10, "Host Timeout"}, + {0x11, "Unsupported Feature or Parameter Value"}, + {0x12, "Invalid HCI Command Parameters"}, + {0x13, "Other End Terminated Connection: User Ended Connection"}, + {0x14, "Other End Terminated Connection: Low Resources"}, + {0x15, "Other End Terminated Connection: About to Power Off"}, + {0x16, "Connection Terminated by Local Host"}, + {0x17, "Repeated Attempts"}, + {0x18, "Pairing Not Allowed"}, + {0x19, "Unknown LMP PDU"}, + {0x1A, "Unsupported Remote Feature"}, + {0x1B, "SCO Offset Rejected"}, + {0x1C, "SCO Interval Rejected"}, + {0x1D, "SCO Air Mode Rejected"}, + {0x1E, "Invalid LMP Parameters"}, + {0x1F, "Unspecified Error"}, + {0x20, "Unsupported LMP Parameter Value"}, + {0x21, "Role Change Not Allowed"}, + {0x22, "LMP Response Timeout"}, + {0x23, "LMP Error Transaction Collision"}, + {0x24, "LMP PDU Not Allowed"}, + {0x25, "Encryption Mode Not Acceptable"}, + {0x26, "Unit Key Used"}, + {0x27, "QoS is Not Supported"}, + {0x28, "Instant Passed"}, + {0x29, "Pairing with Unit Key Not Supported"}, +}; + +static const value_string evt_link_types[] = { + {0x00, "SCO connection (Voice Channels)"}, + {0x01, "ACL connection (Data Channels)"}, + { 0, NULL}, +}; + +static const value_string evt_encryption_modes[] = { + {0x00, "Encryption Disabled"}, + {0x01, "Encryption only for point-to-point packets"}, + {0x02, "Encryption for both point-to-point and broadcast packets"}, + { 0, NULL}, +}; + +static const value_string evt_encryption_enable[] = { + {0x00, "Link Level Encryption is OFF"}, + {0x01, "Link Level Encryption is ON"}, + { 0, NULL}, +}; + +static const value_string evt_key_flag[] = { + {0x00, "Using Semi-permanent Link Key"}, + {0x01, "Using Temporary Link Key"}, + { 0, NULL}, +}; + +static const value_string evt_vers_nr[] = { + {0x00, "Bluetooth LMP 1.0"}, + {0x01, "Bluetooth LMP 1.1"}, + { 0, NULL}, +}; + +static const value_string evt_comp_id[] = { + {0x0000, "Ericsson Mobile Communications"}, + {0x0001, "Nokia Mobile Phones"}, + {0x0002, "Intel Corp."}, + {0x0003, "IBM Corp."}, + {0x0004, "Toshiba Corp."}, + {0x0005, "3Com"}, + {0x0006, "Microsoft"}, + {0x0007, "Lucent"}, + {0x0008, "Motorola"}, + {0x0009, "Infineon Technologies AG"}, + {0x000a, "Cambridge Silicon Radio"}, + {0x000b, "Silicon Wave"}, + {0x000c, "Digianswer"}, + {0xFFFF, "For use in internal and interoperability tests."}, + { 0, NULL}, +}; + +static const value_string evt_service_types[] = { + {0x00, "No Traffic Available"}, + {0x01, "Best Effort Available"}, + {0x02, "Guaranteed Available"}, + { 0, NULL}, +}; + +static const value_string evt_role_vals[] = { + {0x00, "Currently the Master for specified BD_ADDR"}, + {0x01, "Currently the Slave for specified BD_ADDR"}, + { 0, NULL}, +}; + +static const value_string evt_role_vals_handle[] = { + {0x00, "Currently the Master for this connection handle"}, + {0x01, "Currently the Slave for this connection handle"}, + { 0, NULL}, +}; + +static const value_string evt_modes[] = { + {0x00, "Active Mode"}, + {0x01, "Hold Mode"}, + {0x02, "Sniff Mode"}, + {0x03, "Park Mode"}, + { 0, NULL}, +}; + +static const value_string evt_key_types[] = { + {0x00, "Combination Key"}, + {0x01, "Local Unit Key"}, + {0x02, "Remote Unit Key"}, + { 0, NULL}, +}; + +static const value_string evt_page_scan_modes[] = { + {0x00, "Mandatory Page Scan Mode"}, + {0x01, "Optional Page Scan Mode I"}, + {0x02, "Optional Page Scan Mode II"}, + {0x03, "Optional Page Scan Mode III"}, + { 0, NULL}, +}; + +static const value_string evt_page_scan_repetition_modes[] = { + {0x00, "R0"}, + {0x01, "R1"}, + {0x02, "R2"}, + { 0, NULL}, +}; + +static const value_string evt_page_scan_period_modes[] = { + {0x00, "P0"}, + {0x01, "P1"}, + {0x02, "P2"}, + { 0, NULL}, +}; + +static const value_string evt_boolean[] = { + {0x0 , "false" }, + {0x1 , "true" }, + { 0 , NULL }, +}; + +/* Code to actually dissect the packets */ +static void +dissect_bthci_evt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_item *ti_opcode; + proto_item *ti_lmp_features; + proto_item *ti_lmp_subtree; + proto_item *handle_tree; + proto_item *ti_ptype_subtree; + proto_tree *handle_tree_sub; + proto_tree *bthci_evt_tree; + proto_tree *opcode_tree; + guint8 param_length, evt_code, evt_num_handles, evt_num_keys, evt_num_responses, num; + guint16 com_opcode; + guint32 clock; + int flag_DM1, flag_DM3, flag_DM5, flag_DH1, flag_DH3, flag_DH5, flag_HV1, flag_HV2, flag_HV3; + tvbuff_t *next_tvb; + + ti = proto_tree_add_item(tree, proto_bthci_evt, tvb, 0, -1, FALSE); + + bthci_evt_tree = proto_item_add_subtree(ti, ett_bthci_evt); + + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_code, tvb, 0, 1, TRUE); + evt_code = tvb_get_guint8(tvb, 0); + + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_param_length, tvb, 1, 1, TRUE); + param_length = tvb_get_guint8(tvb, 1); + + if ((check_col(pinfo->cinfo, COL_INFO))) + col_add_fstr(pinfo->cinfo, COL_INFO, "Event: %s", val_to_str(evt_code, evt_code_vals, NULL)); + + proto_item_append_text(ti," - %s", val_to_str(evt_code, evt_code_vals, NULL)); + + if (param_length > 0) { + switch(evt_code) { + + case 0x01: /* Inquiry Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + break; + + case 0x02: /* Inquiry result event */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_num_responses, tvb, 2, 1, TRUE); + evt_num_responses = tvb_get_guint8(tvb, 2); + + for (num = 0; num < evt_num_responses; num++) { + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 3+(num*15), 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_page_scan_repetition_mode, tvb, 9+(num*15), 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_page_scan_period_mode, tvb, 10+(num*15), 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_page_scan_mode, tvb, 11+(num*15), 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_class_of_device, tvb, 12+(num*15), 3, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_clock_offset, tvb, 15+(num*15), 2, TRUE); + } + + break; + + case 0x03: /* Connection Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 5, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_type, tvb, 11, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_encryption_mode, tvb, 12, 1, TRUE); + break; + + case 0x04: /* Connection Request */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 2, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_class_of_device, tvb,8,3, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_type, tvb, 11, 1, TRUE); + break; + + case 0x05: /* Disconnection Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_reason, tvb, 5, 1, TRUE); + break; + + case 0x06: /* Authentication Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + break; + + case 0x07: /* Remote Name Request Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_remote_name, tvb, 9, 248, FALSE); + break; + + case 0x08: /* Encryption Change */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_encryption_enable, tvb, 5, 1, TRUE); + break; + + case 0x09: /* Change Connection Link Key Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + break; + + case 0x0a: /* Master Link Key Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_key_flag, tvb, 5, 1, TRUE); + break; + + case 0x0b: /* Read Remote Support Features Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + ti_lmp_features = proto_tree_add_text(bthci_evt_tree, tvb, 5, 8, "LMP_Features: "); + ti_lmp_subtree = proto_item_add_subtree(ti_lmp_features, ett_lmp_subtree); + + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_00, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_01, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_02, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_03, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_04, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_05, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_06, tvb, 5, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_07, tvb, 5, 1, TRUE); + + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_10, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_11, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_12, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_13, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_14, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_15, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_16, tvb, 6, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_17, tvb, 6, 1, TRUE); + + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_20, tvb, 7, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_21, tvb, 7, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_22, tvb, 7, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_23, tvb, 7, 1, TRUE); + proto_tree_add_item(ti_lmp_subtree,hf_bthci_evt_lmp_feature_24, tvb, 7, 1, TRUE); + break; + + case 0x0c: /* Read Remote Version Information Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_vers_nr, tvb, 5, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_comp_id, tvb, 6, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_sub_vers_nr, tvb, 8, 2, TRUE); + break; + + case 0x0d: /* QoS Setup Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_flags, tvb, 5, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_service_type, tvb, 6, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_token_rate, tvb, 7, 4, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_peak_bandwidth, tvb, 11, 4, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_latency, tvb, 15, 4, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_delay_variation, tvb, 19, 4, TRUE); + break; + + case 0x0e: /* Command Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_num_command_packets, tvb, 2, 1, TRUE); + ti_opcode = proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_com_opcode, tvb, 3, 2, TRUE); + com_opcode = tvb_get_letohs(tvb, 3); + + opcode_tree = proto_item_add_subtree(ti_opcode, ett_opcode); + proto_tree_add_item(opcode_tree, hf_bthci_evt_ogf, tvb, 3, 2, TRUE); + proto_tree_add_item(opcode_tree, hf_bthci_evt_ocf, tvb, 3, 2, TRUE); + + if (param_length > 3) { + + switch(com_opcode) { + + /* This is a list of Commands that all return just the status */ + case 0x0402: /* Inquiry Cancel */ + case 0x0403: /* Periodic Inquiry Mode */ + case 0x0404: /* Exit Periodic Enquiry Mode */ + case 0x0c01: /* Set Event Mask */ + case 0x0c03: /* Reset */ + case 0x0c05: /* Set Event Filter */ + case 0x0c0a: /* Write PIN Type */ + case 0x0c0b: /* Create Unit Key */ + case 0x0c13: /* Change Local Name */ + case 0x0c16: /* Write Connection Accept Timeout */ + case 0x0c18: /* Write Page Timeout */ + case 0x0c1a: /* Write Scan Enable */ + case 0x0c1c: /* Write Page Scan Activity */ + case 0x0c1e: /* Write Inquiry Scan Activity */ + case 0x0c20: /* Write Authentication Enable */ + case 0x0c22: /* Write Encryption Mode */ + case 0x0c24: /* Write Class of Device */ + case 0x0c26: /* Write Voice Setting */ + case 0x0c2a: /* Write Num Broadcast Retransmissions */ + case 0x0c2c: /* Write Hold Mode Activity */ + case 0x0c2f: /* Write SCO Flow Control Enable */ + case 0x0c31: /* Set Host Controller To Host Flow Control */ + case 0x0c33: /* Host Buffer Size */ + case 0x0c39: /* Write Current IAC LAP */ + case 0x0c3c: /* Write Page Scan Period Mode */ + case 0x0c3e: /* Write Page Scan Mode */ + case 0x1802: /* Write Loopback Mode */ + case 0x1803: /* Enable Device Under Test Mode */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 5, 1, TRUE); + break; + + case 0x040b: /* Link Key Request Reply */ + case 0x040c: /* Link Key Request Negative Reply */ + case 0x040d: /* PIN Code Request Reply */ + case 0x040e: /* PIN Code Request Negative Reply */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 5, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 6, 6, TRUE); + break; + + case 0x0809: /* Role Discovery */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 5, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 6, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_curr_role, tvb, 8, 1, TRUE); + break; + + case 0x080c: /* Read Link Policy Settings */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 5, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 6, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_policy_setting_switch, tvb, 8, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_policy_setting_hold , tvb, 8, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_policy_setting_sniff , tvb, 8, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_policy_setting_park , tvb, 8, 2, TRUE); + break; + + case 0x080d: /* Write Link Policy Settings */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 5, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 6, 2, TRUE); + break; + + default: + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_ret_params, tvb, 5, -1, TRUE); + break; + + } + + } + break; + + case 0x0f: /* Command Status */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_num_command_packets, tvb, 3, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_com_opcode, tvb, 4, 2, TRUE); + break; + + case 0x10: /* Hardware Error */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_hardware_code, tvb, 2, 1, TRUE); + break; + + case 0x11: /* Flush Occurred */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 2, 2, TRUE); + break; + + case 0x12: /* Role Change */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 3, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_role, tvb, 9, 1, TRUE); + break; + + case 0x13: /* Number Of Completed Packets */ + + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_num_handles, tvb, 2, 1, TRUE); + evt_num_handles = tvb_get_guint8(tvb, 2); + + num = 0; + while (num < evt_num_handles) { + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3+(num*4), 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_num_compl_packets, tvb, 5+(num*4), 2, TRUE); + + num++; + } + break; + + case 0x14: /* Mode Change */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_curr_mode, tvb, 5, 1, TRUE); + handle_tree = proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_interval, tvb, 6, 2, TRUE); + proto_item_append_text(handle_tree, " Baseband slots (%f msec)", tvb_get_letohs(tvb, 6)*0.625); + break; + + case 0x15: /* Return Link Keys */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_num_keys, tvb, 2, 1, TRUE); + evt_num_keys = tvb_get_guint8(tvb, 2); + + num = 0; + while (num < evt_num_keys) { + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 3+(num*22), 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_key, tvb, 9+(num*22), 16, TRUE); + + num++; + } + break; + + case 0x16: /* PIN Code Request */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 2, 6, TRUE); + break; + + case 0x17: /* Link Key Request */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 2, 6, TRUE); + break; + + case 0x18: /* Link Key Notification */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 2, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_key, tvb, 8, 16, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_key_type, tvb, 24, 1, TRUE); + break; + + case 0x19: /* Loopback Command */ + next_tvb = tvb_new_subset(tvb, 2, tvb_length(tvb) - 2, -1); + call_dissector(hci_com_handle, next_tvb, pinfo, ti); + break; + + case 0x1a: /* Data Buffer Overflow */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_link_type, tvb, 2, 1, TRUE); + break; + + case 0x1b: /* Max Slots Change */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 2, 2, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_max_slots, tvb, 4, 1, TRUE); + break; + + case 0x1c: /* Read Clock Offset Complete */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + handle_tree = proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_clock_offset, tvb, 5,2,TRUE); + clock = tvb_get_letohs(tvb, 5) & 32767; /* only bit0-14 are valid */ + proto_item_append_text(handle_tree, " (%g ms)", 1.25*clock); + break; + + case 0x1d: /* Connection Packet Type Changed */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_status, tvb, 2, 1, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 3, 2, TRUE); + + flag_DM1 = (tvb_get_letohs(tvb, 3) & 0x0008) ? 1 : 0; + flag_DH1 = (tvb_get_letohs(tvb, 3) & 0x0010) ? 1 : 0; + flag_DM3 = (tvb_get_letohs(tvb, 3) & 0x0400) ? 1 : 0; + flag_DH3 = (tvb_get_letohs(tvb, 3) & 0x0800) ? 1 : 0; + flag_DM5 = (tvb_get_letohs(tvb, 3) & 0x4000) ? 1 : 0; + flag_DH5 = (tvb_get_letohs(tvb, 3) & 0x8000) ? 1 : 0; + flag_HV1 = (tvb_get_letohs(tvb, 3) & 0x0020) ? 1 : 0; + flag_HV2 = (tvb_get_letohs(tvb, 3) & 0x0040) ? 1 : 0; + flag_HV3 = (tvb_get_letohs(tvb, 3) & 0x0080) ? 1 : 0; + handle_tree = proto_tree_add_text(bthci_evt_tree, tvb, 5, 2, "Usable packet types: "); + ti_ptype_subtree = proto_item_add_subtree(handle_tree, ett_ptype_subtree); + if (flag_DM1) + proto_item_append_text(handle_tree, "DM1 "); + if (flag_DH1) + proto_item_append_text(handle_tree, "DH3 "); + if (flag_DM3) + proto_item_append_text(handle_tree, "DM3 "); + if (flag_DH3) + proto_item_append_text(handle_tree, "DH3 "); + if (flag_DM5) + proto_item_append_text(handle_tree, "DM5 "); + if (flag_DH5) + proto_item_append_text(handle_tree, "DH5 "); + if (flag_HV1) + proto_item_append_text(handle_tree, "HV1 "); + if (flag_HV2) + proto_item_append_text(handle_tree, "HV2 "); + if (flag_HV3) + proto_item_append_text(handle_tree, "HV3 "); + + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_dm1, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_dh1, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_dm3, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_dh3, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_dm5, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_dh5, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_hv1, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_hv2, tvb, 5, 2, TRUE); + proto_tree_add_item(ti_ptype_subtree, hf_bthci_evt_link_type_hv3, tvb, 5, 2, TRUE); + break; + + case 0x1e: /* QoS Violation */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_connection_handle, tvb, 2, 2, TRUE); + break; + + case 0x1f: /* Page Scan Mode Change */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 2, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_page_scan_mode, tvb, 8, 1, TRUE); + break; + + case 0x20: /*Page Scan Repetition Mode Change */ + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_bd_addr, tvb, 2, 6, TRUE); + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_page_scan_repetition_mode, tvb, 8, 1, TRUE); + break; + + default: + proto_tree_add_item(bthci_evt_tree, hf_bthci_evt_params, tvb, 2, -1, TRUE); + break; + } + + } + + + +} + + +/* Register the protocol with Ethereal */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_bthci_evt(void) +{ + +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_bthci_evt_code, + { "Event Code", "bthci_evt.code", + FT_UINT8, BASE_HEX, VALS(evt_code_vals), 0x0, + "Event Code" } + }, + { &hf_bthci_evt_param_length, + { "Parameter Total Length", "bthci_evt.param_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Parameter Total Length" } + }, + { &hf_bthci_evt_params, + { "Event Parameter", "bthci_evt.params", + FT_NONE, BASE_NONE, NULL, 0x0, + "Event Parameter" } + }, + { &hf_bthci_evt_num_command_packets, + { "Number of Allowed Command Packets", "bthci_evt.num_command_packets", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Allowed Command Packets" } + }, + { &hf_bthci_evt_num_handles, + { "Number of Connection Handles", "bthci_evt.num_handles", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Connection Handles and Num_HCI_Data_Packets parameter pairs" } + }, + { &hf_bthci_evt_connection_handle, + { "Connection Handle", "bthci_evt.connection_handle", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Connection Handle" } + }, + + { &hf_bthci_evt_num_compl_packets, + { "Number of Completed Packets", "bthci_evt.num_compl_packets", + FT_UINT16, BASE_DEC, NULL, 0x0, + "The number of HCI Data Packets that have been completed" } + }, + + { &hf_bthci_evt_com_opcode, + { "Command Opcode", "bthci_evt.com_opcode", + FT_UINT16, BASE_HEX, VALS(cmd_opcode_vals), 0x0, + "Command Opcode" } + }, + { &hf_bthci_evt_ogf, + { "ogf", "bthci_evt.ogf", + FT_UINT16, BASE_HEX, VALS(ogf_vals), 0xfc00, + "Opcode Group Field" } + }, + { &hf_bthci_evt_ocf, + { "ocf", "bthci_evt.ocf", + FT_UINT16, BASE_HEX, NULL, 0x03ff, + "Opcode Command Field" } + }, + { &hf_bthci_evt_ret_params, + { "Return Parameter", "bthci_evt.ret_params", + FT_NONE, BASE_NONE, NULL, 0x0, + "Return Parameter" } + }, + { &hf_bthci_evt_status, + { "Status", "bthci_evt.status", + FT_UINT8, BASE_HEX, VALS(evt_status_vals), 0x0, + "Status" } + }, + { &hf_bthci_evt_bd_addr, + { "BD_ADDR", "bthci_evt.bd_addr", + FT_ETHER, BASE_HEX, NULL, 0x0, + "Bluetooth Device Address"} + }, + { &hf_bthci_evt_link_type, + { "Link Type", "bthci_evt.link_type", + FT_UINT8, BASE_HEX, VALS(evt_link_types), 0x0, + "Link Type" } + }, + { &hf_bthci_evt_encryption_mode, + { "Encryption Mode", "bthci_evt.encryption_mode", + FT_UINT8, BASE_HEX, VALS(evt_encryption_modes), 0x0, + "Encryption Mode" } + }, + { &hf_bthci_evt_class_of_device, + { "Class of Device", "bthci_evt.class_of_device", + FT_INT24, BASE_HEX, NULL, 0x0, + "Class of Device for the Device, which requested the connection"} + }, + { &hf_bthci_evt_reason, + { "Reason", "bthci_evt.reason", + FT_UINT8, BASE_HEX, VALS(evt_status_vals), 0x0, + "Reason" } + }, + { &hf_bthci_evt_remote_name, + { "Remote Name", "bthci_evt.remote_name", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Userfriendly descriptive name for the remote device" } + }, + { &hf_bthci_evt_encryption_enable, + { "Encryption Enable", "bthci_evt.encryption_enable", + FT_UINT8, BASE_HEX, VALS(evt_encryption_enable), 0x0, + "Encryption Enable" } + }, + { &hf_bthci_evt_key_flag, + { "Key Flag", "bthci_evt.key_flag", + FT_UINT8, BASE_HEX, VALS(evt_key_flag), 0x0, + "Key Flag" } + }, + { &hf_bthci_evt_vers_nr, + { "LMP Version", "bthci_evt.lmp_vers_nr", + FT_UINT8, BASE_HEX, VALS(evt_vers_nr), 0x0, + "Version of the Current LMP" } + }, + { &hf_bthci_evt_comp_id, + { "Manufacturer Name", "bthci_evt.comp_id", + FT_UINT8, BASE_HEX, VALS(evt_comp_id), 0x0, + "Manufacturer Name of Bluetooth Hardware" } + }, + { &hf_bthci_evt_sub_vers_nr, + { "LMP Subversion", "bthci_evt.lmp_sub_vers_nr", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Subversion of the Current LMP" } + }, + { &hf_bthci_evt_flags, + { "Flags", "bthci_evt.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Flags" } + }, + { &hf_bthci_evt_service_type, + { "Service Type", "bthci_evt.service_type", + FT_UINT8, BASE_HEX, VALS(evt_service_types), 0x0, + "Service Type" } + }, + { &hf_bthci_evt_token_rate, + { "Available Token Rate", "bthci_evt.token_rate", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Available Token Rate, in bytes per second" } + }, + { &hf_bthci_evt_peak_bandwidth, + { "Available Peak Bandwidth", "bthci_evt.peak_bandwidth", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Available Peak Bandwidth, in bytes per second" } + }, + { &hf_bthci_evt_latency, + { "Available Latecy", "bthci_evt.latency", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Available Latency, in microseconds" } + }, + { &hf_bthci_evt_delay_variation, + { "Available Delay Variation", "bthci_evt.delay_variation", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Available Delay Variation, in microseconds" } + }, + { &hf_bthci_evt_hardware_code, + { "Hardware Code", "bthci_evt.hardware_code", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Hardware Code (implementation specific)" } + }, + { &hf_bthci_evt_role, + { "Role", "bthci_evt.role", + FT_UINT8, BASE_HEX, VALS(evt_role_vals), 0x0, + "Role" } + }, + { &hf_bthci_evt_curr_mode, + { "Current Mode", "bthci_evt.current_mode", + FT_UINT8, BASE_HEX, VALS(evt_modes), 0x0, + "Current Mode" } + }, + { &hf_bthci_evt_interval, + { "Interval", "bthci_evt.interval", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Interval - Number of Baseband slots" } + }, + { &hf_bthci_evt_link_key, + { "Link Key", "bthci_evt.link_key", + FT_BYTES, BASE_HEX, NULL, 0x0, + "Link Key for the associated BD_ADDR" } + }, + { &hf_bthci_evt_key_type, + { "Key Type", "bthci_evt.key_type", + FT_UINT8, BASE_HEX, VALS(evt_key_types), 0x0, + "Key Type" } + }, + { &hf_bthci_evt_max_slots, + { "Maximum Number of Slots", "bthci_evt.max_slots", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Maximum Number of slots allowed for baseband packets" } + }, + { &hf_bthci_evt_clock_offset, + { "Clock Offset", "bthci_evt.clock_offset", + FT_UINT8, BASE_HEX, NULL, 0x7FFFF, + "Bit 2-16 of the Clock Offset between CLKmaster-CLKslave" } + }, + { &hf_bthci_evt_page_scan_mode, + { "Page Scan Mode", "bthci_evt.page_scan_mode", + FT_UINT8, BASE_HEX, VALS(evt_page_scan_modes), 0x0, + "Page Scan Mode" } + }, + { &hf_bthci_evt_page_scan_repetition_mode, + { "Page Scan Repetition Mode", "bthci_evt.page_scan_repetition_mode", + FT_UINT8, BASE_HEX, VALS(evt_page_scan_repetition_modes), 0x0, + "Page Scan Repetition Mode" } + }, + { &hf_bthci_evt_page_scan_period_mode, + { "Page Scan Period Mode", "bthci_evt.page_scan_period_mode", + FT_UINT8, BASE_HEX, VALS(evt_page_scan_period_modes), 0x0, + "Page Scan Period Mode" } + }, + { &hf_bthci_evt_link_type_dm1, + { "ACL Link Type DM1", "bthci_evt.link_type_dm1", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0008, + "ACL Link Type DM1" } + }, + { &hf_bthci_evt_link_type_dh1, + { "ACL Link Type DH1", "bthci_evt.link_type_dh1", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0010, + "ACL Link Type DH1" } + }, + { &hf_bthci_evt_link_type_dm3, + { "ACL Link Type DM3", "bthci_evt.link_type_dm3", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0400, + "ACL Link Type DM3" } + }, + { &hf_bthci_evt_link_type_dh3, + { "ACL Link Type DH3", "bthci_evt.link_type_dh3", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0800, + "ACL Link Type DH3" } + }, + { &hf_bthci_evt_link_type_dm5, + { "ACL Link Type DM5", "bthci_evt.link_type_dm5", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x4000, + "ACL Link Type DM5" } + }, + { &hf_bthci_evt_link_type_dh5, + { "ACL Link Type DH5", "bthci_evt.link_type_dh5", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x8000, + "ACL Link Type DH5" } + }, + { &hf_bthci_evt_link_type_hv1, + { "SCO Link Type HV1", "bthci_evt.link_type_hv1", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0020, + "SCO Link Type HV1" } + }, + { &hf_bthci_evt_link_type_hv2, + { "SCO Link Type HV2", "bthci_evt.link_type_hv2", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0040, + "SCO Link Type HV2" } + }, + { &hf_bthci_evt_link_type_hv3, + { "SCO Link Type HV3", "bthci_evt.link_type_hv3", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0080, + "SCO Link Type HV3" } + }, + { &hf_bthci_evt_lmp_feature_00, + { "3-slot packets", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x01, + "3-slot packets" } + }, + { &hf_bthci_evt_lmp_feature_01, + { "5-slot packets", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x02, + "5-slot packets" } + }, + { &hf_bthci_evt_lmp_feature_02, + { "encryption", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x04, + "encryption" } + }, + { &hf_bthci_evt_lmp_feature_03, + { "slot offset", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x08, + "slot offset" } + }, + { &hf_bthci_evt_lmp_feature_04, + { "timing accuracy", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x10, + "timing accuracy" } + }, + { &hf_bthci_evt_lmp_feature_05, + { "switch", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x20, + "switch" } + }, + { &hf_bthci_evt_lmp_feature_06, + { "hold mode", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x40, + "hold mode" } + }, + { &hf_bthci_evt_lmp_feature_07, + { "sniff mode", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x80, + "sniff mode" } + }, + { &hf_bthci_evt_lmp_feature_10, + { "park mode", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x01, + "park mode" } + }, + { &hf_bthci_evt_lmp_feature_11, + { "RSSI", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x02, + "RSSI" } + }, + { &hf_bthci_evt_lmp_feature_12, + { "channel quality driven data rate", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x04, + "channel quality driven data rate" } + }, + { &hf_bthci_evt_lmp_feature_13, + { "SCO link", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x08, + "SCO link" } + }, + { &hf_bthci_evt_lmp_feature_14, + { "HV2 packets", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x10, + "HV2 packets" } + }, + { &hf_bthci_evt_lmp_feature_15, + { "HV3 packets", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x20, + "HV3 packets" } + }, + { &hf_bthci_evt_lmp_feature_16, + { "u-law log", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x40, + "u-law log" } + }, + { &hf_bthci_evt_lmp_feature_17, + { "A-law log", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x80, + "A-law log" } + }, + { &hf_bthci_evt_lmp_feature_20, + { "CVSD", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x01, + "CVSD" } + }, + { &hf_bthci_evt_lmp_feature_21, + { "paging scheme", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x02, + "paging scheme" } + }, + { &hf_bthci_evt_lmp_feature_22, + { "power control", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x04, + "power control" } + }, + { &hf_bthci_evt_lmp_feature_23, + { "transparent SCO data", "bthci_evt.lmp_feature", + FT_UINT8, BASE_BIN, VALS(evt_boolean), 0x08, + "transparent SCO data" } + }, + { &hf_bthci_evt_lmp_feature_24, + { "Flow control lag", "bthci_evt.lmp_feature", + FT_UINT8, BASE_DEC, VALS(evt_boolean), 0x70, + "Flow control lag" } + }, + { &hf_bthci_evt_num_keys, + { "Number of Link Keys", "bthci_evt.num_keys", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Link Keys contained" } + }, + { &hf_bthci_evt_num_responses, + { "Number of responses", "bthci_evt.num_responses", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Responses from Inquiry " } + }, + { &hf_bthci_evt_link_policy_setting_switch, + { "Enable Master Slave Switch", "bthci_evt.link_policy_switch", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0001, + "Enable Master Slave Switch" } + }, + { &hf_bthci_evt_link_policy_setting_hold, + { "Enable Hold Mode", "bthci_evt.link_policy_hold", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0002, + "Enable Hold Mode" } + }, + { &hf_bthci_evt_link_policy_setting_sniff, + { "Enable Sniff Mode", "bthci_evt.link_policy_sniff", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0004, + "Enable Sniff Mode" } + }, + { &hf_bthci_evt_link_policy_setting_park, + { "Enable Park Mode", "bthci_evt.link_policy_park", + FT_UINT16, BASE_BIN, VALS(evt_boolean), 0x0008, + "Enable Park Mode" } + }, + { &hf_bthci_evt_curr_role, + { "Current Role", "bthci_evt_curr_role", + FT_UINT8, BASE_HEX, VALS(evt_role_vals_handle), 0x0, + "Current role for this connection handle" } + }, + + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_bthci_evt, + &ett_opcode, + &ett_lmp_subtree, + &ett_ptype_subtree, + }; + +/* Register the protocol name and description */ + proto_bthci_evt = proto_register_protocol("Bluetooth HCI Event", + "HCI_EVT", "bthci_evt"); + + register_dissector("bthci_evt", dissect_bthci_evt, proto_bthci_evt); + + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_bthci_evt, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_bthci_evt(void) +{ + dissector_handle_t bthci_evt_handle; + + bthci_evt_handle = find_dissector("bthci_evt"); + + hci_com_handle = find_dissector("bthci_cmd"); +} + + diff -Nur ethereal-0.9.7/packet-btl2cap.c ethereal-0.9.7-patched/packet-btl2cap.c --- ethereal-0.9.7/packet-btl2cap.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btl2cap.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,919 @@ +/* packet-btl2cap.c + * Routines for the Bluetooth L2CAP dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include + + + + +/* structures needed for mapping between CIDs and PSMs */ +/* thankfully taken from BlueZ HCIDump by Maxim Krasnyansky */ + +#define CID_TABLE_SIZE 20 + +typedef struct { + guint16 cid; + guint16 psm; +} cid_info; + + +static cid_info cid_table[2][CID_TABLE_SIZE]; + +#define SCID cid_table[0] +#define DCID cid_table[1] + +static void add_cid(int in, guint16 cid, guint16 psm) +{ + cid_info *table = cid_table[in]; + int i; + + for (i=0; ifd->rel_secs + pinfo->fd->rel_usecs / 1000000.0; + + proto_tree_add_item(tree, hf_btl2cap_psm, tvb, offset+4, 2, TRUE); + proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset+6, 2, TRUE); + + if (pinfo->fd->flags.visited == 0) { + psm = tvb_get_letohs(tvb, offset+4); + scid = tvb_get_letohs(tvb, offset+6); + + add_cid(((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0), scid, psm); + + if ((conres=get_conres(((pinfo->p2p_dir == P2P_DIR_RECV) ? 0 : 1), scid))) { + /* There has been an early conres */ + if (conres->rel_time - rel_time > - 0.01) { + if ((psm = get_psm(((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0), conres->scid))) { + add_cid(((pinfo->p2p_dir == P2P_DIR_RECV) ? 0 : 1), conres->dcid, psm); + } + } + del_conres(((pinfo->p2p_dir == P2P_DIR_RECV) ? 0 : 1), conres->scid); + } + } +} + + + +void +dissect_connresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + + double rel_time; + guint16 scid, dcid, psm; + + rel_time = pinfo->fd->rel_secs + pinfo->fd->rel_usecs / 1000000.0; + + proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset+4, 2, TRUE); + proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset+6, 2, TRUE); + proto_tree_add_item(tree, hf_btl2cap_result, tvb, offset+8, 2, TRUE); + proto_tree_add_item(tree, hf_btl2cap_status, tvb, offset+10, 2, TRUE); + + + if (pinfo->fd->flags.visited == 0) { + dcid = tvb_get_letohs(tvb, offset+4); + scid = tvb_get_letohs(tvb, offset+6); + + if ((psm = get_psm(((pinfo->p2p_dir == P2P_DIR_RECV) ? 0 : 1), scid))) { + add_cid(((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0), dcid, psm); + } + else { /* We have no previous connreq: save conres for later */ + add_conres(((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0), + scid, dcid, rel_time); + } + } +} + +void +dissect_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int length) +{ + proto_item *ti_option; + proto_tree *ti_option_subtree; + guint8 option_type, option_length; + + if (length > 0) { + option_type = tvb_get_guint8(tvb, offset); + option_length = tvb_get_guint8(tvb, offset+1); + + ti_option = proto_tree_add_none_format(tree, + hf_btl2cap_option, tvb, + offset, option_length + 2, + "Option: "); + ti_option_subtree = proto_item_add_subtree(ti_option, ett_btl2cap_option); + + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_type, tvb, offset, 1, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_length, tvb, offset+1, 1, TRUE); + if (option_length >0) { + switch (option_type) { + + case 0x01: /* MTU */ + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mtu, tvb, offset+2, 2, TRUE); + proto_item_append_text(ti_option, "MTU"); + break; + + case 0x02: /* Flush timeout */ + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flushTO, tvb, offset+2, 2, TRUE); + proto_item_append_text(ti_option, "Flush Timeout"); + break; + + case 0x03: /* QOS */ + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flags, tvb, offset+2, 1, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset+3, 1, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenrate, tvb, offset+4, 4, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenbucketsize, tvb, offset+8, 4, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_peakbandwidth, tvb, offset+12, 4, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_latency, tvb, offset+16, 4, TRUE); + proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_delayvariation, tvb, offset+20, 4, TRUE); + proto_item_append_text(ti_option, "QOS"); + break; + + default: + proto_item_append_text(ti_option, "unknown"); + break; + } + } + dissect_options(tree, pinfo, tree, offset+2+option_length, length-2-option_length); + } +} + +void +dissect_disconnrequestresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + guint16 scid, dcid; + + proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset+4, 2, TRUE); + proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset+6, 2, TRUE); + + if (pinfo->fd->flags.visited == 0) { + dcid = tvb_get_letohs(tvb, offset+4); + scid = tvb_get_letohs(tvb, offset+6); + del_cid(((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0), dcid, scid); + } +} + + +void +dissect_comrej(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + guint16 reason; + + proto_tree_add_item(tree, hf_btl2cap_rej_reason, tvb, offset+4, 2, TRUE); + reason = tvb_get_letohs(tvb, offset+4); + + switch (reason) { + + case 0x0000: /* Command not understood */ + break; + + case 0x0001: /* Signaling MTU exceeded */ + proto_tree_add_item(tree, hf_btl2cap_sig_mtu, tvb, offset+6, 2, TRUE); + break; + + case 0x0002: /* Invalid CID in requets */ + proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset+6, 2, TRUE); + proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset+8, 2, TRUE); + break; + + default: + break; + } + +} + + +/* Code to actually dissect the packets */ +static void +dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *btl2cap_tree; + proto_tree *btl2cap_cmd_tree; + proto_item *ti_command; + guint16 length, cid, cmd_length; + gint offset; + guint8 cmd_code; + guint16 psm, info_type; + guint16 *psm_pointer; + int cmd_no = 0; + tvbuff_t *next_tvb; + char proto_info_buf[128]; + + proto_info_buf[0] = '\0'; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "L2CAP"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + ti = proto_tree_add_item(tree, proto_btl2cap, tvb, 0, -1, FALSE); + btl2cap_tree = proto_item_add_subtree(ti, ett_btl2cap); + + proto_tree_add_item(btl2cap_tree, hf_btl2cap_length, tvb, 0, 2, TRUE); + proto_tree_add_item(btl2cap_tree, hf_btl2cap_cid, tvb, 2, 2, TRUE); + + length = tvb_get_letohs(tvb, 0); + cid = tvb_get_letohs(tvb, 2); + + if (cid == 0x0001) { /* This is a command packet*/ + + offset = 4; /* Skip L2CAP header */ + + while (offset < length) { + cmd_no++; + + cmd_length = tvb_get_letohs(tvb, offset+2); + + ti_command = proto_tree_add_none_format(btl2cap_tree, + hf_btl2cap_command, tvb, + offset, cmd_length + 4, + "Command #%d: ", cmd_no); + + btl2cap_cmd_tree = proto_item_add_subtree(ti_command, ett_btl2cap_cmd); + + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_code, tvb, offset, 1, TRUE); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_ident, tvb, offset+1, 1, TRUE); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_length, tvb, offset+2, 2, TRUE); + + + cmd_code = tvb_get_guint8(tvb, offset); + + switch(cmd_code) { + + case 0x01: /* Command Reject */ + dissect_comrej(tvb, pinfo, btl2cap_cmd_tree, offset); + proto_item_append_text(ti_command, "Command Reject"); + break; + + case 0x02: /* Connection Request */ + dissect_connrequest(tvb, pinfo, btl2cap_cmd_tree, offset); + proto_item_append_text(ti_command, "Connection Request"); + break; + + case 0x03: /* Connection Response */ + dissect_connresponse(tvb, pinfo, btl2cap_cmd_tree, offset); + proto_item_append_text(ti_command, "Connection Response"); + break; + + case 0x04: /* Configure Request */ + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_dcid, tvb, offset+4, 2, TRUE); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_continuation_flag, tvb, offset+6, 2, TRUE); + if(tvb_get_letohs(tvb, offset+2)>0x0004) + dissect_options(tvb, pinfo, btl2cap_cmd_tree, offset+8, tvb_get_letohs(tvb, offset+2)-6); + proto_item_append_text(ti_command, "Configure Request"); + break; + + case 0x05: /* Configure Response */ + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_scid, tvb, offset+4, 2, TRUE); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_continuation_flag, tvb, offset+6, 2, TRUE); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_configuration_result, tvb, offset+8, 2, TRUE); + if(tvb_get_letohs(tvb, offset+2)>0x0006) + dissect_options(tvb, pinfo, btl2cap_cmd_tree, offset+10, tvb_get_letohs(tvb, offset+2)-6); + proto_item_append_text(ti_command, "Configure Response"); + break; + + case 0x06: /* Disconnect Request */ + dissect_disconnrequestresponse(tvb, pinfo, btl2cap_cmd_tree, offset); + proto_item_append_text(ti_command, "Disconnect Request"); + break; + + case 0x07: /* Disconnect Response */ + dissect_disconnrequestresponse(tvb, pinfo, btl2cap_cmd_tree, offset); + proto_item_append_text(ti_command, "Disconnect Response"); + break; + + case 0x08: /* Echo Request */ + proto_item_append_text(ti_command, "Echo Request"); + break; + + case 0x09: /* Echo Response */ + proto_item_append_text(ti_command, "Echo Response"); + break; + + case 0x0a: /* Information Request */ + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_info_type, tvb, offset+4, 2, TRUE); + proto_item_append_text(ti_command, "Information Request"); + break; + + case 0x0b: /* Information Response */ + info_type = tvb_get_ntohs(tvb, offset+4); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_info_type, tvb, offset+4, 2, TRUE); + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_info_result, tvb, offset+6, 2, TRUE); + if (tvb_get_letohs(tvb, offset+2)>0x0004) { + switch (info_type) { + + case 0x0001: /* Connectionless MTU */ + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_info_mtu, tvb, offset+8, 2, TRUE); + break; + + default: + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_data, tvb, offset+8, -1, TRUE); + break; + } + } + proto_item_append_text(ti_command, "Information Response"); + break; + + default: + proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_data, tvb, offset+4, -1, TRUE); + break; + } + + if (cmd_no != 1) { + strcat(proto_info_buf, ", "); + } + strcat(proto_info_buf, val_to_str(cmd_code, command_code_vals, "Unknown" )); + + offset += cmd_length + 4; /* Skip command data + header */ + } + if ((check_col(pinfo->cinfo, COL_INFO))) + col_add_str(pinfo->cinfo, COL_INFO, proto_info_buf ); + + } + + else if (cid == 0x0002) { /* Connectionless reception channel */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Connectionless reception channel"); + + proto_tree_add_item(btl2cap_tree, hf_btl2cap_psm, tvb, 4, 2, TRUE); + psm = tvb_get_letohs(tvb, 4); + + + next_tvb = tvb_new_subset(tvb, 6, -1, length); + + /* call next dissector */ + if (!dissector_try_port(l2cap_psm_dissector_table, (guint32) psm, + next_tvb, pinfo, tree)) { + /* unknown protocol. declare as data */ + proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, 6, -1, TRUE); + } + + } + + else if ((cid >= 0x0040) && (cid <= 0xFFFF)) { /* Connection oriented channel */ + + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Connection oriented channel"); + + if (pinfo->fd->flags.visited == 0) { + psm = get_psm(((pinfo->p2p_dir == P2P_DIR_RECV) ? 0 : 1), cid); + psm_pointer = malloc(sizeof(guint16)); + *psm_pointer = psm; + p_add_proto_data(pinfo->fd, proto_btl2cap, psm_pointer); + } + else if ((psm_pointer = p_get_proto_data(pinfo->fd, proto_btl2cap))) { + psm = *psm_pointer; + } + else { + psm = 0; + } + + + next_tvb = tvb_new_subset(tvb, 4, -1, length); + + if (psm != 0) { + /* call next dissector */ + if (!dissector_try_port(l2cap_psm_dissector_table, (guint32) psm, + next_tvb, pinfo, tree)) { + /* unknown protocol. declare as data */ + proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, 4, -1, TRUE); + } + } + else { + proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, 4, -1, TRUE); + } + + + } + else { /* Something else */ + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, 4, -1, TRUE); + } + + + +} + + + + + + + +/* Register the protocol with Ethereal */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_btl2cap(void) +{ + +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_btl2cap_length, + { "Length", "btl2cap.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "L2CAP Payload Length" } + }, + { &hf_btl2cap_cid, + { "CID", "btl2cap.cid", + FT_UINT16, BASE_HEX, NULL, 0x0, + "L2CAP Channel Identifier" } + }, + { &hf_btl2cap_payload, + { "Payload", "btl2cap.payload", + FT_NONE, BASE_NONE, NULL, 0x0, + "L2CAP Payload" } + }, + { &hf_btl2cap_command, + { "Command", "btl2cap.command", + FT_NONE, BASE_NONE, NULL, 0x0, + "L2CAP Command" } + }, + { &hf_btl2cap_cmd_code, + { "Command Code", "btl2cap.cmd_code", + FT_UINT8, BASE_HEX, VALS(command_code_vals), 0x0, + "L2CAP Command Code" } + }, + { &hf_btl2cap_cmd_ident, + { "Command Identifier", "btl2cap.cmd_ident", + FT_UINT8, BASE_HEX, NULL, 0x0, + "L2CAP Command Identifier" } + }, + { &hf_btl2cap_cmd_length, + { "Command Length", "btl2cap.cmd_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "L2CAP Command Length" } + }, + { &hf_btl2cap_cmd_data, + { "Command Data", "btl2cap.cmd_data", + FT_NONE, BASE_NONE, NULL, 0x0, + "L2CAP Command Data" } + }, + { &hf_btl2cap_psm, + { "PSM", "btl2cap.psm", + FT_UINT16, BASE_HEX, VALS(psm_vals), 0x0, + "Protocol/Service Multiplexor" } + }, + { &hf_btl2cap_scid, + { "Source CID", "btl2cap.scid", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Source Channel Identifier" } + }, + { &hf_btl2cap_dcid, + { "Destination CID", "btl2cap.dcid", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Destination Channel Identifier" } + }, + { &hf_btl2cap_result, + { "Result", "btl2cap.result", + FT_UINT16, BASE_HEX, VALS(result_vals), 0x0, + "Result" } + }, + { &hf_btl2cap_status, + { "Status", "btl2cap.status", + FT_UINT16, BASE_HEX, VALS(status_vals), 0x0, + "Status" } + }, + { &hf_btl2cap_rej_reason, + { "Reason", "btl2cap.rej_reason", + FT_UINT16, BASE_HEX, VALS(reason_vals), 0x0, + "Reason" } + }, + { &hf_btl2cap_sig_mtu, + { "Maximum Signalling MTU", "btl2cap.sig_mtu", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Maximum Signalling MTU" } + }, + { &hf_btl2cap_info_mtu, + { "Remote Entity MTU", "btl2cap.info_mtu", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Remote entitiys acceptable connectionless MTU" } + }, + { &hf_btl2cap_info_type, + { "Information Type", "btl2cap.info_type", + FT_UINT16, BASE_HEX, VALS(info_type_vals), 0x0, + "Type of implementation-specific information" } + }, + { &hf_btl2cap_info_result, + { "Result", "btl2cap.info_result", + FT_UINT16, BASE_HEX, VALS(info_result_vals), 0x0, + "Information about the success of the request" } + }, + { &hf_btl2cap_continuation_flag, + { "Continuation Flag", "btl2cap.continuation", + FT_BOOLEAN, BASE_BIN, NULL, 0x0001, + "Continuation Flag" } + }, + { &hf_btl2cap_configuration_result, + { "Result", "btl2cap.conf_result", + FT_UINT16, BASE_HEX, VALS(configuration_result_vals), 0x0, + "Configuration Result" } + }, + { &hf_btl2cap_option_type, + { "Type", "btl2cap.option_type", + FT_UINT8, BASE_HEX, VALS(option_type_vals), 0x0, + "Type of option" } + }, + { &hf_btl2cap_option_length, + { "Length", "btl2cap.option_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of octets in option payload " } + }, + { &hf_btl2cap_option_mtu, + { "MTU", "btl2cap.option_mtu", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Maximum Transmission Unit" } + }, + { &hf_btl2cap_option_flushTO, + { "Flush Timeout (ms)", "btl2cap.option_flushto", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Flush Timeout in milliseconds" } + }, + { &hf_btl2cap_option_flags, + { "Flags", "btl2cap.option_flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Flags - must be set to 0 (Reserved for future use)" } + }, + { &hf_btl2cap_option_service_type, + { "Service Type", "btl2cap.option_servicetype", + FT_UINT8, BASE_HEX, VALS(option_servicetype_vals), 0x0, + "Level of service required" } + }, + { &hf_btl2cap_option_tokenrate, + { "Token Rate (bytes/s)", "btl2cap.option_tokenrate", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Rate at which traffic credits are granted (bytes/s)" } + }, + { &hf_btl2cap_option_tokenbucketsize, + { "Token Bucket Size (bytes)", "btl2cap.option_tokenbsize", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Size of the token bucket (bytes)" } + }, + { &hf_btl2cap_option_peakbandwidth, + { "Peak Bandwidth (bytes/s)", "btl2cap.option_peakbandwidth", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Limit how fast packets may be sent (bytes/s)" } + }, + { &hf_btl2cap_option_latency, + { "Latency (microseconds)", "btl2cap.option_latency", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Maximal acceptable dealy (microseconds)" } + }, + { &hf_btl2cap_option_delayvariation, + { "Delay Variation (microseconds)", "btl2cap.option_dealyvar", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Difference between maximum and minimum delay (microseconds)" } + }, + { &hf_btl2cap_option, + { "Configuration Parameter Option", "btl2cap.conf_param_option", + FT_NONE, BASE_NONE, NULL, 0x0, + "Configuration Parameter Option" } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_btl2cap, + &ett_btl2cap_cmd, + &ett_btl2cap_option, + }; + +/* Register the protocol name and description */ + proto_btl2cap = proto_register_protocol("Bluetooth L2CAP Packet", + "L2CAP", "btl2cap"); + + register_dissector("btl2cap", dissect_btl2cap, proto_btl2cap); + + +/* subdissector code */ + l2cap_psm_dissector_table = register_dissector_table("btl2cap.psm", + "L2CAP PSM", FT_UINT16, BASE_HEX); + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_btl2cap, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_init_routine(l2cap_map_init); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_btl2cap(void) +{ + dissector_handle_t btl2cap_handle; + + btl2cap_handle = find_dissector("btl2cap"); + +} + + diff -Nur ethereal-0.9.7/packet-btrfcomm.c ethereal-0.9.7-patched/packet-btrfcomm.c --- ethereal-0.9.7/packet-btrfcomm.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btrfcomm.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,848 @@ +/* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ + +/* packet-btrfcomm.c + * Routines for Bluetooth RFCOMM protocol dissection + * Copyright 2002, Wolfgang Hansmann + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include +#include + +#include "packet-btrfcomm.h" + + +dlci_state state[64]; /* need this to keep track on stuff that is negotiated upon + * dlci setup */ + +static dissector_handle_t data_handle; +static dissector_handle_t ppp_handle; + +static const value_string vs_ctl_pn_i[] = { + {0x0, "use UIH Frames"}, + + /* specified by 07.10, but not used by RFCOMM + + {0x1, "use UI Frames"}, + {0x2, "use I Frames"}, + + */ + + {0, NULL} +}; + +static const value_string vs_ctl_pn_cl[] = { + + {0x0, "no credit based flow control scheme"}, + {0xe, "support of credit based flow control scheme (resp)"}, + {0xf, "support of credit based flow control scheme (req)"}, + + /* specified by 07.10. Redefined by RFCOMM + + {0x0, "type 1 (unstructured octet stream)"}, + {0x1, "type 2 (unstructured octet stream with flow control)"}, + {0x2, "type 3 (uninterruptible framed data)"}, + {0x3, "type 4 (interruptible framed data)"}, + + */ + + {0, NULL} +}; + +static const value_string vs_ctl_rpn_b[] = { + {0, "2400"}, + {1, "4800"}, + {2, "7200"}, + {3, "9600"}, + {4, "19200"}, + {5, "38400"}, + {6, "57600"}, + {7, "115200"}, + {8, "230400"} +}; + + +static const value_string vs_ctl_rpn_d[] = { + {0x0, "5"}, + {0x2, "6"}, + {0x1, "7"}, + {0x3, "8"}, + {0, NULL} +}; + + +static const value_string vs_ctl_rpn_s[] = { + {0, "1"}, + {1, "1.5"}, + {0, NULL} +}; + + +static const true_false_string tfs_ctl_rpn_p = { + "parity", "no parity" +}; + + +static const value_string vs_ctl_rpn_pt[] = { + {0, "odd parity"}, + {1, "even parity"}, + {2, "mark parity"}, + {3, "space parity"}, + {0, NULL} +}; + + +static const value_string vs_ctl_rls_l[] = { + + /* L1 == 1, masked 0x0e */ + + {0x1, "Overrun error"}, + {0x2, "Parity error"}, + {0x4, "Framing error"}, + {0, NULL} +}; + + +static const value_string vs_rfcomm_addr_d[] = { + {1, "Server Device"}, + {0, "Initiating Device"}, + {0, NULL} +}; + + +static const value_string vs_frame_type[] = { + + /* masked 0xef */ + + {0x2f, "Set Asynchronous Balanced Mode (SABM)"}, + {0x63, "Unnumbered Acknowledgement (UA)"}, + {0x0f, "Disconnected Mode (DM)"}, + {0x43, "Disconnect (DISC)"}, + {0xef, "Unnumbered Information with Header check (UIH)"}, + + /* specified by 07.10, but not used by RFCOMM + + {0x03, "Unnumbered Information (UI)"}, + + */ + + {0, NULL} +}; + + +static const value_string vs_frame_type_short[] = { + + /* masked 0xef */ + + {0x2f, "SABM"}, + {0x63, "UA"}, + {0x0f, "DM"}, + {0x43, "DISC"}, + {0xef, "UIH"}, + + /* specified by 07.10, but not used by RFCOMM + + {0x03, "UI"}, + + */ + + {0, NULL} +}; + + +static const value_string vs_ctl[] = { + + /* masked 0xfc */ + + {0x20, "DLC parameter negotiation (PN)"}, + {0x08, "Test Command (Test)"}, + {0x28, "Flow Control On Command (FCon)"}, + {0x18, "Flow Control Off Command (FCoff)"}, + {0x38, "Modem Status Command (MSC)"}, + {0x04, "Non Supported Command Response (NSC)"}, + {0x24, "Remote Port Negotiation Command (RPN)"}, + {0x14, "Remote Line Status Command (RLS)"}, + + /* Specified by 07.10, but not used by RFCOMM + + {0x10, "Power Saving Control (PSC)"}, + {0x30, "Multiplexer close down (CLD)"}, + {0x34, "Service Negotiation Command (SNC)"}, + + */ + + + /* old + + {0x80, "DLC parameter negotiation (PN)"}, + {0x20, "Test Command (Test)"}, + {0xa0, "Flow Control On Command (FCon)"}, + {0x60, "Flow Control Off Command (FCoff)"}, + {0xe0, "Modem Status Command (MSC)"}, + {0x10, "Non Supported Command Response (NSC)"}, + {0x90, "Remote Port Negotiation Command (RPN)"}, + {0x50, "Remote Line Status Command (RLS)"}, + + {0x40, "Power Saving Control (PSC)"}, + {0xc0, "Multiplexer close down (CLD)"}, + {0xd0, "Service Negotiation Command (SNC)"}, + + */ + + + {0x0, NULL} +}; + +static const value_string vs_ea[] = { + {1, "Last field octet"}, + {0, "More field octets following"}, + {0, NULL} +}; + +static const value_string vs_cr[] = { + {1, "Command"}, + {0, "Response"}, + {0, NULL} +}; + + +int get_le_multi_byte_value(tvbuff_t *tvb, int off, guint32 *val_ptr) { + + guint8 byte, bc = 0; + guint32 val = 0; + + do { + + byte = tvb_get_guint8(tvb, off++); + val |= ((byte >> 1) & 0xff) << (bc++ * 7); + + } while ((byte & 0x1) == 0); + + *val_ptr = val; + return bc; +} + + +static int hf_pf = -1; +static int hf_ea = -1; +static int hf_len = -1; +static int hf_frame_type = -1; +static int hf_cr = -1; +static int hf_dlci = -1; +static int hf_fc_credits = -1; + +static int hf_pn_i14 = -1; +static int hf_pn_c14 = -1; + +static int hf_mcc_ea = -1; +static int hf_mcc_cr = -1; +static int hf_mcc_cmd = -1; + +static int hf_msc_fc = -1; +static int hf_msc_rtc = -1; +static int hf_msc_rtr = -1; +static int hf_msc_ic = -1; +static int hf_msc_dv = -1; +static int hf_msc_l = -1; + +static int hf_fcs = -1; + + +/* Initialize the protocol and registered fields */ +static int proto_btrfcomm = -1; + + +/* Initialize the subtree pointers */ + +static gint ett_btrfcomm = -1; +static gint ett_btrfcomm_ctrl = -1; +static gint ett_addr = -1; +static gint ett_control = -1; +static gint ett_mcc = -1; +static gint ett_ctrl_pn_ci = -1; +static gint ett_ctrl_pn_v24 = -1; + +static void *my_malloc(int size) { + + void *p = calloc(size, 1); + + if (!p) { + perror("calloc()"); + exit(1); + } + return p; +} + + +int append_fragment(dlci_stream *pstream, tvbuff_t *tvb, int off, int len) { + + ppp_chunk *chnk = my_malloc(len + sizeof(ppp_chunk)); + const guint8 *ptr_src = tvb_get_ptr(tvb, off, len); + int src_index = 0, dst_index, eof = 0; + + /* ignore first 0x7e, break on first 0x7e */ + + for(dst_index = 0; dst_index < len; dst_index++) { + if (ptr_src[dst_index] == 0x7e) { + if (dst_index != 0) { + eof = 1; + break; + } + continue; + } + chnk->buf[src_index++] = ptr_src[dst_index]; + } + + if (src_index == 0) { + free(chnk); + return 0; + } + + chnk->len = src_index; + chnk->next = NULL; + + if (!pstream->first) + pstream->first = chnk; + else + pstream->last->next = chnk; + + pstream->last = chnk; + pstream->len += src_index; + + return eof; +} + + +void clear_fragments(dlci_stream *pstream) { + + ppp_chunk *curr = pstream->first, *curr_tmp; + + while (curr) { + curr_tmp = curr; + curr = curr->next; + free(curr_tmp); + } + + pstream->len = 0; + pstream->last = NULL; + pstream->first = NULL; +} + + +int decode_fragments(dlci_stream *pstream, guint8 *buf) { + + int real_len = 0, is_escaped = 0, chunk_index = 0; + ppp_chunk *chunk_curr = pstream->first; + + for (real_len = 0; chunk_curr;) { + + guint8 byte; + + /* fetch next byte */ + + byte = chunk_curr->buf[chunk_index++]; + if (chunk_index >= chunk_curr->len) { + chunk_index = 0; + chunk_curr = chunk_curr->next; + } + if (is_escaped) { + buf[real_len++] = byte ^ 0x20; + is_escaped = 0; + } else { + if (byte == 0x7d) + is_escaped = 1; + else + buf[real_len++] = byte; + } + + } + return real_len; +} + + +int dissect_ctrl_pn(packet_info *pinfo, proto_tree *t, tvbuff_t *tvb, + int off, int cr_flag) { + + proto_tree *st; + proto_item *ti; + + int dlci = tvb_get_guint8(tvb, off) & 0x3f; + int cl = tvb_get_guint8(tvb, off + 1) & 0xf0; + + proto_tree_add_text(t, tvb, off, 1, "DLCI: 0x%d", dlci); + + ti = proto_tree_add_text(t, tvb, off + 1, 1, "I1-I4: 0x%x, C1-C4: 0x%x", + tvb_get_guint8(tvb, off + 1) & 0xf, + (tvb_get_guint8(tvb, off + 1) >> 4) & 0xf); + st = proto_item_add_subtree(ti, ett_ctrl_pn_ci); + proto_tree_add_item(st, hf_pn_i14, tvb, off + 1, 1, FALSE); + proto_tree_add_item(st, hf_pn_c14, tvb, off + 1, 1, FALSE); + + proto_tree_add_text(t, tvb, off + 2, 1, "Priority: 0x%d", + tvb_get_guint8(tvb, off + 2) & 0x3f); + proto_tree_add_text(t, tvb, off + 3, 1, "Acknowledgement timer (T1): %d ms", + (guint32)tvb_get_guint8(tvb, off + 3) * 100); + proto_tree_add_text(t, tvb, off + 4, 2, "Maximum frame size (N1): %d", + tvb_get_letohs(tvb, off + 4)); + proto_tree_add_text(t, tvb, off + 6, 1, + "Max. number of retransmissions (N2): %d", + tvb_get_guint8(tvb, off + 6)); + proto_tree_add_text(t, tvb, off + 7, 1, "Error recovery mode: 0x%x", + tvb_get_guint8(tvb, off + 7) & 0x07); + + if (pinfo->fd->flags.visited == 0) { + if (cl == 0) { + /* sender does not do credit based flow control */ + state[dlci].do_credit_fc = 0; + } else if (cr_flag && cl == 0xf0) { + /* sender requests to use credit based flow control */ + state[dlci].do_credit_fc |= 1; + } + else if (!cr_flag && cl == 0xe0) { + /* receiver also knows how to handle credit based + flow control */ + state[dlci].do_credit_fc |= 2; + } + } + + return 8; +} + + +int dissect_ctrl_msc(proto_tree *t, tvbuff_t *tvb, int off, int length) { + + proto_tree *st; + proto_item *it; + + guint8 status = tvb_get_guint8(tvb, off + 1); + + proto_tree_add_text(t, tvb, off, 1, "DLCI: 0x%d", + (tvb_get_guint8(tvb, off) >> 2) & 0x3f); + it = proto_tree_add_text(t, tvb, off + 1, 2, "V.24 Signals: FC = %d, RTC = %d, " + "RTR = %d, IC = %d, DV = %d", (status >> 1) & 1, + (status >> 2) & 1, (status >> 3) & 1, + (status >> 6) & 1, (status >> 7) & 1); + st = proto_item_add_subtree(it, ett_ctrl_pn_v24); + + proto_tree_add_item(st, hf_msc_fc, tvb, off + 1, 1, FALSE); + proto_tree_add_item(st, hf_msc_rtc, tvb, off + 1, 1, FALSE); + proto_tree_add_item(st, hf_msc_rtr, tvb, off + 1, 1, FALSE); + proto_tree_add_item(st, hf_msc_ic, tvb, off + 1, 1, FALSE); + proto_tree_add_item(st, hf_msc_dv, tvb, off + 1, 1, FALSE); + + if (length == 3) { + proto_tree_add_text(t, tvb, off + 2, 1, "Break bits B1-B3: 0x%x", + (tvb_get_guint8(tvb, off + 2) & 0xf) >> 1); + proto_tree_add_item(t, hf_msc_l, tvb, off + 2, 1, FALSE); + } + + return length; +} + + +static void dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + rfcomm_packet_state *rps = p_get_proto_data(pinfo->fd, proto_btrfcomm); + proto_item *ti_main, *ti_addr, *ti_hctl, *ti; + proto_tree *st, *st_ctrl, *st_addr, *st_hctl; + int size, off, off_fcs, pf_flag, cr_flag, ea_flag; + guint8 frame_type; + guint32 frame_len, mcc_type = 0; + guint32 dlci; + char proto_info_buf[128]; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFCOMM"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + ti_main = proto_tree_add_item(tree, proto_btrfcomm, tvb, 0, -1, FALSE); + st = proto_item_add_subtree(ti_main, ett_btrfcomm); + + ea_flag = tvb_get_guint8(tvb, 0) & 0x01; + cr_flag = (tvb_get_guint8(tvb, 0) & 0x02) ? 1 : 0; + dlci = tvb_get_guint8(tvb, 0) >> 2; + + pf_flag = (tvb_get_guint8(tvb, 1) & 0x10) ? 1 : 0; + frame_type = tvb_get_guint8(tvb, 1) & 0xef; + + + ti_addr = proto_tree_add_text(st, tvb, 0, 1, "Address: E/A flag: %d, C/R " + "flag: %d, DLCI: %d", ea_flag, cr_flag, dlci); + st_addr = proto_item_add_subtree(ti_addr, ett_addr); + + proto_tree_add_item(st_addr, hf_ea, tvb, 0, 1, FALSE); + proto_tree_add_item(st_addr, hf_cr, tvb, 0, 1, FALSE); + proto_tree_add_item(st_addr, hf_dlci, tvb, 0, 1, FALSE); + + ti_hctl = proto_tree_add_text(st, tvb, 1, 1, "Control: Frame type: %s (0x%x), " + "P/F flag: %d", + val_to_str(frame_type, vs_frame_type, "Unknown"), + frame_type, pf_flag); + + st_hctl = proto_item_add_subtree(ti_hctl, ett_control); + + proto_tree_add_item(st_hctl, hf_pf, tvb, 1, 1, FALSE); + proto_tree_add_item(st_hctl, hf_frame_type, tvb, 1, 1, FALSE); + + frame_len = tvb_get_guint8(tvb, 2); + if (frame_len & 0x1) { + frame_len >>= 1; /* 0 - 127 */ + size = 1; + } else { + frame_len >>= 1; /* 128 - ... */ + frame_len |= (tvb_get_guint8(tvb, 3)) << 7; + size = 2; + } + proto_tree_add_uint(st, hf_len, tvb, 2, size, frame_len); + + off = 2 + size; + + if (frame_type == 0xef /* UID frame */ && dlci != 0 && pf_flag) { + + if (pinfo->fd->flags.visited == 0 && + ((state[dlci].do_credit_fc & 0x3) == 0x3)) { + + if (rps == NULL) + rps = my_malloc(sizeof(rfcomm_packet_state)); + + rps->do_credit_fc = 1; + p_add_proto_data(pinfo->fd, proto_btrfcomm, rps); + } + + if (rps && rps->do_credit_fc) { + + /* add credit based flow control byte */ + + proto_tree_add_item(st, hf_fc_credits, tvb, off, 1, FALSE); + off++; + } + } + + off_fcs = off + frame_len; + + if (dlci == 0 && frame_len > 0) { + + guint32 length; + int mcc_len, mcc_cr_flag, mcc_ea_flag; + char *mcc_type_name; + proto_tree *st_mcc; + proto_item *ti_mcc; + + ti = proto_tree_add_text(st, tvb, off, 1, + "Multiplexer Control Command"); + st_ctrl = proto_item_add_subtree(ti, ett_btrfcomm_ctrl); + + size = get_le_multi_byte_value(tvb, off, &mcc_type); + mcc_type = (mcc_type >> 1) & 0x3f; /* shift c/r flag off */ + mcc_cr_flag = (tvb_get_guint8(tvb, off) & 0x2) ? 1 : 0; + mcc_ea_flag = tvb_get_guint8(tvb, off) & 0x1; + mcc_type_name = val_to_str(mcc_type, vs_ctl, "Unknown"); + + ti_mcc = proto_tree_add_text(st_ctrl, tvb, off, 1, "Type: %s (0x%x), " + "C/R flag = %d, E/A flag = %d", + mcc_type_name, mcc_type, mcc_cr_flag, + mcc_ea_flag); + st_mcc = proto_item_add_subtree(ti_mcc, ett_mcc); + + proto_tree_add_item(st_mcc, hf_mcc_cmd, tvb, off, size, FALSE); + proto_tree_add_item(st_mcc, hf_mcc_cr, tvb, off, 1, FALSE); + proto_tree_add_item(st_mcc, hf_mcc_ea, tvb, off, 1, FALSE); + + proto_item_append_text(ti, ": %s", mcc_type_name); + + off += size; + mcc_len = size; + + size = get_le_multi_byte_value(tvb, off, &length); + proto_tree_add_text(st_ctrl, tvb, off, size, "Length: %d", length); + + off += size; + mcc_len += size + length; + proto_item_set_len(ti, mcc_len); + + switch(mcc_type) { + case 0x20: /* Parameter Negotiation */ + size = dissect_ctrl_pn(pinfo, st_ctrl, tvb, off, mcc_cr_flag); + break; + case 0x38: /* Model Status Command */ + size = dissect_ctrl_msc(st_ctrl, tvb, off, length); + break; + default: + size = length; + } + off += size; + } + + /* set column info and protocol headline */ + + snprintf(proto_info_buf, 127, "%s, DLCI = %d", + val_to_str(frame_type, vs_frame_type_short, "Unknown"), dlci); + if (mcc_type) { + strcat(proto_info_buf, ", "); + strcat(proto_info_buf, val_to_str(mcc_type, vs_ctl, "Unknown")); + } + + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_str(pinfo->cinfo, COL_INFO, proto_info_buf); + proto_item_append_text(st, ": %s", proto_info_buf); + + proto_tree_add_item(st, hf_fcs, tvb, off_fcs, 1, FALSE); + + if (dlci != 0 && frame_len > 0) { + + tvbuff_t *next_tvb; + + if (frame_type == 0xef && pinfo->fd->flags.visited == 0) { + + dlci_stream *pstream = &state[dlci].direction[cr_flag]; + + if (append_fragment(pstream, tvb, off, frame_len)) { + + /* was last fragment */ + + guint8 *buf; + + /* reassemble and unescape fragments into buf */ + + if (rps == NULL) { + rps = my_malloc(sizeof(rfcomm_packet_state)); + p_add_proto_data(pinfo->fd, proto_btrfcomm, + rps); + } + + buf = my_malloc(pstream->len); + + rps->ppp_len = decode_fragments(pstream, buf); + rps->ppp_frame = buf; /* that's it */ + + clear_fragments(pstream); + } + } + + if (rps && rps->ppp_frame) { + next_tvb = tvb_new_real_data(rps->ppp_frame, rps->ppp_len, + rps->ppp_len); + tvb_set_child_real_data_tvbuff(tvb, next_tvb); + add_new_data_source(pinfo, next_tvb, "Reassembled PPP frame"); + + + call_dissector(ppp_handle, next_tvb, pinfo, tree); + } else { + next_tvb = tvb_new_subset(tvb, off, frame_len, frame_len); + call_dissector(data_handle, next_tvb, pinfo, tree); + } + } +} + + +void proto_register_btrfcomm(void) +{ + static hf_register_info hf[] = { + {&hf_dlci, + {"DLCI", "btrfcomm.dlci", + FT_UINT8, BASE_HEX, NULL, 0xfc, + "RFCOMM DLCI", HFILL} + }, + {&hf_ea, + {"EA Flag", "btrfcomm.ea", + FT_UINT8, BASE_HEX, VALS(vs_ea), 0x1, + "EA flag (should be always 1)", HFILL} + }, + {&hf_cr, + {"C/R Flag", "btrfcomm.cr", + FT_UINT8, BASE_HEX, VALS(vs_cr), 0x2, + "Command/Response flag", HFILL} + }, + {&hf_mcc_ea, + {"EA Flag", "btrfcomm.mcc.ea", + FT_UINT8, BASE_HEX, VALS(vs_ea), 0x1, + "EA flag (should be always 1)", HFILL} + }, + {&hf_mcc_cr, + {"C/R Flag", "btrfcomm.mcc.cr", + FT_UINT8, BASE_HEX, VALS(vs_cr), 0x2, + "Command/Response flag", HFILL} + }, + {&hf_mcc_cmd, + {"C/R Flag", "btrfcomm.mcc.cmd", + FT_UINT8, BASE_HEX, VALS(vs_ctl), 0xfc, + "Command/Response flag", HFILL} + }, + {&hf_frame_type, + {"Frame type", "btrfcomm.frame_type", + FT_UINT8, BASE_HEX, VALS(vs_frame_type), 0xef, + "Command/Response flag", HFILL} + }, + {&hf_pf, + {"P/F flag", "btrfcomm.pf", + FT_UINT8, BASE_HEX, NULL, 0x10, + "Poll/Final bit", HFILL} + }, + {&hf_pn_i14, + {"Type of frame", "btrfcomm.pn.i", + FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_i), 0x0f, + "Type of information frames used for that particular DLCI", + HFILL} + }, + {&hf_pn_c14, + {"Convergence layer", "btrfcomm.pn.cl", + FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_cl), 0xf0, + "Convergence layer used for that particular DLCI", HFILL} + }, + {&hf_len, + {"Payload length", "btrfcomm.len", + FT_UINT32, BASE_DEC, NULL, 0, + "Frame length", HFILL} + }, + {&hf_fcs, + {"Frame Check Sequence", "btrfcomm.fcs", + FT_UINT8, BASE_HEX, NULL, 0, + "Checksum over frame", HFILL} + }, + {&hf_msc_fc, + {"Flow Control (FC)", "btrfcomm.msc.fc", + FT_UINT8, BASE_HEX, NULL, 0x2, + "Flow Control", HFILL} + }, + {&hf_msc_rtc, + {"Ready To Communicate (RTC)", "btrfcomm.msc.rtc", + FT_UINT8, BASE_HEX, NULL, 0x4, + "Ready To Communicate", HFILL} + }, + {&hf_msc_rtr, + {"Ready To Receive (RTR)", "btrfcomm.msc.rtr", + FT_UINT8, BASE_HEX, NULL, 0x8, + "Ready To Receive", HFILL} + }, + {&hf_msc_ic, + {"Incoming Call Indicator (IC)", "btrfcomm.msc.ic", + FT_UINT8, BASE_HEX, NULL, 0x40, + "Incoming Call Indicator", HFILL} + }, + {&hf_msc_dv, + {"Data Valid (DV)", "btrfcomm.msc.dv", + FT_UINT8, BASE_HEX, NULL, 0x80, + "Data Valid", HFILL} + }, + {&hf_msc_l, + {"Length of break in units of 200ms", "btrfcomm.msc.bl", + FT_UINT8, BASE_DEC, NULL, 0xf0, + "Length of break in units of 200ms", HFILL} + }, + {&hf_fc_credits, + {"Credits", "btrfcomm.credits", + FT_UINT8, BASE_DEC, NULL, 0, + "Flow control: number of UIH frames allowed to send", HFILL} + } + + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_btrfcomm, + &ett_btrfcomm_ctrl, + &ett_addr, + &ett_control, + &ett_mcc, + &ett_ctrl_pn_ci, + &ett_ctrl_pn_v24 + }; + + int i, j; + + for (i = 0; i<64; i++) { + + state[i].do_credit_fc = 0; + + for (j = 0; j<2; j++) { + dlci_stream *p = &state[i].direction[j]; + p->first = p->last = NULL; + p->len = 0; + } + } + +/* Register the protocol name and description */ + + proto_btrfcomm = proto_register_protocol("Bluetooth RFCOMM Packet", + "RFCOMM", "btrfcomm"); + + register_dissector("btrfcomm", dissect_btrfcomm, proto_btrfcomm); + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_btrfcomm, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ + +void proto_reg_handoff_btrfcomm(void) +{ + dissector_handle_t btrfcomm_handle; + + btrfcomm_handle = find_dissector("btrfcomm"); + dissector_add("btl2cap.psm", 0x0003, btrfcomm_handle); + + data_handle = find_dissector("data"); + ppp_handle = find_dissector("ppp_hdlc"); +} + + + + + + + + + + + + diff -Nur ethereal-0.9.7/packet-btrfcomm.h ethereal-0.9.7-patched/packet-btrfcomm.h --- ethereal-0.9.7/packet-btrfcomm.h 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btrfcomm.h 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,48 @@ +/* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ + +#ifndef ETHEREAL_PACKET_BTRFCOMM_H +#define ETHEREAL_PACKET_BTRFCOMM_H + +typedef struct ppp_chunk_ { + struct ppp_chunk_ *next; + int len; + guint8 buf[1]; +} ppp_chunk; + +typedef struct dlci_stream_ { + + int len; + + ppp_chunk *first; + ppp_chunk *last; + +} dlci_stream; + +typedef struct dlci_state_ { + + char do_credit_fc; + dlci_stream direction[2]; + +} dlci_state; + + +typedef struct rfcomm_packet_state_ { + + int do_credit_fc; + guint8 *ppp_frame; + int ppp_len; + +} rfcomm_packet_state; + +#endif /* ETHEREAL_PACKET_BTRFCOMM_H */ + + + + + + + + + + + diff -Nur ethereal-0.9.7/packet-btsco.c ethereal-0.9.7-patched/packet-btsco.c --- ethereal-0.9.7/packet-btsco.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btsco.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,140 @@ +/* packet-bthci-evt.c + * Routines for the Bluetooth SCO dissection + * Copyright 2002, Christoph Scholz + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include + +/* Initialize the protocol and registered fields */ +static int proto_btsco = -1; +static int hf_btsco_chandle = -1; +static int hf_btsco_length = -1; +static int hf_btsco_data = -1; + +/* Initialize the subtree pointers */ +static gint ett_btsco = -1; + + +/* Code to actually dissect the packets */ +static void +dissect_btsco(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *btsco_tree; + + + ti = proto_tree_add_item(tree, proto_btsco, tvb, 0, -1, FALSE); + btsco_tree = proto_item_add_subtree(ti, ett_btsco); + + proto_tree_add_item(btsco_tree, hf_btsco_chandle, tvb, 0, 2, TRUE); + proto_tree_add_item(btsco_tree, hf_btsco_length, tvb, 2, 1, TRUE); + proto_tree_add_item(btsco_tree, hf_btsco_data, tvb, 3, -1, TRUE); + +} + + +/* Register the protocol with Ethereal */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_btsco(void) +{ + +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_btsco_chandle, + { "Connection Handle", "btsco.chandle", + FT_UINT16, BASE_HEX, NULL, 0x0FFF, + "Connection Handle" } + }, + { &hf_btsco_length, + { "Data Total Length", "btsco.length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Data Total Length" } + }, + { &hf_btsco_data, + { "Data", "btsco.data", + FT_NONE, BASE_NONE, NULL, 0x0, + "Data" } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_btsco, + }; + +/* Register the protocol name and description */ + proto_btsco = proto_register_protocol("Bluetooth SCO Packet", + "SCO", "btsco"); + + register_dissector("btsco", dissect_btsco, proto_btsco); + + + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_btsco, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ +void +proto_reg_handoff_btsco(void) +{ + dissector_handle_t btsco_handle; + + btsco_handle = find_dissector("btsco"); + +} + + diff -Nur ethereal-0.9.7/packet-btsdp.c ethereal-0.9.7-patched/packet-btsdp.c --- ethereal-0.9.7/packet-btsdp.c 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btsdp.c 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,889 @@ +/* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ + +/* packet-btsdp.c + * Routines for Bluetooth SDP dissection + * Copyright 2002, Wolfgang Hansmann + * + * $Id: ethereal_affix-2.patch,v 1.1 2002/10/31 08:38:05 kds Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include +#include +#include + +#include "packet-btsdp.h" + +/* Initialize the protocol and registered fields */ +static int proto_btsdp = -1; + +static int hf_pduid = -1; +static int hf_tid = -1; +static int hf_plen = -1; + +static int hf_ssr_total_count = -1; +static int hf_ssr_current_count = -1; +static int hf_error_code = -1; +static int hf_ssares_al_bytecount = -1; + + +/* Initialize the subtree pointers */ + +static gint ett_btsdp = -1; +static gint ett_btsdp_ssr = -1; +static gint ett_btsdp_des = -1; +static gint ett_btsdp_attribute = -1; +static gint ett_btsdp_service_search_pattern = -1; +static gint ett_btsdp_attribute_idlist = -1; + +static const value_string vs_pduid[] = { + {0x1, "SDP_ErrorResponse"}, + {0x2, "SDP_ServiceSearchRequest"}, + {0x3, "SDP_ServiceSearchResponse"}, + {0x4, "SDP_ServiceAttributeRequest"}, + {0x5, "SDP_ServiceAttributeResponse"}, + {0x6, "SDP_ServiceSearchAttributeRequest"}, + {0x7, "SDP_ServiceSearchAttributeResponse"}, + {0x0, NULL} +}; + +static const value_string vs_error_code[] = { + {0x0001, "Invalid/unsupported SDP version"}, + {0x0002, "Invalid Service Record Handle"}, + {0x0003, "Invalid request syntax"}, + {0x0004, "Invalid PDU size"}, + {0x0005, "Invalid Continuation State"}, + {0x0006, "Insufficient Resources to satisfy Request"}, + {0, NULL} +}; + +static const value_string vs_general_attribute_id[] = { + {0x0000, "ServiceRecordHandle"}, + {0x0001, "ServiceClassIDList"}, + {0x0002, "ServiceRecordState"}, + {0x0003, "ServiceID"}, + {0x0004, "ProtocolDescriptorList"}, + {0x0005, "BrowseGroupList"}, + {0x0006, "LanguageBaseAttributeIDList"}, + {0x0007, "ServiceinfoTimeToLive"}, + {0x0008, "ServiceAvailability"}, + {0x0009, "BluetoothProfileDescriptorList"}, + {0x000a, "DocumentationURL"}, + {0x000b, "ClientExecutableURL"}, + {0x000c, "IconURL"}, + + {0x0100, "Service Name"}, + {0x0101, "Service Description"}, + {0x0102, "Service Provider"}, + + {0, NULL} +}; + + +static const value_string vs_protocols[] = { + {0x0001, "SDP"}, + {0x0002, "UDP"}, + {0x0003, "RFCOMM"}, + {0x0004, "TCP"}, + {0x0005, "TCS-BIN"}, + {0x0006, "TCS-AT"}, + {0x0008, "OBEX"}, + {0x0009, "IP"}, + {0x000A, "FTP"}, + {0x000C, "HTTP"}, + {0x000E, "WSP"}, + {0x000F, "BNEP"}, + {0x0010, "UPNP"}, + {0x0011, "HIDP"}, + {0x0012, "HardcopyControlChannel"}, + {0x0014, "HardcopyDataChannel"}, + {0x0016, "HardcopyNotification"}, + {0x0017, "AVCTP"}, + {0x0019, "AVDTP"}, + {0x001B, "CMPT"}, + {0x001D, "UDI_C-Plane"}, + {0x0100, "L2CAP"}, + {0, NULL} +}; + +static const value_string vs_service_classes[] = { + + {0x0001, "SDP"}, + {0x0002, "UDP"}, + {0x0003, "RFCOMM"}, + {0x0004, "TCP"}, + {0x0005, "TCS-BIN"}, + {0x0006, "TCS-AT"}, + {0x0008, "OBEX"}, + {0x0009, "IP"}, + {0x000A, "FTP"}, + {0x000C, "HTTP"}, + {0x000E, "WSP"}, + {0x000F, "BNEP"}, + {0x0010, "UPNP"}, + {0x0011, "HIDP"}, + {0x0012, "HardcopyControlChannel"}, + {0x0014, "HardcopyDataChannel"}, + {0x0016, "HardcopyNotification"}, + {0x0017, "AVCTP"}, + {0x0019, "AVDTP"}, + {0x001B, "CMPT"}, + {0x001D, "UDI_C-Plane"}, + {0x0100, "L2CAP"}, + + {0x1000, "ServiceDiscoveryServerServiceClassID"}, + {0x1001, "BrowseGroupDescriptorServiceClassID"}, + {0x1002, "PublicBrowseGroup"}, + {0x1101, "SerialPort"}, + {0x1102, "LANAccessUsingPPP"}, + {0x1103, "DialupNetworking"}, + {0x1104, "IrMCSync"}, + {0x1105, "OBEXObjectPush"}, + {0x1106, "OBEXFileTransfer"}, + {0x1107, "IrMCSyncCommand"}, + {0x1108, "Headset"}, + {0x1109, "CordlessTelephony"}, + {0x110A, "AudioSource"}, + {0x110B, "AudioSink"}, + {0x110C, "A/V_RemoteControlTarget"}, + {0x110D, "AdvancedAudioDistribution"}, + {0x110E, "A/V_RemoteControl"}, + {0x110F, "VideoConferencing"}, + {0x1110, "Intercom"}, + {0x1111, "Fax"}, + {0x1112, "HeadsetAudioGateway"}, + {0x1113, "WAP"}, + {0x1114, "WAP_CLIENT"}, + {0x1115, "PANU"}, + {0x1116, "NAP"}, + {0x1117, "GN"}, + {0x1118, "DirectPrinting"}, + {0x1119, "ReferencePrinting"}, + {0x111A, "Imaging"}, + {0x111B, "ImagingResponder"}, + {0x111C, "ImagingAutomaticArchive"}, + {0x111D, "ImagingReferencedObjects"}, + {0x1115, "PANU"}, + {0x1116, "NAP"}, + {0x1117, "GN"}, + {0x1118, "DirectPrinting"}, + {0x1119, "ReferencePrinting"}, + {0x111A, "Imaging"}, + {0x111B, "ImagingResponder"}, + {0x111C, "ImagingAutomaticArchive"}, + {0x111D, "ImagingReferencedObjects"}, + {0x111E, "Handsfree"}, + {0x111F, "HandsfreeAudioGateway"}, + {0x1120, "DirectPrintingReferenceObjectsService"}, + {0x1121, "ReflectedUI"}, + {0x1122, "BasicPrinting"}, + {0x1123, "PrintingStatus"}, + {0x1124, "HumanInterfaceDeviceService"}, + {0x1125, "HardcopyCableReplacement"}, + {0x1126, "HCR_Print"}, + {0x1127, "HCR_Scan"}, + {0x1128, "Common_ISDN_Access"}, + {0x1129, "VideoConferencingGW"}, + {0x112A, "UDI_MT"}, + {0x112B, "UDI_TA"}, + {0x112C, "Audio/Video"}, + {0x112D, "SIM_Access"}, + {0x1200, "PnPInformation"}, + {0x1201, "GenericNetworking"}, + {0x1202, "GenericFileTransfer"}, + {0x1203, "GenericAudio"}, + {0x1204, "GenericTelephony"}, + {0x1205, "UPNP_Service"}, + {0x1206, "UPNP_IP_Service"}, + {0x1300, "ESDP_UPNP_IP_PAN"}, + {0x1301, "ESDP_UPNP_IP_LAP"}, + {0x1302, "ESDP_UPNP_L2CAP"}, + {0, NULL} +}; + +/* +static void *my_malloc(int size) { + + void *p = calloc(size, 1); + + if (!p) { + perror("calloc()"); + exit(1); + } + return p; +} +*/ + +static guint32 get_uint_by_size(tvbuff_t *tvb, int off, int size) { + + switch(size) { + case 0: + return tvb_get_guint8(tvb, off); + case 1: + return tvb_get_ntohs(tvb, off); + case 2: + return tvb_get_ntohl(tvb, off); + default: + return 0xffffffff; + } +} + + +static gint32 get_int_by_size(tvbuff_t *tvb, int off, int size) { + + switch(size) { + case 0: + return tvb_get_guint8(tvb, off); + case 1: + return tvb_get_ntohs(tvb, off); + case 2: + return tvb_get_ntohl(tvb, off); + default: + return -1; + } +} + + +void string_buf_init(string_buf *s, char *buf, int len) { + + s->buf = buf; + s->len = len; + s->curr_end = 0; +} + +int string_buf_append(string_buf *s, char *fmt, ...) { + + va_list ap; + int ret; + + va_start(ap, fmt); + + ret = vsnprintf(s->buf + s->curr_end, s->len - s->curr_end, fmt, ap); + if (ret > 0) + s->curr_end += ret; + if (s->curr_end > s->len) + s->curr_end = s->len; + s->buf[s->len - 1] = '\0'; + + va_end(ap); + + return ret; +} + + +static int get_type_length(tvbuff_t *tvb, int off, int *off_value) { + + int size = 0; + guint8 byte0 = tvb_get_guint8(tvb, off++); + + switch (byte0 & 0x07) { + case 0: + size = (byte0 >> 3) == 0 ? 0 : 1; + break; + case 1: + size = 2; + break; + case 2: + size = 4; + break; + case 3: + size = 8; + break; + case 4: + size = 16; + break; + case 5: + size = tvb_get_guint8(tvb, off); + off++; + break; + case 6: + size = tvb_get_ntohs(tvb, off); + off += 2; + break; + case 7: + size = tvb_get_ntohl(tvb, off); + off += 4; + break; + } + + *off_value = off; + return size; +} + + +static int dissect_sdp_type(proto_tree *t, tvbuff_t *tvb, int off, string_buf *sb) { + + int off_start = off, type_size; + guint8 byte0 = tvb_get_guint8(tvb, off); + guint8 type = byte0 >> 3; + guint8 size_index = byte0 & 0x07; + int size = 0; + + size = get_type_length(tvb, off, &off); + + type_size = off - off_start + size; + + switch (type) { + case 0: + proto_tree_add_text(t, tvb, off_start, type_size, "Nil"); + if (sb) + string_buf_append(sb, "Nil"); + break; + case 1: { + guint32 val = get_uint_by_size(tvb, off, size_index); + proto_tree_add_text(t, tvb, off_start, type_size, + "unsigned int %d", val); + if (sb) + string_buf_append(sb, "%u", val); + break; + } + case 2: { + guint32 val = get_int_by_size(tvb, off, size_index); + proto_tree_add_text(t, tvb, off_start, type_size, + "signed int %d", val); + if (sb) + string_buf_append(sb, "%d", val); + break; + } + case 3: { + + char *ptr = tvb_bytes_to_str(tvb, off, size); + + if (size == 2) { + + guint16 id = tvb_get_ntohs(tvb, off); + char *uuid_name = val_to_str(id, vs_service_classes, "Unknown"); + + proto_tree_add_text(t, tvb, off_start, type_size, + "%s(0x%s)", uuid_name, ptr); + if (sb) + string_buf_append(sb, "UUID %s (0x%s)", uuid_name, ptr); + } else { + + proto_tree_add_text(t, tvb, off_start, type_size, + "UUID 0x%s", ptr); + if (sb) + string_buf_append(sb, "0x%s", ptr); + } + break; + } + case 8: + /* fall through */ + case 4: { + char buf[4096]; + + strncpy(buf, tvb_get_ptr(tvb, off, size), 4096); + if (size < 4095) + buf[size] = 0; + else + buf[4095] = 0; + + proto_tree_add_text(t, tvb, off_start, type_size, "%s \"%s\"", + type == 8 ? "URL" : "String", buf); + if (sb) + string_buf_append(sb, "\"%s\"", buf); + break; + } + case 5: { + guint8 var = tvb_get_guint8(tvb, off); + + proto_tree_add_text(t, tvb, off_start, type_size, "%s", + var ? "true" : "false"); + if (sb) + string_buf_append(sb, "%s", var ? "true" : "false"); + break; + } + case 6: /* Data Element sequence */ + + /* fall through */ + + case 7: /* Data Element alternative */ { + + proto_tree *ti, *st; + int bytes_to_go = size; + int first = 1; + + ti = proto_tree_add_text(t, tvb, off_start, type_size, "%s", + type == 6 ? "Data Element sequence" : + "Data Element alternative"); + st = proto_item_add_subtree(ti, ett_btsdp_des); + + if (sb) + string_buf_append(sb, "{"); + + while (bytes_to_go > 0) { + + if (sb && !first) + string_buf_append(sb, ", "); + else + first = 0; + + size = dissect_sdp_type(st, tvb, off, sb); + off += size; + bytes_to_go -= size; + } + + if (sb) + string_buf_append(sb, "}"); + + break; + } + } + + return type_size; +} + + +static int dissect_sdp_service_attribute(proto_tree *t, tvbuff_t *tvb, int off) { + + proto_tree *st, *ti_sa, *ti_av; + int size; + char *att_name, buf[1024]; + string_buf sb; + guint16 id = tvb_get_ntohs(tvb, off + 1); + + att_name = val_to_str(id, vs_general_attribute_id, "Unknown"); + + ti_sa = proto_tree_add_text(t, tvb, off, -1, + "Service Attribute: id = %s (0x%x)", att_name, id); + st = proto_item_add_subtree(ti_sa, ett_btsdp_attribute); + + proto_tree_add_text(st, tvb, off, 3, "Attribute ID: %s (0x%x)", att_name, id); + ti_av = proto_tree_add_text(st, tvb, off + 3, -1, "Attribute Value"); + st = proto_item_add_subtree(ti_av, ett_btsdp_attribute); + + string_buf_init(&sb, buf, 1024); + size = dissect_sdp_type(st, tvb, off + 3, &sb); + proto_item_append_text(ti_sa, ", value = %s", sb.buf); + + proto_item_set_len(ti_sa, size + 3); + proto_item_set_len(ti_av, size); + + return size + 3; +} + + +static int dissect_sdp_service_attribute_list(proto_tree *t, tvbuff_t *tvb, int off) { + + proto_tree *st, *ti; + int off_start = off, size = 0, len; + + len = get_type_length(tvb, off, &off); + + ti = proto_tree_add_text(t, tvb, off_start, -1, "AttributeList"); + st = proto_item_add_subtree(ti, ett_btsdp_attribute); + + while (off - off_start < len) { + size = dissect_sdp_service_attribute(st, tvb, off); + off += size; + } + proto_item_set_len(ti, off - off_start); + return off - off_start; +} + + +static int dissect_sdp_service_attribute_list_array(proto_tree *t, tvbuff_t *tvb, + int off) { + proto_tree *st, *ti; + int off_start = off, size = 0, len; + + len = get_type_length(tvb, off, &off); + + ti = proto_tree_add_text(t, tvb, off_start, -1, "AttributeLists"); + st = proto_item_add_subtree(ti, ett_btsdp_attribute); + + while (off - off_start < len) { + size = dissect_sdp_service_attribute_list(st, tvb, off); + off += size; + } + proto_item_set_len(ti, off - off_start); + return off - off_start; +} + + +static int dissect_attribute_id_list(proto_tree *t, tvbuff_t *tvb, int off) { + + /* dissect attribute id list */ + + proto_item *ti; + proto_tree *st; + int off_start = off, bytes_to_go; + + ti = proto_tree_add_text(t, tvb, off, 2, "AttributeIDList"); + st = proto_item_add_subtree(ti, ett_btsdp_attribute_idlist); + + bytes_to_go = get_type_length(tvb, off, &off); + proto_item_set_len(ti, off - off_start + bytes_to_go); + + for (; off - off_start < bytes_to_go;) { + + guint8 byte0 = tvb_get_guint8(tvb, off); + + if (byte0 == 0x09) { /* 16 bit attribute id */ + + proto_tree_add_text(st, tvb, off, 3, "0x%04x", + tvb_get_ntohs(tvb, off + 1)); + off += 3; + + } else if (byte0 == 0x0a) { /* 32 bit attribute range */ + + proto_tree_add_text(st, tvb, off, 5, "0x%04x - 0x%04x", + tvb_get_ntohs(tvb, off + 1), + tvb_get_ntohs(tvb, off + 3)); + off += 5; + } + } + return off - off_start; +} + + +static int dissect_sdp_error_response(proto_tree *t, tvbuff_t *tvb, int off) { + + proto_tree_add_item(t, hf_error_code, tvb, off, 2, FALSE); + return -1; +} + + +static int dissect_sdp_service_search_request(proto_tree *t, tvbuff_t *tvb, int off) { + + int off_start = off, bytes_to_go, size; + proto_item *ti; + proto_tree *st; + + ti = proto_tree_add_text(t, tvb, off, 2, "ServiceSearchPattern"); + st = proto_item_add_subtree(ti, ett_btsdp_service_search_pattern); + + bytes_to_go = get_type_length(tvb, off, &off); + proto_item_set_len(ti, off - off_start + bytes_to_go); + + for (; off - off_start < bytes_to_go; off += size) { + size = dissect_sdp_type(st, tvb, off, NULL); + } + + /* dissect maximum service record count */ + + proto_tree_add_text(t, tvb, off, 2, "MaximumServiceRecordCount: %d", + tvb_get_ntohs(tvb, off)); + off += 2; + + proto_tree_add_text(t, tvb, off, -1, "ContinuationState"); + return -1; +} + + +static int dissect_sdp_service_search_response(proto_tree *t, tvbuff_t *tvb, int off) { + + proto_tree *st; + proto_item *ti; + + guint16 curr_count; + int i; + + proto_tree_add_item(t, hf_ssr_total_count, tvb, off, 2, FALSE); + proto_tree_add_item(t, hf_ssr_current_count, tvb, off + 2, 2, FALSE); + + curr_count = tvb_get_ntohs(tvb, off + 2); + + ti = proto_tree_add_text(t, tvb, off + 4, + curr_count * 4, "ServiceRecordHandleList"); + st = proto_item_add_subtree(ti, ett_btsdp_ssr); + + off += 4; + + for (i = 0; icinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDP"); + + ti = proto_tree_add_item(tree, proto_btsdp, tvb, 0, -1, FALSE); + st = proto_item_add_subtree(ti, ett_btsdp); + + proto_tree_add_item(st, hf_pduid, tvb, 0, 1, FALSE); + proto_tree_add_item(st, hf_tid, tvb, 1, 2, FALSE); + proto_tree_add_item(st, hf_plen, tvb, 3, 2, FALSE); + + pdu = tvb_get_guint8(tvb, 0); + plen = tvb_get_ntohs(tvb, 3); + + pdu_name = val_to_str(pdu, vs_pduid, "Unknown"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_str(pinfo->cinfo, COL_INFO, pdu_name); + proto_item_append_text(ti, ": %s (0x%x)", pdu_name, pdu); + + off = 5; + + switch(pdu) { + case 0x1: + dissect_sdp_error_response(st, tvb, off); + break; + case 0x2: + dissect_sdp_service_search_request(st, tvb, off); + break; + case 0x3: + dissect_sdp_service_search_response(st, tvb, off); + break; + case 0x4: + dissect_sdp_service_attribute_request(st, tvb, off); + break; + case 0x5: + dissect_sdp_service_attribute_response(st, tvb, off); + break; + case 0x6: + dissect_sdp_service_search_attribute_request(st, tvb, off); + break; + case 07: + dissect_sdp_service_search_attribute_response(st, tvb, off); + break; + } +} + + +void proto_register_btsdp(void) +{ + static hf_register_info hf[] = { + {&hf_pduid, + {"PDU", "btsdp.pdu", + FT_UINT8, BASE_HEX, VALS(vs_pduid), 0, + "PDU type", HFILL} + }, + {&hf_tid, + {"TransactionID", "btsdp.tid", + FT_UINT16, BASE_HEX, NULL, 0, + "Transaction ID", HFILL} + }, + {&hf_plen, + {"ParameterLength", "btsdp.len", + FT_UINT16, BASE_DEC, NULL, 0, + "ParameterLength", HFILL} + }, + {&hf_error_code, + {"ErrorCode", "btsdp.error_code", + FT_UINT16, BASE_HEX, NULL, 0, + "Error Code", HFILL} + }, + {&hf_ssr_total_count, + {"TotalServiceRecordCount", "btsdp.ssr.total_count", + FT_UINT16, BASE_DEC, NULL, 0, + "Total count of service records", HFILL} + }, + {&hf_ssr_current_count, + {"CurrentServiceRecordCount", "btsdp.ssr.current_count", + FT_UINT16, BASE_DEC, NULL, 0, + "count of service records in this message", HFILL} + }, + {&hf_ssares_al_bytecount, + {"AttributeListsByteCount", "btsdp.ssares.byte_count", + FT_UINT16, BASE_DEC, NULL, 0, + "count of bytes in attribute list response", HFILL} + } + }; + + /* Setup protocol subtree array */ + + static gint *ett[] = { + &ett_btsdp, + &ett_btsdp_ssr, + &ett_btsdp_des, + &ett_btsdp_attribute, + &ett_btsdp_service_search_pattern, + &ett_btsdp_attribute_idlist + }; + + proto_btsdp = proto_register_protocol("Bluetooth SDP", + "SDP", "btsdp"); + + register_dissector("btsdp", dissect_btsdp, proto_btsdp); + + + /* Required function calls to register the header fields and subtrees used */ + + proto_register_field_array(proto_btsdp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ + +void proto_reg_handoff_btsdp(void) +{ + dissector_handle_t btsdp_handle; + + btsdp_handle = find_dissector("btsdp"); + dissector_add("btl2cap.psm", 0x0001, btsdp_handle); +} + + + + + + + + + + + + diff -Nur ethereal-0.9.7/packet-btsdp.h ethereal-0.9.7-patched/packet-btsdp.h --- ethereal-0.9.7/packet-btsdp.h 1970-01-01 01:00:00.000000000 +0100 +++ ethereal-0.9.7-patched/packet-btsdp.h 2002-10-09 17:58:31.000000000 +0200 @@ -0,0 +1,25 @@ +/* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ + +#ifndef ETHEREAL_PACKET_BTSDP_H +#define ETHEREAL_PACKET_BTSDP_H + +typedef struct string_buf_ { + + char *buf; + int len; + int curr_end; + +} string_buf; + +#endif /* ETHEREAL_PACKET_BTSDP_H */ + + + + + + + + + + + diff -Nur ethereal-0.9.7/packet-ethertype.c ethereal-0.9.7-patched/packet-ethertype.c --- ethereal-0.9.7/packet-ethertype.c 2002-08-29 02:39:52.000000000 +0200 +++ ethereal-0.9.7-patched/packet-ethertype.c 2002-10-09 17:58:31.000000000 +0200 @@ -37,7 +37,7 @@ #include "etypes.h" #include "ppptypes.h" -static dissector_table_t ethertype_dissector_table; +dissector_table_t ethertype_dissector_table; static dissector_handle_t data_handle; diff -Nur ethereal-0.9.7/packet-sll.c ethereal-0.9.7-patched/packet-sll.c --- ethereal-0.9.7/packet-sll.c 2002-08-29 02:40:01.000000000 +0200 +++ ethereal-0.9.7-patched/packet-sll.c 2002-10-09 17:58:31.000000000 +0200 @@ -77,16 +77,19 @@ */ #define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */ #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */ +#define LINUX_SLL_P_AFFIX_HCI 0x0027 /* Bluetooth HCI */ static const value_string ltype_vals[] = { { LINUX_SLL_P_802_3, "Raw 802.3" }, { LINUX_SLL_P_802_2, "802.2 LLC" }, + { LINUX_SLL_P_AFFIX_HCI, "Affix HCI"}, { 0, NULL } }; static dissector_handle_t ipx_handle; static dissector_handle_t llc_handle; static dissector_handle_t data_handle; +static dissector_handle_t affix_hci_handle; void capture_sll(const guchar *pd, int len, packet_counts *ld) @@ -212,6 +215,11 @@ call_dissector(ipx_handle, next_tvb, pinfo, tree); break; + case LINUX_SLL_P_AFFIX_HCI: + call_dissector(affix_hci_handle, tvb, pinfo, tree); + break; + + default: call_dissector(data_handle,next_tvb, pinfo, tree); break; @@ -283,6 +291,7 @@ */ llc_handle = find_dissector("llc"); ipx_handle = find_dissector("ipx"); + affix_hci_handle = find_dissector("affix_hci"); data_handle = find_dissector("data"); sll_handle = create_dissector_handle(dissect_sll, proto_sll);