/* packet-btlmp.c * Routines for Bluetooth LMP dissection * Copyright 2009, Michael Ossmann * * Wireshark - 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #else #include #endif #include /* needed for epan/gcc-4.x */ #include #include /* LMP opcodes */ #define LMP_NAME_REQ 1 #define LMP_NAME_RES 2 #define LMP_ACCEPTED 3 #define LMP_NOT_ACCEPTED 4 #define LMP_CLKOFFSET_REQ 5 #define LMP_CLKOFFSET_RES 6 #define LMP_DETACH 7 #define LMP_IN_RAND 8 #define LMP_COMB_KEY 9 #define LMP_UNIT_KEY 10 #define LMP_AU_RAND 11 #define LMP_SRES 12 #define LMP_TEMP_RAND 13 #define LMP_TEMP_KEY 14 #define LMP_ENCRYPTION_MODE_REQ 15 #define LMP_ENCRYPTION_KEY_SIZE_REQ 16 #define LMP_START_ENCRYPTION_REQ 17 #define LMP_STOP_ENCRYPTION_REQ 18 #define LMP_SWITCH_REQ 19 #define LMP_HOLD 20 #define LMP_HOLD_REQ 21 #define LMP_SNIFF_REQ 23 #define LMP_UNSNIFF_REQ 24 #define LMP_PARK_REQ 25 #define LMP_SET_BROADCAST_SCAN_WINDOW 27 #define LMP_MODIFY_BEACON 28 #define LMP_UNPARK_BD_ADDR_REQ 29 #define LMP_UNPARK_PM_ADDR_REQ 30 #define LMP_INCR_POWER_REQ 31 #define LMP_DECR_POWER_REQ 32 #define LMP_MAX_POWER 33 #define LMP_MIN_POWER 34 #define LMP_AUTO_RATE 35 #define LMP_PREFERRED_RATE 36 #define LMP_VERSION_REQ 37 #define LMP_VERSION_RES 38 #define LMP_FEATURES_REQ 39 #define LMP_FEATURES_RES 40 #define LMP_QUALITY_OF_SERVICE 41 #define LMP_QUALITY_OF_SERVICE_REQ 42 #define LMP_SCO_LINK_REQ 43 #define LMP_REMOVE_SCO_LINK_REQ 44 #define LMP_MAX_SLOT 45 #define LMP_MAX_SLOT_REQ 46 #define LMP_TIMING_ACCURACY_REQ 47 #define LMP_TIMING_ACCURACY_RES 48 #define LMP_SETUP_COMPLETE 49 #define LMP_USE_SEMI_PERMANENT_KEY 50 #define LMP_HOST_CONNECTION_REQ 51 #define LMP_SLOT_OFFSET 52 #define LMP_PAGE_MODE_REQ 53 #define LMP_PAGE_SCAN_MODE_REQ 54 #define LMP_SUPERVISION_TIMEOUT 55 #define LMP_TEST_ACTIVATE 56 #define LMP_TEST_CONTROL 57 #define LMP_ENCRYPTION_KEY_SIZE_MASK_REQ 58 #define LMP_ENCRYPTION_KEY_SIZE_MASK_RES 59 #define LMP_SET_AFH 60 #define LMP_ENCAPSULATED_HEADER 61 #define LMP_ENCAPSULATED_PAYLOAD 62 #define LMP_SIMPLE_PAIRING_CONFIRM 63 #define LMP_SIMPLE_PAIRING_NUMBER 64 #define LMP_DHKEY_CHECK 65 #define LMP_ESCAPE_1 124 #define LMP_ESCAPE_2 125 #define LMP_ESCAPE_3 126 #define LMP_ESCAPE_4 127 /* LMP extended opcodes */ #define LMP_ACCEPTED_EXT 1 #define LMP_NOT_ACCEPTED_EXT 2 #define LMP_FEATURES_REQ_EXT 3 #define LMP_FEATURES_RES_EXT 4 #define LMP_PACKET_TYPE_TABLE_REQ 11 #define LMP_ESCO_LINK_REQ 12 #define LMP_REMOVE_ESCO_LINK_REQ 13 #define LMP_CHANNEL_CLASSIFICATION_REQ 16 #define LMP_CHANNEL_CLASSIFICATION 17 #define LMP_SNIFF_SUBRATING_REQ 21 #define LMP_SNIFF_SUBRATING_RES 22 #define LMP_PAUSE_ENCRYPTION_REQ 23 #define LMP_RESUME_ENCRYPTION_REQ 24 #define LMP_IO_CAPABILITY_REQ 25 #define LMP_IO_CAPABILITY_RES 26 #define LMP_NUMERIC_COMPARISON_FAILED 27 #define LMP_PASSKEY_FAILED 28 #define LMP_OOB_FAILED 29 #define LMP_KEYPRESS_NOTIFICATION 30 #define LMP_POWER_CONTROL_REQ 31 #define LMP_POWER_CONTROL_RES 32 /* initialize the protocol and registered fields */ static int proto_btlmp = -1; static int hf_lmp_accscheme = -1; static int hf_lmp_afhchmap = -1; static int hf_lmp_afhclass = -1; static int hf_lmp_afhinst = -1; static int hf_lmp_afhmaxintvl = -1; static int hf_lmp_afhminintvl = -1; static int hf_lmp_afhmode = -1; static int hf_lmp_afhrptmode = -1; static int hf_lmp_airmode = -1; static int hf_lmp_araddr = -1; static int hf_lmp_authreqs = -1; static int hf_lmp_authres = -1; static int hf_lmp_bdaddr = -1; static int hf_lmp_bdaddr1 = -1; static int hf_lmp_bdaddr2 = -1; static int hf_lmp_bsw = -1; static int hf_lmp_clkoffset = -1; static int hf_lmp_commit = -1; static int hf_lmp_confirm = -1; static int hf_lmp_compid = -1; static int hf_lmp_cryptmode = -1; static int hf_lmp_daccess = -1; static int hf_lmp_db = -1; static int hf_lmp_dbsleep = -1; static int hf_lmp_deltab = -1; static int hf_lmp_desco = -1; static int hf_lmp_drift = -1; static int hf_lmp_dsco = -1; static int hf_lmp_dsniff = -1; static int hf_lmp_encdata = -1; static int hf_lmp_enclen = -1; static int hf_lmp_encmaj = -1; static int hf_lmp_encmin = -1; static int hf_lmp_eop = -1; static int hf_lmp_eopinre = -1; static int hf_lmp_escolenms = -1; static int hf_lmp_escolensm = -1; static int hf_lmp_escotypems = -1; static int hf_lmp_escotypesm = -1; static int hf_lmp_err = -1; static int hf_lmp_escohdl = -1; static int hf_lmp_escoltaddr = -1; static int hf_lmp_features = -1; static int hf_lmp_fpage = -1; static int hf_lmp_htime = -1; static int hf_lmp_hinst = -1; static int hf_lmp_hopmode = -1; static int hf_lmp_iocaps = -1; static int hf_lmp_jitter = -1; static int hf_lmp_key = -1; static int hf_lmp_keysz = -1; static int hf_lmp_ksmask = -1; static int hf_lmp_ltaddr1 = -1; static int hf_lmp_ltaddr2 = -1; static int hf_lmp_ltaddr3 = -1; static int hf_lmp_ltaddr4 = -1; static int hf_lmp_ltaddr5 = -1; static int hf_lmp_ltaddr6 = -1; static int hf_lmp_ltaddr7 = -1; static int hf_lmp_maccess = -1; static int hf_lmp_maxslots = -1; static int hf_lmp_maxsp = -1; static int hf_lmp_maxss = -1; static int hf_lmp_minsmt = -1; static int hf_lmp_naccslots = -1; static int hf_lmp_namefrag = -1; static int hf_lmp_namelen = -1; static int hf_lmp_nameoffset = -1; static int hf_lmp_nb = -1; static int hf_lmp_nbc = -1; static int hf_lmp_nbsleep = -1; static int hf_lmp_negstate = -1; static int hf_lmp_nonce = -1; static int hf_lmp_nottype = -1; static int hf_lmp_npoll = -1; static int hf_lmp_oobauthdata = -1; static int hf_lmp_op = -1; static int hf_lmp_opinre = -1; static int hf_lmp_pagesch = -1; static int hf_lmp_pcmode = -1; static int hf_lmp_pkttype = -1; static int hf_lmp_pkttypetbl = -1; static int hf_lmp_pmaddr = -1; static int hf_lmp_pmaddr1 = -1; static int hf_lmp_pmaddr2 = -1; static int hf_lmp_pmaddr3 = -1; static int hf_lmp_pmaddr4 = -1; static int hf_lmp_pmaddr5 = -1; static int hf_lmp_pmaddr6 = -1; static int hf_lmp_pmaddr7 = -1; static int hf_lmp_pollintvl = -1; static int hf_lmp_pollper = -1; static int hf_lmp_pssettings = -1; static int hf_lmp_pwradjreq = -1; static int hf_lmp_pwradjres = -1; static int hf_lmp_pwradj_8dpsk = -1; static int hf_lmp_pwradj_dqpsk = -1; static int hf_lmp_pwradj_gfsk = -1; static int hf_lmp_rand = -1; static int hf_lmp_rate = -1; static int hf_lmp_rate_fec = -1; static int hf_lmp_rate_size = -1; static int hf_lmp_rate_type = -1; static int hf_lmp_rate_edrsize = -1; static int hf_lmp_rxfreq = -1; static int hf_lmp_scohdl = -1; static int hf_lmp_scopkt = -1; static int hf_lmp_slotoffset = -1; static int hf_lmp_sniffatt = -1; static int hf_lmp_sniffsi = -1; static int hf_lmp_sniffto = -1; static int hf_lmp_subversnr = -1; static int hf_lmp_suptimeout = -1; static int hf_lmp_swinst = -1; static int hf_lmp_taccess = -1; static int hf_lmp_tb = -1; static int hf_lmp_tesco = -1; static int hf_lmp_testlen = -1; static int hf_lmp_testscen = -1; static int hf_lmp_tid = -1; static int hf_lmp_timectrl = -1; static int hf_lmp_time_change = -1; static int hf_lmp_time_init = -1; static int hf_lmp_time_accwin = -1; static int hf_lmp_tsco = -1; static int hf_lmp_tsniff = -1; static int hf_lmp_txfreq = -1; static int hf_lmp_versnr = -1; static int hf_lmp_wesco = -1; /* timing control flags */ static const int *timectrl_fields[] = { &hf_lmp_time_change, &hf_lmp_time_init, &hf_lmp_time_accwin, /* bits 3-7 reserved */ NULL }; static const true_false_string time_change = { "timing change", "no timing change" }; static const true_false_string time_init = { "use initialization 2", "use initialization 1" }; static const true_false_string time_accwin = { "no access window", "access window" }; static const true_false_string fec = { "do not use FEC", "use FEC" }; static const true_false_string tid = { "transaction initiated by slave", "transaction initiated by master" }; /* short LMP opcodes */ static const value_string opcode[] = { { LMP_NAME_REQ, "LMP_name_req" }, { LMP_NAME_RES, "LMP_name_res" }, { LMP_ACCEPTED, "LMP_accepted" }, { LMP_NOT_ACCEPTED, "LMP_not_accepted" }, { LMP_CLKOFFSET_REQ, "LMP_clkoffset_req" }, { LMP_CLKOFFSET_RES, "LMP_clkoffset_res" }, { LMP_DETACH, "LMP_detach" }, { LMP_IN_RAND, "LMP_in_rand" }, { LMP_COMB_KEY, "LMP_comb_key" }, { LMP_UNIT_KEY, "LMP_unit_key" }, { LMP_AU_RAND, "LMP_au_rand" }, { LMP_SRES, "LMP_sres" }, { LMP_TEMP_RAND, "LMP_temp_rand" }, { LMP_TEMP_KEY, "LMP_temp_key" }, { LMP_ENCRYPTION_MODE_REQ, "LMP_encryption_mode_req" }, { LMP_ENCRYPTION_KEY_SIZE_REQ, "LMP_encryption_key_size_req" }, { LMP_START_ENCRYPTION_REQ, "LMP_start_encryption_req" }, { LMP_STOP_ENCRYPTION_REQ, "LMP_stop_encryption_req" }, { LMP_SWITCH_REQ, "LMP_switch_req" }, { LMP_HOLD, "LMP_hold" }, { LMP_HOLD_REQ, "LMP_hold_req" }, { LMP_SNIFF_REQ, "LMP_sniff_req" }, { LMP_UNSNIFF_REQ, "LMP_unsniff_req" }, { LMP_PARK_REQ, "LMP_park_req" }, { LMP_SET_BROADCAST_SCAN_WINDOW, "LMP_set_broadcast_scan_window" }, { LMP_MODIFY_BEACON, "LMP_modify_beacon" }, { LMP_UNPARK_BD_ADDR_REQ, "LMP_unpark_BD_ADDR_req" }, { LMP_UNPARK_PM_ADDR_REQ, "LMP_unpark_PM_ADDR_req" }, { LMP_INCR_POWER_REQ, "LMP_incr_power_req" }, { LMP_DECR_POWER_REQ, "LMP_decr_power_req" }, { LMP_MAX_POWER, "LMP_max_power" }, { LMP_MIN_POWER, "LMP_min_power" }, { LMP_AUTO_RATE, "LMP_auto_rate" }, { LMP_PREFERRED_RATE, "LMP_preferred_rate" }, { LMP_VERSION_REQ, "LMP_version_req" }, { LMP_VERSION_RES, "LMP_version_res" }, { LMP_FEATURES_REQ, "LMP_features_req" }, { LMP_FEATURES_RES, "LMP_features_res" }, { LMP_QUALITY_OF_SERVICE, "LMP_quality_of_service" }, { LMP_QUALITY_OF_SERVICE_REQ, "LMP_quality_of_service_req" }, { LMP_SCO_LINK_REQ, "LMP_SCO_link_req" }, { LMP_REMOVE_SCO_LINK_REQ, "LMP_remove_SCO_link_req" }, { LMP_MAX_SLOT, "LMP_max_slot" }, { LMP_MAX_SLOT_REQ, "LMP_max_slot_req" }, { LMP_TIMING_ACCURACY_REQ, "LMP_timing_accuracy_req" }, { LMP_TIMING_ACCURACY_RES, "LMP_timing_accuracy_res" }, { LMP_SETUP_COMPLETE, "LMP_setup_complete" }, { LMP_USE_SEMI_PERMANENT_KEY, "LMP_use_semi_permanent_key" }, { LMP_HOST_CONNECTION_REQ, "LMP_host_connection_req" }, { LMP_SLOT_OFFSET, "LMP_slot_offset" }, { LMP_PAGE_MODE_REQ, "LMP_page_mode_req" }, { LMP_PAGE_SCAN_MODE_REQ, "LMP_page_scan_mode_req" }, { LMP_SUPERVISION_TIMEOUT, "LMP_supervision_timeout" }, { LMP_TEST_ACTIVATE, "LMP_test_activate" }, { LMP_TEST_CONTROL, "LMP_test_control" }, { LMP_ENCRYPTION_KEY_SIZE_MASK_REQ, "LMP_encryption_key_size_mask_req" }, { LMP_ENCRYPTION_KEY_SIZE_MASK_RES, "LMP_encryption_key_size_mask_res" }, { LMP_SET_AFH, "LMP_set_AFH" }, { LMP_ENCAPSULATED_HEADER, "LMP_encapsulated_header" }, { LMP_ENCAPSULATED_PAYLOAD, "LMP_encapsulated_payload" }, { LMP_SIMPLE_PAIRING_CONFIRM, "LMP_Simple_Pairing_Confirm" }, { LMP_SIMPLE_PAIRING_NUMBER, "LMP_Simple_Pairing_Number" }, { LMP_DHKEY_CHECK, "LMP_DHkey_Check" }, { LMP_ESCAPE_1, "Escape 1" }, { LMP_ESCAPE_2, "Escape 2" }, { LMP_ESCAPE_3, "Escape 3" }, { LMP_ESCAPE_4, "Escape 4" }, { 0, NULL } }; /* extended LMP opcodes */ static const value_string ext_opcode[] = { { LMP_ACCEPTED_EXT, "LMP_accepted_ext" }, { LMP_NOT_ACCEPTED_EXT, "LMP_not_accepted_ext" }, { LMP_FEATURES_REQ_EXT, "LMP_features_req_ext" }, { LMP_FEATURES_RES_EXT, "LMP_features_res_ext" }, { LMP_PACKET_TYPE_TABLE_REQ, "LMP_packet_type_table_req" }, { LMP_ESCO_LINK_REQ, "LMP_eSCO_link_req" }, { LMP_REMOVE_ESCO_LINK_REQ, "LMP_remove_eSCO_link_req" }, { LMP_CHANNEL_CLASSIFICATION_REQ, "LMP_channel_classification_req" }, { LMP_CHANNEL_CLASSIFICATION, "LMP_channel_classification" }, { LMP_SNIFF_SUBRATING_REQ, "LMP_sniff_subrating_req" }, { LMP_SNIFF_SUBRATING_RES, "LMP_sniff_subrating_res" }, { LMP_PAUSE_ENCRYPTION_REQ, "LMP_pause_encryption_req" }, { LMP_RESUME_ENCRYPTION_REQ, "LMP_resume_encryption_req" }, { LMP_IO_CAPABILITY_REQ, "LMP_IO_Capability_req" }, { LMP_IO_CAPABILITY_RES, "LMP_IO_Capability_res" }, { LMP_NUMERIC_COMPARISON_FAILED, "LMP_numeric_comparison_failed" }, { LMP_PASSKEY_FAILED, "LMP_passkey_failed" }, { LMP_OOB_FAILED, "LMP_oob_failed" }, { LMP_KEYPRESS_NOTIFICATION, "LMP_keypress_notification" }, { LMP_POWER_CONTROL_REQ, "LMP_power_control_req" }, { LMP_POWER_CONTROL_RES, "LMP_power_control_res" }, { 0, NULL } }; /* LMP error codes */ static const value_string error_code[] = { { 0x00, "Success" }, { 0x01, "Unknown HCI Command" }, { 0x02, "Unknown Connection Identifier" }, { 0x03, "Hardware Failure" }, { 0x04, "Page Timeout" }, { 0x05, "Authentication Failure" }, { 0x06, "PIN or Key Missing" }, { 0x07, "Memory Capacity Exceeded" }, { 0x08, "Connection Timeout" }, { 0x09, "Connection Limit Exceeded" }, { 0x0A, "Synchronous Connection Limit To A Device Exceeded" }, { 0x0B, "ACL Connection Already Exists" }, { 0x0C, "Command Disallowed" }, { 0x0D, "Connection Rejected due to Limited Resources" }, { 0x0E, "Connection Rejected Due To Security Reasons" }, { 0x0F, "Connection Rejected due to Unacceptable BD_ADDR" }, { 0x10, "Connection Accept Timeout Exceeded" }, { 0x11, "Unsupported Feature or Parameter Value" }, { 0x12, "Invalid HCI Command Parameters" }, { 0x13, "Remote User Terminated Connection" }, { 0x14, "Remote Device Terminated Connection due to Low Resources" }, { 0x15, "Remote Device Terminated Connection due to Power Off" }, { 0x16, "Connection Terminated By Local Host" }, { 0x17, "Repeated Attempts" }, { 0x18, "Pairing Not Allowed" }, { 0x19, "Unknown LMP PDU" }, { 0x1A, "Unsupported Remote Feature / Unsupported LMP 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, "Link Key Can Not be Changed" }, { 0x27, "Requested QoS Not Supported" }, { 0x28, "Instant Passed" }, { 0x29, "Pairing With Unit Key Not Supported" }, { 0x2A, "Different Transaction Collision" }, { 0x2B, "Reserved" }, { 0x2C, "QoS Unacceptable Parameter" }, { 0x2D, "QoS Rejected" }, { 0x2E, "Channel Classification Not Supported" }, { 0x2F, "Insufficient Security" }, { 0x30, "Parameter Out Of Mandatory Range" }, { 0x31, "Reserved" }, { 0x32, "Role Switch Pending" }, { 0x33, "Reserved" }, { 0x34, "Reserved Slot Violation" }, { 0x35, "Role Switch Failed" }, { 0x36, "Extended Inquiry Response Too Large" }, { 0x37, "Secure Simple Pairing Not Supported By Host." }, { 0x38, "Host Busy - Pairing" }, { 0x39, "Connection Rejected due to No Suitable Channel Found" }, { 0, NULL } }; static const value_string encryption_mode[] = { { 0, "no encryption" }, { 1, "encryption" }, { 2, "encryption" }, /* 3 - 255 reserved */ { 0, NULL } }; static const value_string access_scheme[] = { { 0, "polling technique" }, /* 1 - 15 reserved */ { 0, NULL } }; static const value_string packet_size[] = { { 0, "no packet-size preference available" }, { 1, "use 1-slot packets" }, { 2, "use 3-slot packets" }, { 3, "use 5-slot packets" }, { 0, NULL } }; static const value_string edr_type[] = { { 0, "use DM1 packets" }, { 1, "use 2 Mbps packets" }, { 2, "use 3 Mbps packets" }, /* 3 reserved */ { 0, NULL } }; static const value_string versnr[] = { { 0, "Bluetooth Core Specification 1.0b" }, { 1, "Bluetooth Core Specification 1.1" }, { 2, "Bluetooth Core Specification 1.2" }, { 3, "Bluetooth Core Specification 2.0 + EDR" }, { 4, "Bluetooth Core Specification 2.1 + EDR" }, { 5, "Bluetooth Core Specification 3.0 + HS" }, /* 6 - 255 reserved */ { 0, NULL } }; static const value_string compid[] = { { 0, "Ericsson Technology Licensing" }, { 1, "Nokia Mobile Phones" }, { 2, "Intel Corp." }, { 3, "IBM Corp." }, { 4, "Toshiba Corp." }, { 5, "3Com" }, { 6, "Microsoft" }, { 7, "Lucent" }, { 8, "Motorola" }, { 9, "Infineon Technologies AG" }, { 10, "Cambridge Silicon Radio" }, { 11, "Silicon Wave" }, { 12, "Digianswer A/S" }, { 13, "Texas Instruments Inc." }, { 14, "Parthus Technologies Inc." }, { 15, "Broadcom Corporation" }, { 16, "Mitel Semiconductor" }, { 17, "Widcomm, Inc." }, { 18, "Zeevo, Inc." }, { 19, "Atmel Corporation" }, { 20, "Mitsubishi Electric Corporation" }, { 21, "RTX Telecom A/S" }, { 22, "KC Technology Inc." }, { 23, "Newlogic" }, { 24, "Transilica, Inc." }, { 25, "Rohde & Schwarz GmbH & Co. KG" }, { 26, "TTPCom Limited" }, { 27, "Signia Technologies, Inc." }, { 28, "Conexant Systems Inc." }, { 29, "Qualcomm" }, { 30, "Inventel" }, { 31, "AVM Berlin" }, { 32, "BandSpeed, Inc." }, { 33, "Mansella Ltd" }, { 34, "NEC Corporation" }, { 35, "WavePlus Technology Co., Ltd." }, { 36, "Alcatel" }, { 37, "Philips Semiconductors" }, { 38, "C Technologies" }, { 39, "Open Interface" }, { 40, "R F Micro Devices" }, { 41, "Hitachi Ltd" }, { 42, "Symbol Technologies, Inc." }, { 43, "Tenovis" }, { 44, "Macronix International Co. Ltd." }, { 45, "GCT Semiconductor" }, { 46, "Norwood Systems" }, { 47, "MewTel Technology Inc." }, { 48, "ST Microelectronics" }, { 49, "Synopsys" }, { 50, "Red-M (Communications) Ltd" }, { 51, "Commil Ltd" }, { 52, "Computer Access Technology Corporation (CATC)" }, { 53, "Eclipse (HQ Espana) S.L." }, { 54, "Renesas Technology Corp." }, { 55, "Mobilian Corporation" }, { 56, "Terax" }, { 57, "Integrated System Solution Corp." }, { 58, "Matsushita Electric Industrial Co., Ltd." }, { 59, "Gennum Corporation" }, { 60, "Research In Motion" }, { 61, "IPextreme, Inc." }, { 62, "Systems and Chips, Inc" }, { 63, "Bluetooth SIG, Inc" }, { 64, "Seiko Epson Corporation" }, { 65, "Integrated Silicon Solution Taiwan, Inc." }, { 66, "CONWISE Technology Corporation Ltd" }, { 67, "PARROT SA" }, { 68, "Socket Mobile" }, { 69, "Atheros Communications, Inc." }, { 70, "MediaTek, Inc." }, { 71, "Bluegiga (tentative)" }, { 72, "Marvell Technology Group Ltd." }, { 73, "3DSP Corporation" }, { 74, "Accel Semiconductor Ltd." }, { 75, "Continental Automotive Systems" }, { 76, "Apple, Inc." }, { 77, "Staccato Communications, Inc." }, { 78, "Avago Technologies" }, { 79, "APT Ltd." }, { 80, "SiRF Technology, Inc." }, { 81, "Tzero Technologies, Inc." }, { 82, "J&M Corporation" }, { 83, "Free2move AB" }, /* 84 - 65534 reserved */ { 65535, "test" }, { 0, NULL } }; static const value_string sco_packet[] = { { 0, "HV1" }, { 1, "HV2" }, { 2, "HV3" }, /* 3 - 255 reserved */ { 0, NULL } }; static const value_string air_mode[] = { { 0, "mu-law log" }, { 1, "A-law log" }, { 2, "CVSD" }, { 3, "transparent data" }, /* 4 - 255 reserved */ { 0, NULL } }; static const value_string paging_scheme[] = { { 0, "mandatory scheme" }, /* 1 - 255 reserved */ { 0, NULL } }; static const value_string paging_scheme_settings[] = { /* for mandatory scheme: */ { 0, "R0" }, { 1, "R1" }, { 2, "R2" }, /* 3 - 255 reserved */ { 0, NULL } }; static const value_string afh_mode[] = { { 0, "AFH disabled" }, { 1, "AFH enabled" }, /* 2 - 255 reserved */ { 0, NULL } }; static const value_string features_page[] = { { 0, "standard features" }, /* 1 - 255 other feature pages */ { 0, NULL } }; static const value_string packet_type_table[] = { { 0, "1 Mbps only" }, { 1, "2/3 Mbps" }, /* 2 - 255 reserved */ { 0, NULL } }; static const value_string negotiation_state[] = { { 0, "Initiate negotiation" }, { 1, "The latest received set of negotiable parameters were possible but these parameters are preferred." }, { 2, "The latest received set of negotiable parameters would cause a reserved slot violation." }, { 3, "The latest received set of negotiable parameters would cause a latency violation." }, { 4, "The latest received set of negotiable parameters are not supported." }, /* 5 - 255 reserved */ { 0, NULL } }; static const value_string afh_reporting_mode[] = { { 0, "AFH reporting disabled" }, { 1, "AFH reporting enabled" }, /* 2 - 255 reserved */ { 0, NULL } }; static const value_string io_capabilities[] = { { 0, "Display Only" }, { 1, "Display Yes/No" }, { 2, "Keyboard Only" }, { 3, "No Input/No Output" }, /* 4 - 255 reserved */ { 0, NULL } }; static const value_string oob_auth_data[] = { { 0, "No OOB Authentication Data received" }, { 1, "OOB Authentication Data received" }, /* 2 - 255 reserved */ { 0, NULL } }; static const value_string auth_requirements[] = { { 0x00, "MITM Protection Not Required - No Bonding" }, { 0x01, "MITM Protection Required - No Bonding" }, { 0x02, "MITM Protection Not Required - Dedicated Bonding" }, { 0x03, "MITM Protection Required - Dedicated Bonding" }, { 0x04, "MITM Protection Not Required - General Bonding" }, { 0x05, "MITM Protection Required - General Bonding" }, /* 0x06 - 0xff reserved */ { 0, NULL } }; static const value_string power_adjust_req[] = { { 0, "decrement power one step" }, { 1, "increment power one step" }, { 2, "increase to maximum power" }, /* 3 - 255 reserved */ { 0, NULL } }; static const value_string power_adjust_res[] = { { 0, "not supported" }, { 1, "changed one step (not min or max)" }, { 2, "max power" }, { 3, "min power" }, /* 4 - 255 reserved */ { 0, NULL } }; static const value_string test_scenario[] = { { 0, "Pause Test Mode" }, { 1, "Transmitter test - 0 pattern" }, { 2, "Transmitter test - 1 pattern" }, { 3, "Transmitter test - 1010 pattern" }, { 4, "Pseudorandom bit sequence" }, { 5, "Closed Loop Back - ACL packets" }, { 6, "Closed Loop Back - Synchronous packets" }, { 7, "ACL Packets without whitening" }, { 8, "Synchronous Packets without whitening" }, { 9, "Transmitter test - 1111 0000 pattern" }, /* 10 - 254 reserved */ { 255, "Exit Test Mode" }, { 0, NULL } }; static const value_string hopping_mode[] = { { 0, "RX/TX on single frequency" }, { 1, "Normal hopping" }, /* 2 - 255 reserved */ { 0, NULL } }; static const value_string power_control_mode[] = { { 0, "fixed TX output power" }, { 1, "adaptive power control" }, /* 2 - 255 reserved */ { 0, NULL } }; static const value_string esco_packet_type[] = { { 0x00, "NULL/POLL" }, { 0x07, "EV3" }, { 0x0C, "EV4" }, { 0x0D, "EV5" }, { 0x26, "2-EV3" }, { 0x2C, "2-EV5" }, { 0x37, "3-EV3" }, { 0x3D, "3-EV5" }, /* other values reserved */ { 0, NULL } }; static const value_string notification_value[] = { { 0, "passkey entry started" }, { 1, "passkey digit entered" }, { 2, "passkey digit erased" }, { 3, "passkey cleared" }, { 4, "passkey entry completed" }, /* 5 - 255 reserved */ { 0, NULL } }; /* initialize the subtree pointers */ static gint ett_lmp = -1; static gint ett_lmp_pwradjres = -1; static gint ett_lmp_rate = -1; static gint ett_lmp_timectrl = -1; /* LMP PDUs with short opcodes */ void dissect_name_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_nameoffset, tvb, offset, 1, ENC_NA); } void dissect_name_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_nameoffset, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(tree, hf_lmp_namelen, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(tree, hf_lmp_namefrag, tvb, offset, 14, ENC_ASCII|ENC_NA); } void dissect_accepted(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_opinre, tvb, offset, 1, ENC_NA); } void dissect_not_accepted(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_opinre, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(tree, hf_lmp_err, tvb, offset, 1, ENC_NA); } void dissect_clkoffset_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_clkoffset_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_clkoffset, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_detach(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_err, tvb, offset, 1, ENC_NA); } void dissect_in_rand(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_rand, tvb, offset, 16, ENC_NA); } void dissect_comb_key(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_rand, tvb, offset, 16, ENC_NA); } void dissect_unit_key(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_key, tvb, offset, 16, ENC_NA); } void dissect_au_rand(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_rand, tvb, offset, 16, ENC_NA); } void dissect_sres(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 5); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 4); proto_tree_add_item(tree, hf_lmp_authres, tvb, offset, 4, ENC_NA); } void dissect_temp_rand(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_rand, tvb, offset, 16, ENC_NA); } void dissect_temp_key(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_key, tvb, offset, 16, ENC_NA); } void dissect_encryption_mode_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_cryptmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_encryption_key_size_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_keysz, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_start_encryption_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_rand, tvb, offset, 16, ENC_NA); } void dissect_stop_encryption_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_switch_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 5); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 4); proto_tree_add_item(tree, hf_lmp_swinst, tvb, offset, 4, ENC_LITTLE_ENDIAN); } void dissect_hold(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 7); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 6); proto_tree_add_item(tree, hf_lmp_htime, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_hinst, tvb, offset, 4, ENC_LITTLE_ENDIAN); } void dissect_hold_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 7); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 6); proto_tree_add_item(tree, hf_lmp_htime, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_hinst, tvb, offset, 4, ENC_LITTLE_ENDIAN); } void dissect_sniff_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 10); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 9); proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_dsniff, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_tsniff, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_sniffatt, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_sniffto, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_unsniff_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_park_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_db, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_tb, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_nb, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_deltab, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_araddr, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_nbsleep, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_dbsleep, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_daccess, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_taccess, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_naccslots, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_npoll, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_maccess, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_lmp_accscheme, tvb, offset, 1, ENC_NA); } void dissect_set_broadcast_scan_window(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { int db_present; DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); /* bit0 of timing control flags indicates presence of db */ db_present = tvb_get_guint8(tvb, offset) & 0x01; offset += 1; if (db_present) { DISSECTOR_ASSERT(len == 6); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 4); proto_tree_add_item(tree, hf_lmp_db, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } else { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); } proto_tree_add_item(tree, hf_lmp_bsw, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_modify_beacon(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { int db_present; DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); /* bit0 of timing control flags indicates presence of db */ db_present = tvb_get_guint8(tvb, offset) & 0x01; offset += 1; if (db_present) { DISSECTOR_ASSERT(len == 13); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 11); proto_tree_add_item(tree, hf_lmp_db, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } else { DISSECTOR_ASSERT(len == 11); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 9); } proto_tree_add_item(tree, hf_lmp_tb, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_nb, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_deltab, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_daccess, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_taccess, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_naccslots, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_npoll, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_maccess, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_lmp_accscheme, tvb, offset, 1, ENC_NA); } void dissect_unpark_bd_addr_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { int db_present; proto_item *item; DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); /* bit0 of timing control flags indicates presence of db */ db_present = tvb_get_guint8(tvb, offset) & 0x01; offset += 1; if (db_present) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 15); proto_tree_add_item(tree, hf_lmp_db, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } else { DISSECTOR_ASSERT(len == 15); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 13); } proto_tree_add_item(tree, hf_lmp_ltaddr1, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_lmp_ltaddr2, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_bdaddr1, tvb, offset, 6, ENC_LITTLE_ENDIAN); offset += 6; proto_tree_add_item(tree, hf_lmp_bdaddr2, tvb, offset, 6, ENC_LITTLE_ENDIAN); offset += 6; } void dissect_unpark_pm_addr_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { int db_present; DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); /* bit0 of timing control flags indicates presence of db */ db_present = tvb_get_guint8(tvb, offset) & 0x01; offset += 1; if (db_present) { DISSECTOR_ASSERT(len == 15); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 13); proto_tree_add_item(tree, hf_lmp_db, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } else { DISSECTOR_ASSERT(len == 13); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 11); } proto_tree_add_item(tree, hf_lmp_ltaddr1, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_lmp_ltaddr2, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr1, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr2, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_ltaddr3, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_lmp_ltaddr4, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr3, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr4, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_ltaddr5, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_lmp_ltaddr6, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr5, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr6, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_ltaddr7, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pmaddr7, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_incr_power_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); /* skipping one byte "for future use" */ } void dissect_decr_power_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); /* skipping one byte "for future use" */ } void dissect_max_power(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_min_power(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_auto_rate(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_preferred_rate(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { proto_item *rate_item; proto_tree *rate_tree; DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); rate_item = proto_tree_add_item(tree, hf_lmp_rate, tvb, offset, 1, ENC_LITTLE_ENDIAN); rate_tree = proto_item_add_subtree(rate_item, ett_lmp_rate); proto_tree_add_item(rate_tree, hf_lmp_rate_fec, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(rate_tree, hf_lmp_rate_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(rate_tree, hf_lmp_rate_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(rate_tree, hf_lmp_rate_edrsize, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_version_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 6); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 5); proto_tree_add_item(tree, hf_lmp_versnr, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_compid, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_subversnr, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_version_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 6); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 5); proto_tree_add_item(tree, hf_lmp_versnr, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_compid, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_subversnr, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_features_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 9); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 8); proto_tree_add_item(tree, hf_lmp_features, tvb, offset, 8, ENC_NA); } void dissect_features_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 9); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 8); proto_tree_add_item(tree, hf_lmp_features, tvb, offset, 8, ENC_NA); } void dissect_quality_of_service(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3); proto_tree_add_item(tree, hf_lmp_pollintvl, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_nbc, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_quality_of_service_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3); proto_tree_add_item(tree, hf_lmp_pollintvl, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_nbc, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_sco_link_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 7); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 6); proto_tree_add_item(tree, hf_lmp_scohdl, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_dsco, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_tsco, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_scopkt, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_airmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_remove_sco_link_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_scohdl, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_err, tvb, offset, 1, ENC_NA); } void dissect_max_slot(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_maxslots, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_max_slot_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_maxslots, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_timing_accuracy_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_timing_accuracy_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_drift, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_jitter, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_setup_complete(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_use_semi_permanent_key(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_host_connection_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_slot_offset(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 9); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 8); proto_tree_add_item(tree, hf_lmp_slotoffset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_bdaddr, tvb, offset, 6, ENC_LITTLE_ENDIAN); } void dissect_page_mode_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_pagesch, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pssettings, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_page_scan_mode_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_pagesch, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pssettings, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_supervision_timeout(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_suptimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_test_activate(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_test_control(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 10); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 9); /* FIXME these fields should all be XORed with 0x55. . . */ proto_tree_add_item(tree, hf_lmp_testscen, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_hopmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_txfreq, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_rxfreq, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pcmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pollper, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_pkttype, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_testlen, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_encryption_key_size_mask_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 1); } void dissect_encryption_key_size_mask_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_ksmask, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_set_afh(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 16); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 15); proto_tree_add_item(tree, hf_lmp_afhinst, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_lmp_afhmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_afhchmap, tvb, offset, 10, ENC_NA); } void dissect_encapsulated_header(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3); proto_tree_add_item(tree, hf_lmp_encmaj, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_encmin, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_enclen, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_encapsulated_payload(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_encdata, tvb, offset, 16, ENC_NA); } void dissect_simple_pairing_confirm(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_commit, tvb, offset, 16, ENC_NA); } void dissect_simple_pairing_number(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_nonce, tvb, offset, 16, ENC_NA); } void dissect_dhkey_check(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 17); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 16); proto_tree_add_item(tree, hf_lmp_confirm, tvb, offset, 16, ENC_NA); } /* LMP PDUs with extended opcodes */ void dissect_accepted_ext(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_opinre, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_eopinre, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_not_accepted_ext(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_opinre, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_eopinre, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_err, tvb, offset, 1, ENC_NA); } void dissect_features_req_ext(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 12); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 10); proto_tree_add_item(tree, hf_lmp_fpage, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_maxsp, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* * extended features might need to be different from hf_lmp_features * if hf_lmp_features is broken out */ proto_tree_add_item(tree, hf_lmp_features, tvb, offset, 8, ENC_NA); } void dissect_features_res_ext(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 12); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 10); proto_tree_add_item(tree, hf_lmp_fpage, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_maxsp, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* * extended features might need to be different from hf_lmp_features * if hf_lmp_features is broken out */ proto_tree_add_item(tree, hf_lmp_features, tvb, offset, 8, ENC_NA); } void dissect_packet_type_table_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_pkttypetbl, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_esco_link_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 16); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 14); proto_tree_add_item(tree, hf_lmp_escohdl, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_escoltaddr, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_timectrl, ett_lmp_timectrl, timectrl_fields, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_desco, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_tesco, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_wesco, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_escotypems, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(tree, hf_lmp_escotypesm, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(tree, hf_lmp_escolenms, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_escolensm, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_airmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_negstate, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_remove_esco_link_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 4); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 2); proto_tree_add_item(tree, hf_lmp_escohdl, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_err, tvb, offset, 1, ENC_NA); } void dissect_channel_classification_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 7); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 5); proto_tree_add_item(tree, hf_lmp_afhrptmode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_afhminintvl, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_afhmaxintvl, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_channel_classification(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 12); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 10); proto_tree_add_item(tree, hf_lmp_afhclass, tvb, offset, 10, ENC_NA); } void dissect_sniff_subrating_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 9); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 7); proto_tree_add_item(tree, hf_lmp_maxss, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_minsmt, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_sniffsi, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_sniff_subrating_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 9); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 7); proto_tree_add_item(tree, hf_lmp_maxss, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_minsmt, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_lmp_sniffsi, tvb, offset, 2, ENC_LITTLE_ENDIAN); } void dissect_pause_encryption_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); } void dissect_resume_encryption_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); } void dissect_io_capability_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 5); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3); proto_tree_add_item(tree, hf_lmp_iocaps, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_oobauthdata, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_authreqs, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_io_capability_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 5); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3); proto_tree_add_item(tree, hf_lmp_iocaps, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_oobauthdata, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_lmp_authreqs, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_numeric_comparison_failed(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); } void dissect_passkey_failed(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); } void dissect_oob_failed(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 2); } void dissect_keypress_notification(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_nottype, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_power_control_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); proto_tree_add_item(tree, hf_lmp_pwradjreq, tvb, offset, 1, ENC_LITTLE_ENDIAN); } void dissect_power_control_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) { proto_item *pa_item; proto_tree *pa_tree; DISSECTOR_ASSERT(len == 3); DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1); pa_item = proto_tree_add_item(tree, hf_lmp_pwradjres, tvb, offset, 1, ENC_LITTLE_ENDIAN); pa_tree = proto_item_add_subtree(pa_item, ett_lmp_pwradjres); proto_tree_add_item(pa_tree, hf_lmp_pwradj_gfsk, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(pa_tree, hf_lmp_pwradj_dqpsk, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(pa_tree, hf_lmp_pwradj_8dpsk, tvb, offset, 1, ENC_LITTLE_ENDIAN); } /* Link Manager Protocol */ static void dissect_btlmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *lmp_item; proto_tree *lmp_tree; int offset; int len; int op; /* opcode */ int eop; /* extended opcode */ offset = 0; len = tvb_length(tvb); DISSECTOR_ASSERT(len >= 1); /* make entries in protocol column and info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LMP"); /* clear the info column first just in case of type fetching failure. */ col_clear(pinfo->cinfo, COL_INFO); op = tvb_get_guint8(tvb, offset) >> 1; if (op == LMP_ESCAPE_4) { DISSECTOR_ASSERT(len >= 2); eop = tvb_get_guint8(tvb, offset + 1); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(eop, opcode, "Unknown Extended Opcode (%d)")); } else { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(op, opcode, "Unknown Opcode (%d)")); } /* see if we are being asked for details */ if (!tree) return; lmp_item = proto_tree_add_item(tree, proto_btlmp, tvb, offset, -1, ENC_NA); lmp_tree = proto_item_add_subtree(lmp_item, ett_lmp); proto_tree_add_item(lmp_tree, hf_lmp_tid, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(lmp_tree, hf_lmp_op, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; switch (op) { case LMP_NAME_REQ: dissect_name_req(lmp_tree, tvb, offset, len); break; case LMP_NAME_RES: dissect_name_res(lmp_tree, tvb, offset, len); break; case LMP_ACCEPTED: dissect_accepted(lmp_tree, tvb, offset, len); break; case LMP_NOT_ACCEPTED: dissect_not_accepted(lmp_tree, tvb, offset, len); break; case LMP_CLKOFFSET_REQ: dissect_clkoffset_req(lmp_tree, tvb, offset, len); break; case LMP_CLKOFFSET_RES: dissect_clkoffset_res(lmp_tree, tvb, offset, len); break; case LMP_DETACH: dissect_detach(lmp_tree, tvb, offset, len); break; case LMP_IN_RAND: dissect_in_rand(lmp_tree, tvb, offset, len); break; case LMP_COMB_KEY: dissect_comb_key(lmp_tree, tvb, offset, len); break; case LMP_UNIT_KEY: dissect_unit_key(lmp_tree, tvb, offset, len); break; case LMP_AU_RAND: dissect_au_rand(lmp_tree, tvb, offset, len); break; case LMP_SRES: dissect_sres(lmp_tree, tvb, offset, len); break; case LMP_TEMP_RAND: dissect_temp_rand(lmp_tree, tvb, offset, len); break; case LMP_TEMP_KEY: dissect_temp_key(lmp_tree, tvb, offset, len); break; case LMP_ENCRYPTION_MODE_REQ: dissect_encryption_mode_req(lmp_tree, tvb, offset, len); break; case LMP_ENCRYPTION_KEY_SIZE_REQ: dissect_encryption_key_size_req(lmp_tree, tvb, offset, len); break; case LMP_START_ENCRYPTION_REQ: dissect_start_encryption_req(lmp_tree, tvb, offset, len); break; case LMP_STOP_ENCRYPTION_REQ: dissect_stop_encryption_req(lmp_tree, tvb, offset, len); break; case LMP_SWITCH_REQ: dissect_switch_req(lmp_tree, tvb, offset, len); break; case LMP_HOLD: dissect_hold(lmp_tree, tvb, offset, len); break; case LMP_HOLD_REQ: dissect_hold_req(lmp_tree, tvb, offset, len); break; case LMP_SNIFF_REQ: dissect_sniff_req(lmp_tree, tvb, offset, len); break; case LMP_UNSNIFF_REQ: dissect_unsniff_req(lmp_tree, tvb, offset, len); break; case LMP_PARK_REQ: dissect_park_req(lmp_tree, tvb, offset, len); break; case LMP_SET_BROADCAST_SCAN_WINDOW: dissect_set_broadcast_scan_window(lmp_tree, tvb, offset, len); break; case LMP_MODIFY_BEACON: dissect_modify_beacon(lmp_tree, tvb, offset, len); break; case LMP_UNPARK_BD_ADDR_REQ: dissect_unpark_bd_addr_req(lmp_tree, tvb, offset, len); break; case LMP_UNPARK_PM_ADDR_REQ: dissect_unpark_pm_addr_req(lmp_tree, tvb, offset, len); break; case LMP_INCR_POWER_REQ: dissect_incr_power_req(lmp_tree, tvb, offset, len); break; case LMP_DECR_POWER_REQ: dissect_decr_power_req(lmp_tree, tvb, offset, len); break; case LMP_MAX_POWER: dissect_max_power(lmp_tree, tvb, offset, len); break; case LMP_MIN_POWER: dissect_min_power(lmp_tree, tvb, offset, len); break; case LMP_AUTO_RATE: dissect_auto_rate(lmp_tree, tvb, offset, len); break; case LMP_PREFERRED_RATE: dissect_preferred_rate(lmp_tree, tvb, offset, len); break; case LMP_VERSION_REQ: dissect_version_req(lmp_tree, tvb, offset, len); break; case LMP_VERSION_RES: dissect_version_res(lmp_tree, tvb, offset, len); break; case LMP_FEATURES_REQ: dissect_features_req(lmp_tree, tvb, offset, len); break; case LMP_FEATURES_RES: dissect_features_res(lmp_tree, tvb, offset, len); break; case LMP_QUALITY_OF_SERVICE: dissect_quality_of_service(lmp_tree, tvb, offset, len); break; case LMP_QUALITY_OF_SERVICE_REQ: dissect_quality_of_service_req(lmp_tree, tvb, offset, len); break; case LMP_SCO_LINK_REQ: dissect_sco_link_req(lmp_tree, tvb, offset, len); break; case LMP_REMOVE_SCO_LINK_REQ: dissect_remove_sco_link_req(lmp_tree, tvb, offset, len); break; case LMP_MAX_SLOT: dissect_max_slot(lmp_tree, tvb, offset, len); break; case LMP_MAX_SLOT_REQ: dissect_max_slot_req(lmp_tree, tvb, offset, len); break; case LMP_TIMING_ACCURACY_REQ: dissect_timing_accuracy_req(lmp_tree, tvb, offset, len); break; case LMP_TIMING_ACCURACY_RES: dissect_timing_accuracy_res(lmp_tree, tvb, offset, len); break; case LMP_SETUP_COMPLETE: dissect_setup_complete(lmp_tree, tvb, offset, len); break; case LMP_USE_SEMI_PERMANENT_KEY: dissect_use_semi_permanent_key(lmp_tree, tvb, offset, len); break; case LMP_HOST_CONNECTION_REQ: dissect_host_connection_req(lmp_tree, tvb, offset, len); break; case LMP_SLOT_OFFSET: dissect_slot_offset(lmp_tree, tvb, offset, len); break; case LMP_PAGE_MODE_REQ: dissect_page_mode_req(lmp_tree, tvb, offset, len); break; case LMP_PAGE_SCAN_MODE_REQ: dissect_page_scan_mode_req(lmp_tree, tvb, offset, len); break; case LMP_SUPERVISION_TIMEOUT: dissect_supervision_timeout(lmp_tree, tvb, offset, len); break; case LMP_TEST_ACTIVATE: dissect_test_activate(lmp_tree, tvb, offset, len); break; case LMP_TEST_CONTROL: dissect_test_control(lmp_tree, tvb, offset, len); break; case LMP_ENCRYPTION_KEY_SIZE_MASK_REQ: dissect_encryption_key_size_mask_req(lmp_tree, tvb, offset, len); break; case LMP_ENCRYPTION_KEY_SIZE_MASK_RES: dissect_encryption_key_size_mask_res(lmp_tree, tvb, offset, len); break; case LMP_SET_AFH: dissect_set_afh(lmp_tree, tvb, offset, len); break; case LMP_ENCAPSULATED_HEADER: dissect_encapsulated_header(lmp_tree, tvb, offset, len); break; case LMP_ENCAPSULATED_PAYLOAD: dissect_encapsulated_payload(lmp_tree, tvb, offset, len); break; case LMP_SIMPLE_PAIRING_CONFIRM: dissect_simple_pairing_confirm(lmp_tree, tvb, offset, len); break; case LMP_SIMPLE_PAIRING_NUMBER: dissect_simple_pairing_number(lmp_tree, tvb, offset, len); break; case LMP_DHKEY_CHECK: dissect_dhkey_check(lmp_tree, tvb, offset, len); break; case LMP_ESCAPE_1: break; case LMP_ESCAPE_2: break; case LMP_ESCAPE_3: break; case LMP_ESCAPE_4: /* extended opcode */ DISSECTOR_ASSERT(len >= 2); proto_tree_add_item(lmp_tree, hf_lmp_eop, tvb, offset, 1, ENC_NA); offset += 1; switch (eop) { case LMP_ACCEPTED_EXT: dissect_accepted_ext(lmp_tree, tvb, offset, len); break; case LMP_NOT_ACCEPTED_EXT: dissect_not_accepted_ext(lmp_tree, tvb, offset, len); break; case LMP_FEATURES_REQ_EXT: dissect_features_req_ext(lmp_tree, tvb, offset, len); break; case LMP_FEATURES_RES_EXT: dissect_features_res_ext(lmp_tree, tvb, offset, len); break; case LMP_PACKET_TYPE_TABLE_REQ: dissect_packet_type_table_req(lmp_tree, tvb, offset, len); break; case LMP_ESCO_LINK_REQ: dissect_esco_link_req(lmp_tree, tvb, offset, len); break; case LMP_REMOVE_ESCO_LINK_REQ: dissect_remove_esco_link_req(lmp_tree, tvb, offset, len); break; case LMP_CHANNEL_CLASSIFICATION_REQ: dissect_channel_classification_req(lmp_tree, tvb, offset, len); break; case LMP_CHANNEL_CLASSIFICATION: dissect_channel_classification(lmp_tree, tvb, offset, len); break; case LMP_SNIFF_SUBRATING_REQ: dissect_sniff_subrating_req(lmp_tree, tvb, offset, len); break; case LMP_SNIFF_SUBRATING_RES: dissect_sniff_subrating_res(lmp_tree, tvb, offset, len); break; case LMP_PAUSE_ENCRYPTION_REQ: dissect_pause_encryption_req(lmp_tree, tvb, offset, len); break; case LMP_RESUME_ENCRYPTION_REQ: dissect_resume_encryption_req(lmp_tree, tvb, offset, len); break; case LMP_IO_CAPABILITY_REQ: dissect_io_capability_req(lmp_tree, tvb, offset, len); break; case LMP_IO_CAPABILITY_RES: dissect_io_capability_res(lmp_tree, tvb, offset, len); break; case LMP_NUMERIC_COMPARISON_FAILED: dissect_numeric_comparison_failed(lmp_tree, tvb, offset, len); break; case LMP_PASSKEY_FAILED: dissect_passkey_failed(lmp_tree, tvb, offset, len); break; case LMP_OOB_FAILED: dissect_oob_failed(lmp_tree, tvb, offset, len); break; case LMP_KEYPRESS_NOTIFICATION: dissect_keypress_notification(lmp_tree, tvb, offset, len); break; case LMP_POWER_CONTROL_REQ: dissect_power_control_req(lmp_tree, tvb, offset, len); break; case LMP_POWER_CONTROL_RES: dissect_power_control_res(lmp_tree, tvb, offset, len); break; default: break; } default: break; } }; /* register the protocol with Wireshark */ void proto_register_btlmp(void) { /* list of fields */ static hf_register_info hf[] = { { &hf_lmp_accscheme, { "Access Scheme", "btlmp.accscheme", FT_UINT8, BASE_DEC, VALS(access_scheme), 0xf0, NULL, HFILL } }, { &hf_lmp_afhchmap, { "AFH Channel Map", "btlmp.afhchmap", /* could break out individual channels but long */ FT_BYTES, BASE_NONE, NULL, 0x0, "Adaptive Frequency Hopping Channel Map", HFILL } }, { &hf_lmp_afhclass, { "AFH Channel Classification", "btlmp.afhclass", /* could break out individual channels but long */ FT_BYTES, BASE_NONE, NULL, 0x0, "Adaptive Frequency Hopping Channel Classification", HFILL } }, { &hf_lmp_afhinst, { "AFH Instant", "btlmp.afhinst", FT_UINT32, BASE_HEX, NULL, 0x0, "Adaptive Frequency Hopping Instant (slot)", HFILL } }, { &hf_lmp_afhmaxintvl, { "AFH Max Interval", "btlmp.maxintvl", FT_UINT16, BASE_HEX, NULL, 0x0, "Adaptive Maximum Interval in slots", HFILL } }, { &hf_lmp_afhminintvl, { "AFH Min Interval", "btlmp.minintvl", FT_UINT16, BASE_HEX, NULL, 0x0, "Adaptive Minimum Interval in slots", HFILL } }, { &hf_lmp_afhmode, { "AFH Mode", "btlmp.afhmode", FT_UINT8, BASE_DEC, VALS(afh_mode), 0x0, "Adaptive Frequency Hopping Mode", HFILL } }, { &hf_lmp_afhrptmode, { "AFH Reporting Mode", "btlmp.afhrptmode", FT_UINT8, BASE_DEC, VALS(afh_reporting_mode), 0x0, "Adaptive Frequency Hopping Reporting Mode", HFILL } }, { &hf_lmp_airmode, { "Air Mode", "btlmp.airmode", FT_UINT8, BASE_HEX, VALS(air_mode), 0x0, NULL, HFILL } }, { &hf_lmp_araddr, { "AR_ADDR", "btlmp.araddr", FT_UINT8, BASE_HEX, NULL, 0xfe, NULL, HFILL } }, { &hf_lmp_authreqs, { "Authentication Requirements", "btlmp.authreqs", FT_UINT8, BASE_HEX, VALS(auth_requirements), 0xf0, NULL, HFILL } }, { &hf_lmp_authres, { "Authentication Response", "btlmp.authres", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_bdaddr, { "BD_ADDR", "btlmp.bdaddr", FT_UINT64, BASE_HEX, NULL, 0x0000ffffffffffff, NULL, HFILL } }, { &hf_lmp_bdaddr1, { "BD_ADDR 1", "btlmp.bdaddr", FT_UINT64, BASE_HEX, NULL, 0x0000ffffffffffff, NULL, HFILL } }, { &hf_lmp_bdaddr2, { "BD_ADDR2", "btlmp.bdaddr", FT_UINT64, BASE_HEX, NULL, 0x0000ffffffffffff, "BD_ADDR 2", HFILL } }, { &hf_lmp_bsw, { "Broadcast Scan Window", "btlmp.bsw", FT_UINT16, BASE_HEX, NULL, 0x0, "Broadcast Scan Window in slots", HFILL } }, { &hf_lmp_clkoffset, { "Clock Offset", "btlmp.clkoffset", FT_UINT16, BASE_DEC, NULL, 0x0, "Clock Offset in units of 1.25 ms", HFILL } }, { &hf_lmp_commit, { "Commitment Value", "btlmp.commit", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_confirm, { "Confirmation Value", "btlmp.confirm", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_compid, { "Company ID", "btlmp.compid", FT_UINT16, BASE_DEC, VALS(compid), 0x0, NULL, HFILL } }, { &hf_lmp_cryptmode, { "Encryption Mode", "btlmp.cryptmode", FT_UINT8, BASE_DEC, VALS(encryption_mode), 0x0, NULL, HFILL } }, { &hf_lmp_daccess, { "Daccess", "btlmp.daccess", FT_UINT8, BASE_HEX, NULL, 0x0, "Daccess in slots", HFILL } }, { &hf_lmp_db, { "Db", "btlmp.db", FT_UINT16, BASE_HEX, NULL, 0x0, "Db in slots", HFILL } }, { &hf_lmp_dbsleep, { "Dbsleep", "btlmp.dbsleep", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_deltab, { "Deltab", "btlmp.deltab", FT_UINT8, BASE_HEX, NULL, 0x0, "Deltab in slots", HFILL } }, { &hf_lmp_desco, { "Desco", "btlmp.desco", FT_UINT8, BASE_HEX, NULL, 0x0, "Desco in slots", HFILL } }, { &hf_lmp_drift, { "Drift", "btlmp.drift", FT_UINT8, BASE_DEC, NULL, 0x0, "Drift in ppm", HFILL } }, { &hf_lmp_dsco, { "Dsco", "btlmp.dsco", FT_UINT8, BASE_HEX, NULL, 0x0, "Dsco in slots", HFILL } }, { &hf_lmp_dsniff, { "Dsniff", "btlmp.dsniff", FT_UINT16, BASE_HEX, NULL, 0x0, "Dsniff in slots", HFILL } }, { &hf_lmp_encdata, { "Encapsulated Data", "btlmp.encdata", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_enclen, { "Encapsulated Length", "btlmp.enclen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_encmaj, { "Encapsulated Major Type", "btlmp.encmaj", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_encmin, { "Encapsulated Minor Type", "btlmp.encmin", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_eop, { "Extended Opcode", "btlmp.eop", FT_UINT8, BASE_DEC, VALS(ext_opcode), 0x0, NULL, HFILL } }, { &hf_lmp_eopinre, { "In Response To", "btlmp.eopinre", FT_UINT8, BASE_DEC, VALS(ext_opcode), 0x0, "Extended Opcode this is in response to", HFILL } }, { &hf_lmp_escolenms, { "Packet Length M -> S", "btlmp.escolenms", FT_UINT16, BASE_DEC, NULL, 0x0, "Packet Length in bytes Master to Slave", HFILL } }, { &hf_lmp_escolensm, { "Packet Length S -> M", "btlmp.escolensm", FT_UINT16, BASE_DEC, NULL, 0x0, "Packet Length in bytes Slave to Master", HFILL } }, { &hf_lmp_escotypems, { "eSCO Packet Type M -> S", "btlmp.escotypems", FT_UINT8, BASE_HEX, VALS(esco_packet_type), 0x0, "eSCO Packet Type Master to Slave", HFILL } }, { &hf_lmp_escotypesm, { "eSCO Packet Type S -> M", "btlmp.escotypesm", FT_UINT8, BASE_HEX, VALS(esco_packet_type), 0x0, "eSCO Packet Type Slave to Master", HFILL } }, { &hf_lmp_err, { "Error Code", "btlmp.err", FT_UINT8, BASE_HEX, VALS(error_code), 0x0, NULL, HFILL } }, { &hf_lmp_escohdl, { "eSCO Handle", "btlmp.escohdl", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_escoltaddr, { "eSCO LT_ADDR", "btlmp.escoltaddr", FT_UINT8, BASE_HEX, NULL, 0x0, "eSCO Logical Transport Address", HFILL } }, { &hf_lmp_features, { "Features", "btlmp.features", /* could break out individual features but long */ FT_BYTES, BASE_NONE, NULL, 0x0, "Feature Mask", HFILL } }, { &hf_lmp_fpage, { "Features Page", "btlmp.fpage", FT_UINT8, BASE_DEC, VALS(features_page), 0x0, NULL, HFILL } }, { &hf_lmp_htime, { "Hold Time", "btlmp.htime", FT_UINT16, BASE_HEX, NULL, 0x0, "Hold Time in slots", HFILL } }, { &hf_lmp_hinst, { "Hold Instant", "btlmp.hinst", FT_UINT32, BASE_HEX, NULL, 0x0, "Hold Instant (slot)", HFILL } }, { &hf_lmp_hopmode, { "Hopping Mode", "btlmp.hopmode", FT_UINT8, BASE_DEC, VALS(hopping_mode), 0x0, NULL, HFILL } }, { &hf_lmp_iocaps, { "IO Capabilities", "btlmp.iocaps", FT_UINT8, BASE_DEC, VALS(io_capabilities), 0x0, "Input/Output Capabilities", HFILL } }, { &hf_lmp_jitter, { "Jitter", "btlmp.jitter", FT_UINT8, BASE_DEC, NULL, 0x0, "Jitter in microseconds", HFILL } }, { &hf_lmp_key, { "Key", "btlmp.key", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_keysz, { "Key Size", "btlmp.keysz", FT_UINT8, BASE_DEC, NULL, 0x0, "Key Size in bytes", HFILL } }, { &hf_lmp_ksmask, { "Key Size Mask", "btlmp.ksmask", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_ltaddr1, { "LT_ADDR 1", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0x0f, "Logical Transport Address 1", HFILL } }, { &hf_lmp_ltaddr2, { "LT_ADDR 2", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0xf0, "Logical Transport Address 2", HFILL } }, { &hf_lmp_ltaddr3, { "LT_ADDR 3", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0x0f, "Logical Transport Address 3", HFILL } }, { &hf_lmp_ltaddr4, { "LT_ADDR 4", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0xf0, "Logical Transport Address 4", HFILL } }, { &hf_lmp_ltaddr5, { "LT_ADDR 5", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0x0f, "Logical Transport Address 5", HFILL } }, { &hf_lmp_ltaddr6, { "LT_ADDR 6", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0xf0, "Logical Transport Address 6", HFILL } }, { &hf_lmp_ltaddr7, { "LT_ADDR 7", "btlmp.ltaddr", FT_UINT8, BASE_HEX, NULL, 0x0f, "Logical Transport Address 7", HFILL } }, { &hf_lmp_maccess, { "Maccess", "btlmp.maccess", FT_UINT8, BASE_HEX, NULL, 0x0f, "Number of access windows", HFILL } }, { &hf_lmp_maxslots, { "Max Slots", "btlmp.maxslots", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_maxsp, { "Max Supported Page", "btlmp.maxsp", FT_UINT8, BASE_DEC, NULL, 0x0, "Highest extended features page with non-zero bit", HFILL } }, { &hf_lmp_maxss, { "Max Sniff Subrate", "btlmp.maxss", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_minsmt, { "Min Sniff Mode Timeout", "btlmp.minsmt", FT_UINT16, BASE_HEX, NULL, 0x0, "Min Sniff Mode Timeout in slots", HFILL } }, { &hf_lmp_naccslots, { "Nacc-slots", "btlmp.naccslots", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_namefrag, { "Name Fragment", "btlmp.namefrag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_namelen, { "Name Length", "btlmp.namelen", FT_UINT8, BASE_DEC, NULL, 0x0, "Name Length in bytes", HFILL } }, { &hf_lmp_nameoffset, { "Name Offset", "btlmp.nameoffset", FT_UINT8, BASE_DEC, NULL, 0x0, "Name Offset in bytes", HFILL } }, { &hf_lmp_nb, { "Nb", "btlmp.nb", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_nbc, { "Nbc", "btlmp.nbc", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_nbsleep, { "Nbsleep", "btlmp.nbsleep", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_negstate, { "Negotiation State", "btlmp.negstate", FT_UINT8, BASE_DEC, VALS(negotiation_state), 0x0, NULL, HFILL } }, { &hf_lmp_nonce, { "Nonce Value", "btlmp.nonce", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_nottype, { "Notification Type", "btlmp.nottype", FT_UINT8, BASE_DEC, VALS(notification_value), 0x0, NULL, HFILL } }, { &hf_lmp_npoll, { "Npoll", "btlmp.npoll", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_oobauthdata, { "OOB Authentication Data", "btlmp.oobauthdata", FT_UINT8, BASE_DEC, VALS(oob_auth_data), 0xfe, NULL, HFILL } }, { &hf_lmp_op, { "Opcode", "btlmp.op", FT_UINT8, BASE_DEC, VALS(opcode), 0xfe, NULL, HFILL } }, { &hf_lmp_opinre, { "In Response To", "btlmp.opinre", FT_UINT8, BASE_DEC, VALS(opcode), 0x7f, "Opcode this is in response to", HFILL } }, { &hf_lmp_pagesch, { "Paging Scheme", "btlmp.pagesch", FT_UINT8, BASE_DEC, VALS(paging_scheme), 0x0, NULL, HFILL } }, { &hf_lmp_pcmode, { "Power Control Mode", "btlmp.pcmode", FT_UINT8, BASE_DEC, VALS(power_control_mode), 0x0, NULL, HFILL } }, { &hf_lmp_pkttype, { "Packet Type", "btlmp.pkttype", /* FIXME break out further */ FT_UINT8, BASE_HEX, NULL, 0x0, "Packet Type", HFILL } }, { &hf_lmp_pkttypetbl, { "Packet Type Table", "btlmp.pkttypetbl", FT_UINT8, BASE_DEC, VALS(packet_type_table), 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr, { "PM_ADDR", "btlmp.pmaddr", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr1, { "PM_ADDR 1", "btlmp.pmaddr1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr2, { "PM_ADDR 2", "btlmp.pmaddr2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr3, { "PM_ADDR 3", "btlmp.pmaddr3", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr4, { "PM_ADDR 4", "btlmp.pmaddr4", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr5, { "PM_ADDR 5", "btlmp.pmaddr5", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr6, { "PM_ADDR 6", "btlmp.pmaddr6", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pmaddr7, { "PM_ADDR 7", "btlmp.pmaddr7", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pollintvl, { "Poll Interval", "btlmp.pollintvl", FT_UINT16, BASE_HEX, NULL, 0x0, "Poll Interval in slots", HFILL } }, { &hf_lmp_pollper, { "Poll Period", "btlmp.pollper", FT_UINT8, BASE_DEC, NULL, 0x0, "Poll Period in units of 1.25 ms", HFILL } }, { &hf_lmp_pssettings, { "Paging Scheme Settings", "btlmp.pssettings", FT_UINT8, BASE_DEC, VALS(paging_scheme_settings), 0x0, NULL, HFILL } }, { &hf_lmp_pwradjreq, { "Power Adjustment Request", "btlmp.pwradjreq", FT_UINT8, BASE_DEC, VALS(power_adjust_req), 0x0, NULL, HFILL } }, { &hf_lmp_pwradjres, { "Power Adjustment Response", "btlmp.pwradjres", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_pwradj_8dpsk, { "8DPSK", "btlmp.pwradj_8dpsk", FT_UINT8, BASE_DEC, VALS(power_adjust_res), 0x30, "8DPSK Power Adjustment Response", HFILL } }, { &hf_lmp_pwradj_dqpsk, { "DQPSK", "btlmp.pwradj_dqpsk", FT_UINT8, BASE_DEC, VALS(power_adjust_res), 0x0C, "DQPSK Power Adjustment Response", HFILL } }, { &hf_lmp_pwradj_gfsk, { "GFSK", "btlmp.pwradj_gfsk", FT_UINT8, BASE_DEC, VALS(power_adjust_res), 0x03, "GFSK Power Adjustment Response", HFILL } }, { &hf_lmp_rand, { "Random Number", "btlmp.rand", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_rate, { "Data Rate", "btlmp.rate", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_rate_fec, { "FEC", "btlmp.rate.fec", FT_BOOLEAN, BASE_DEC, TFS(&fec), 0x01, "Forward Error Correction", HFILL } }, { &hf_lmp_rate_size, { "Packet Size", "btlmp.rate.size", FT_UINT8, BASE_HEX, VALS(packet_size), 0x06, "Basic Rate Packet Size", HFILL } }, { &hf_lmp_rate_type, { "EDR Type", "btlmp.rate.type", FT_UINT8, BASE_HEX, VALS(edr_type), 0x18, "Enhanced Data Rate type", HFILL } }, { &hf_lmp_rate_edrsize, { "EDR Size", "btlmp.rate.edrsize", FT_UINT8, BASE_HEX, VALS(packet_size), 0x60, "Enhanced Data Rate packet size", HFILL } }, { &hf_lmp_rxfreq, { "RX Frequency", "btlmp.rxfreq", FT_UINT8, BASE_DEC, NULL, 0x0, "Receive Frequency in MHz above 2402", HFILL } }, { &hf_lmp_scohdl, { "SCO Handle", "btlmp.scohdl", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_scopkt, { "SCO Packet", "btlmp.scopkt", FT_UINT8, BASE_DEC, VALS(sco_packet), 0x0, NULL, HFILL } }, { &hf_lmp_slotoffset, { "Slot Offset", "btlmp.slotoffset", FT_UINT16, BASE_DEC, NULL, 0x0, "Slot Offset in microseconds", HFILL } }, { &hf_lmp_sniffatt, { "Sniff Attempt", "btlmp.sniffatt", FT_UINT16, BASE_HEX, NULL, 0x0, "Number of receive slots", HFILL } }, { &hf_lmp_sniffsi, { "Sniff Subrating Instant", "btlmp.sniffsi", FT_UINT32, BASE_HEX, NULL, 0x0, "Sniff Subrating Instant (slot)", HFILL } }, { &hf_lmp_sniffto, { "Sniff Timeout", "btlmp.sniffto", FT_UINT16, BASE_HEX, NULL, 0x0, "Number of receive slots", HFILL } }, { &hf_lmp_subversnr, { "SubVersNr", "btlmp.subversnr", FT_UINT16, BASE_DEC, NULL, 0x0, "SubVersion", HFILL } }, { &hf_lmp_suptimeout, { "Supervision Timeout", "btlmp.suptimeout", FT_UINT16, BASE_HEX, NULL, 0x0, "Supervision Timeout in slots", HFILL } }, { &hf_lmp_swinst, { "Switch Instant", "btlmp.swinst", FT_UINT32, BASE_HEX, NULL, 0x0, "Switch Instant (slot)", HFILL } }, { &hf_lmp_taccess, { "Taccess", "btlmp.taccess", FT_UINT8, BASE_HEX, NULL, 0x0, "Taccess in slots", HFILL } }, { &hf_lmp_tb, { "Tb", "btlmp.tb", FT_UINT16, BASE_HEX, NULL, 0x0, "Tb in slots", HFILL } }, { &hf_lmp_tesco, { "Tesco", "btlmp.tesco", FT_UINT8, BASE_HEX, NULL, 0x0, "Tesco in slots", HFILL } }, { &hf_lmp_testlen, { "Test Length", "btlmp.testlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of test sequence in bytes", HFILL } }, { &hf_lmp_testscen, { "Test Scenario", "btlmp.testscen", FT_UINT8, BASE_DEC, VALS(test_scenario), 0x0, NULL, HFILL } }, { &hf_lmp_tid, { "TID", "btlmp.tid", FT_BOOLEAN, BASE_DEC, TFS(&tid), 0x01, "Transaction ID", HFILL } }, { &hf_lmp_timectrl, { "Timing Control Flags", "btlmp.timectrl", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_lmp_time_change, { "Timing Change", "btlmp.time.change", FT_BOOLEAN, 8, TFS(&time_change), 0x01, NULL, HFILL } }, { &hf_lmp_time_init, { "Initialization", "btlmp.time.init", FT_BOOLEAN, 8, TFS(&time_init), 0x02, NULL, HFILL } }, { &hf_lmp_time_accwin, { "Access Window", "btlmp.time.accwin", FT_BOOLEAN, 8, TFS(&time_accwin), 0x04, NULL, HFILL } }, { &hf_lmp_tsco, { "Tsco", "btlmp.tsco", FT_UINT8, BASE_HEX, NULL, 0x0, "Tsco in slots", HFILL } }, { &hf_lmp_tsniff, { "Tsniff", "btlmp.tsniff", FT_UINT16, BASE_HEX, NULL, 0x0, "Tsniff in slots", HFILL } }, { &hf_lmp_txfreq, { "TX Frequency", "btlmp.txfreq", FT_UINT8, BASE_DEC, NULL, 0x0, "Transmit Frequency in MHz above 2402", HFILL } }, { &hf_lmp_versnr, { "VersNr", "btlmp.versnr", FT_UINT8, BASE_DEC, VALS(versnr), 0x0, "Version", HFILL } }, { &hf_lmp_wesco, { "Wesco", "btlmp.wesco", FT_UINT8, BASE_HEX, NULL, 0x0, "Number of slots in retransmission window", HFILL } }, }; /* protocol subtree arrays */ static gint *ett[] = { &ett_lmp, &ett_lmp_pwradjres, &ett_lmp_rate, &ett_lmp_timectrl, }; /* register the protocol name and description */ proto_btlmp = proto_register_protocol( "Bluetooth Link Manager Protocol", /* full name */ "btlmp", /* short name */ "btlmp" /* abbreviation (e.g. for filters) */ ); register_dissector("btlmp", dissect_btlmp, proto_btlmp); /* register the header fields and subtrees used */ proto_register_field_array(proto_btlmp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_btlmp(void) { } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */