From fad50ec11d648d196884b29a394dc77ed44c4410 Mon Sep 17 00:00:00 2001 From: Matheus Eduardo Garbelini Date: Wed, 1 Sep 2021 10:01:05 +0800 Subject: [PATCH] add dissector --- .gitignore | 4 +- BTSnifferBREDR.py | 1 + dissectors/AUTHORS | 3 + dissectors/CMakeLists.txt | 58 + dissectors/COPYING | 340 +++ dissectors/README.md | 40 + dissectors/build.sh | 38 + dissectors/config.h | 381 +++ dissectors/h4bcm.so | Bin 0 -> 406056 bytes dissectors/packet-btbrlmp.c | 4987 +++++++++++++++++++++++++++++++++++ dissectors/packet-h4bcm.c | 1570 +++++++++++ dissectors/plugin.c | 40 + 12 files changed, 7460 insertions(+), 2 deletions(-) create mode 100644 dissectors/AUTHORS create mode 100644 dissectors/CMakeLists.txt create mode 100644 dissectors/COPYING create mode 100644 dissectors/README.md create mode 100755 dissectors/build.sh create mode 100644 dissectors/config.h create mode 100755 dissectors/h4bcm.so create mode 100644 dissectors/packet-btbrlmp.c create mode 100644 dissectors/packet-h4bcm.c create mode 100644 dissectors/plugin.c diff --git a/.gitignore b/.gitignore index b1bd130..c19eedc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ firmware/.pio/ -libs/__pycache__/ +*__pycache__* -*__pycache__* \ No newline at end of file +dissectors/build/ diff --git a/BTSnifferBREDR.py b/BTSnifferBREDR.py index 594d77b..4647770 100755 --- a/BTSnifferBREDR.py +++ b/BTSnifferBREDR.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 + import os import sys import _ctypes diff --git a/dissectors/AUTHORS b/dissectors/AUTHORS new file mode 100644 index 0000000..bde8539 --- /dev/null +++ b/dissectors/AUTHORS @@ -0,0 +1,3 @@ +Authors: +Jiska Classen / Secure Mobile Networking Lab +Michael Ossmann diff --git a/dissectors/CMakeLists.txt b/dissectors/CMakeLists.txt new file mode 100644 index 0000000..0236e3a --- /dev/null +++ b/dissectors/CMakeLists.txt @@ -0,0 +1,58 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) +include(UseMakePluginReg) + +# Plugin name and version info (major minor micro extra) +set_module_info(h4bcm 1 1 0 0) + +set(DISSECTOR_SRC packet-h4bcm.c packet-btbrlmp.c) + +set(PLUGIN_FILES plugin.c ${DISSECTOR_SRC}) + +set_source_files_properties(${PLUGIN_FILES} PROPERTIES COMPILE_FLAGS + "${WERROR_COMMON_FLAGS}") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +register_plugin_files(plugin.c plugin ${DISSECTOR_SRC}) + +add_plugin_library(h4bcm epan) + +target_link_libraries(h4bcm epan) + +target_compile_options(h4bcm PRIVATE -w) + +install_plugin(h4bcm epan) + +file( + GLOB DISSECTOR_HEADERS + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + "*.h") +checkapi( + NAME + h4bcm + SWITCHES + -g + abort + -g + termoutput + -build + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS}) + +# +# Editor modelines - https://www.wireshark.org/tools/modelines.html +# +# Local variables: c-basic-offset: 8 tab-width: 8 indent-tabs-mode: t End: +# +# vi: set shiftwidth=8 tabstop=8 noexpandtab: +# :indentSize=8:tabSize=8:noTabs=false: +# diff --git a/dissectors/COPYING b/dissectors/COPYING new file mode 100644 index 0000000..aa0aea5 --- /dev/null +++ b/dissectors/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/dissectors/README.md b/dissectors/README.md new file mode 100644 index 0000000..7f920bd --- /dev/null +++ b/dissectors/README.md @@ -0,0 +1,40 @@ +Bluetooth H4 Broadcom Wireshark plugin from the InternalBlue project +==================================================================== + +This dissector contains vendor specific additions to the serial protocol +H4, which is used by the operating system's driver to interact with +Bluetooth chips. Broadcom not only supports sending standard messages +such as HCI commands and events but also has an undocumented +diagnostic protocol using the H4 serial data type 0x07. + +Subprotocols inside Broadcom's diagnostic protocol include the Link Management +Protocol (LMP) and Bluetooth Baseband (BB). The dissectors for LMP and BB were +updated to be compatible with Wireshark 3.0. Credit for most of the LMP and BB +dissector goes to the original authors of libbtbb. + +About this repository +--------------------- + +This repository contains only the Wireshark dissector without the rest of +Internalblue. All credit goes to the original authors of InternalBlue. For +additional information see the original repository: + +https://github.com/seemoo-lab/internalblue + +Build and Install +----------------- + +To build this on Debian/Ubuntu/BackTrack linux distributions: + + sudo apt-get install wireshark-dev wireshark cmake + + mkdir build + cd build + cmake .. + make + make install + +This will install to the ~/.local/lib/wireshark/plugins/3.0/epan/ in your home +directory. To override this set the DESTDIR environment variable when running +cmake. + diff --git a/dissectors/build.sh b/dissectors/build.sh new file mode 100755 index 0000000..1caaf83 --- /dev/null +++ b/dissectors/build.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +PLUGIN_VERSION=2.0.0 +WIRESHARK_INCLUDES=$(pkg-config wireshark --cflags-only-I) + +mkdir -p build + +clang-11 -DG_DISABLE_DEPRECATED -DG_DISABLE_SINGLE_INCLUDES -DHAVE_PLUGINS -DPLUGIN_VERSION=\"$PLUGIN_VERSION\" \ +-Dh4bcm_EXPORTS $WIRESHARK_INCLUDES -I. -fvisibility=hidden -Qunused-arguments \ +-Wall -Wextra -Wendif-labels -Wpointer-arith -Wformat-security -fwrapv -fno-strict-overflow -Wvla -Waddress \ +-Wattributes -Wdiv-by-zero -Wignored-qualifiers -Wpragmas -Wno-overlength-strings -Wno-long-long -Wheader-guard \ +-Wcomma -Wshorten-64-to-32 -Wframe-larger-than=32768 -Wc++-compat -Wunused-const-variable -Wshadow -Wold-style-definition \ +-Wstrict-prototypes -Werror=implicit -Wno-pointer-sign -std=gnu99 -fno-stack-protector -fpic -Wall -Wno-braced-scalar-init \ +-Wno-unused-variable -Wno-reorder -O2 -g -DNDEBUG -fPIC -fcolor-diagnostics -w -std=gnu11 -Werror \ +-o build/packet-h4bcm.c.o -c packet-h4bcm.c + +clang-11 -DG_DISABLE_DEPRECATED -DG_DISABLE_SINGLE_INCLUDES -DHAVE_PLUGINS -DPLUGIN_VERSION=\"$PLUGIN_VERSION\" \ +-Dh4bcm_EXPORTS $WIRESHARK_INCLUDES -I. -fvisibility=hidden -Qunused-arguments \ +-Wall -Wextra -Wendif-labels -Wpointer-arith -Wformat-security -fwrapv -fno-strict-overflow -Wvla -Waddress \ +-Wattributes -Wdiv-by-zero -Wignored-qualifiers -Wpragmas -Wno-overlength-strings -Wno-long-long -Wheader-guard \ +-Wcomma -Wshorten-64-to-32 -Wframe-larger-than=32768 -Wc++-compat -Wunused-const-variable -Wshadow -Wold-style-definition \ +-Wstrict-prototypes -Werror=implicit -Wno-pointer-sign -std=gnu99 -fno-stack-protector -fpic -Wall -Wno-braced-scalar-init \ +-Wno-unused-variable -Wno-reorder -O2 -g -DNDEBUG -fPIC -fcolor-diagnostics -w -std=gnu11 -Werror \ +-o build/packet-btbrlmp.c.o -c packet-btbrlmp.c + +clang-11 -DG_DISABLE_DEPRECATED -DG_DISABLE_SINGLE_INCLUDES -DHAVE_PLUGINS -DPLUGIN_VERSION=\"$PLUGIN_VERSION\" \ +-Dh4bcm_EXPORTS $WIRESHARK_INCLUDES -I. -fvisibility=hidden -Qunused-arguments \ +-Wall -Wextra -Wendif-labels -Wpointer-arith -Wformat-security -fwrapv -fno-strict-overflow -Wvla -Waddress \ +-Wattributes -Wdiv-by-zero -Wignored-qualifiers -Wpragmas -Wno-overlength-strings -Wno-long-long -Wheader-guard \ +-Wcomma -Wshorten-64-to-32 -Wframe-larger-than=32768 -Wc++-compat -Wunused-const-variable -Wshadow -Wold-style-definition \ +-Wstrict-prototypes -Werror=implicit -Wno-pointer-sign -std=gnu99 -fno-stack-protector -fpic -Wall -Wno-braced-scalar-init \ +-Wno-unused-variable -Wno-reorder -O2 -g -DNDEBUG -fPIC -fcolor-diagnostics -w -std=gnu11 -Werror \ +-o build/plugin.c.o -c plugin.c + + +gcc --std=gnu11 -fPIC -w -O3 -shared -o h4bcm.so build/packet-btbrlmp.c.o build/packet-h4bcm.c.o build/plugin.c.o -lwireshark -lwiretap -lwsutil + +# sudo cp h4bcm.so /usr/local/lib/wireshark/plugins/3.4/epan/ diff --git a/dissectors/config.h b/dissectors/config.h new file mode 100644 index 0000000..4749de7 --- /dev/null +++ b/dissectors/config.h @@ -0,0 +1,381 @@ +/* cmakeconfig.h.in */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* Note: You cannot use earlier #defines in later #cmakedefines (cmake 2.6.2). */ + +/* Name of package */ +#define PACKAGE "wireshark" + +#define VERSION_EXTRA "" + +/* Version number of package */ +#define VERSION "3.4.0" +#define VERSION_MAJOR 3 +#define VERSION_MINOR 4 +#define VERSION_MICRO 0 + +#define PLUGIN_PATH_ID "3.4" +#define VERSION_FLAVOR "Development Build" + +/* Build wsutil with SIMD optimization */ +#define HAVE_SSE4_2 1 + +/* Define to 1 if we want to enable plugins */ +#define HAVE_PLUGINS 1 + +/* Define to 1 if we check hf conflict */ +/* #undef ENABLE_CHECK_FILTER */ + +/* Link Wireshark libraries statically */ +/* #undef ENABLE_STATIC */ + +/* Enable AirPcap */ +/* #undef HAVE_AIRPCAP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALLOCA_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to use the MaxMind DB library */ +/* #undef HAVE_MAXMINDDB */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if yu have the `fseeko` function. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if you have the `getexecname' function. */ +/* #undef HAVE_GETEXECNAME */ + +/* Define to 1 if you have the `getifaddrs' function. */ +#define HAVE_GETIFADDRS 1 + +/* Define if LIBSSH support is enabled */ +/* #undef HAVE_LIBSSH */ + +/* Define if you have the 'dlget' function. */ +/* #undef HAVE_DLGET */ + +/* Define if you have the 'getexecname' function. */ +/* #undef HAVE_GETEXECNAME */ + +/* Define if you have the 'floorl' function. */ +#define HAVE_FLOORL 1 + +/* Define to 1 if you have the getopt_long function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define to use heimdal kerberos */ +/* #undef HAVE_HEIMDAL_KERBEROS */ + +/* Define to 1 if you have the `krb5_pac_verify' function. */ +#define HAVE_KRB5_PAC_VERIFY 1 + +/* Define to 1 if you have the `krb5_c_fx_cf2_simple' function. */ +#define HAVE_KRB5_C_FX_CF2_SIMPLE 1 + +/* Define to 1 if you have the `inflatePrime' function. */ +#define HAVE_INFLATEPRIME 1 + +/* Define to 1 if you have the `issetugid' function. */ +/* #undef HAVE_ISSETUGID */ + +/* Define to use kerberos */ +#define HAVE_KERBEROS 1 + +/* Define to use nghttp2 */ +#define HAVE_NGHTTP2 1 + +/* Define to use the libcap library */ +#define HAVE_LIBCAP 1 + +/* Define to use GnuTLS library */ +#define HAVE_LIBGNUTLS 1 + +/* Define to 1 if GnuTLS was built with pkcs11 support. */ +#define HAVE_GNUTLS_PKCS11 1 + +/* Enable libnl support */ +#define HAVE_LIBNL 1 + +/* libnl version 1 */ +/* #undef HAVE_LIBNL1 */ + +/* libnl version 2 */ +/* #undef HAVE_LIBNL2 */ + +/* libnl version 3 */ +#define HAVE_LIBNL3 1 + +/* Define to use libpcap library */ +#define HAVE_LIBPCAP 1 + +/* Define to 1 if you have the `smi' library (-lsmi). */ +#define HAVE_LIBSMI 1 + +/* Define to use zlib library */ +#define HAVE_ZLIB 1 + +/* Define to use the minizip library */ +/* #undef HAVE_MINIZIP */ + +/* Define to use brotli library */ +#define HAVE_BROTLI 1 + +/* Define to use lz4 library */ +#define HAVE_LZ4 1 + +/* Check for lz4frame */ +#define HAVE_LZ4FRAME_H 1 + +/* Define to use snappy library */ +#define HAVE_SNAPPY 1 + +/* Define to use zstd library */ +#define HAVE_ZSTD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_SOCKIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_IF_BONDING_H 1 + +/* Define to use Lua */ +/* #undef HAVE_LUA */ + +/* Define to use MIT kerberos */ +#define HAVE_MIT_KERBEROS 1 + +/* Define to 1 if you have the `mkstemps' function. */ +#define HAVE_MKSTEMPS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* nl80211.h is new enough */ +#define HAVE_NL80211 1 + +/* SET_CHANNEL is supported */ +#define HAVE_NL80211_CMD_SET_CHANNEL 1 + +/* SPLIT_WIPHY_DUMP is supported */ +#define HAVE_NL80211_SPLIT_WIPHY_DUMP 1 + +/* VHT_CAPABILITY is supported */ +#define HAVE_NL80211_VHT_CAPABILITY 1 + +/* Define to 1 if you have macOS frameworks */ +/* #undef HAVE_MACOS_FRAMEWORKS */ + +/* Define to 1 if you have the macOS CFPropertyListCreateWithStream function */ +/* #undef HAVE_CFPROPERTYLISTCREATEWITHSTREAM */ + +/* Define to 1 if you have the `pcap_create' function. */ +/* #undef HAVE_PCAP_CREATE */ + +/* Define to 1 if the capture buffer size can be set. */ +#define CAN_SET_CAPTURE_BUFFER_SIZE 1 + +/* Define to 1 if you have the `pcap_freecode' function. */ +/* #undef HAVE_PCAP_FREECODE */ + +/* Define to 1 if you have the `pcap_free_datalinks' function. */ +/* #undef HAVE_PCAP_FREE_DATALINKS */ + +/* Define to 1 if you have the `pcap_open' function. */ +/* #undef HAVE_PCAP_OPEN */ + +/* Define to 1 if you have libpcap/WinPcap/Npcap remote capturing support. */ +/* #undef HAVE_PCAP_REMOTE */ + +/* Define to 1 if you have the `pcap_setsampling' function. */ +/* #undef HAVE_PCAP_SETSAMPLING */ + +/* Define to 1 if you have the `pcap_set_tstamp_precision' function. */ +/* #undef HAVE_PCAP_SET_TSTAMP_PRECISION */ + +/* Define to 1 if you have the `pcap_set_tstamp_type' function. */ +/* #undef HAVE_PCAP_SET_TSTAMP_TYPE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the optreset variable */ +/* #undef HAVE_OPTRESET */ + +/* Define if sa_len field exists in struct sockaddr */ +/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ + +/* Define to 1 if you want to playing SBC by standalone BlueZ SBC library */ +#define HAVE_SBC 1 + +/* Define to 1 if you have the SpanDSP library. */ +#define HAVE_SPANDSP 1 + +/* Define to 1 if you have the bcg729 library. */ +/* #undef HAVE_BCG729 */ + +/* Define to 1 if you have the ilbc library. */ +/* #undef HAVE_ILBC */ + +/* Define to 1 if you have the speexdsp library. */ +/* #undef HAVE_SPEEXDSP */ + +/* Define to 1 if you have the lixbml2 library. */ +#define HAVE_LIBXML2 1 + +/* Define to 1 if you have the `setresgid' function. */ +#define HAVE_SETRESGID 1 + +/* Define to 1 if you have the `setresuid' function. */ +#define HAVE_SETRESUID 1 + +/* Define to 1 if you have the Sparkle or WinSparkle library */ +/* #undef HAVE_SOFTWARE_UPDATE */ + +/* Define if you have the 'strptime' function. */ +#define HAVE_STRPTIME 1 + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */ + +/* Define if st_flags field exists in struct stat */ +/* #undef HAVE_STRUCT_STAT_ST_FLAGS */ + +/* Define if st_blksize field exists in struct stat */ +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if `__st_birthtime' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT___ST_BIRTHTIME */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if tm_zone field exists in struct tm */ +#define HAVE_STRUCT_TM_TM_ZONE 1 + +/* Define if tzname array exists */ +#define HAVE_TZNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +/* #undef PACKAGE */ + +/* Define to the address where bug reports for this package should be sent. */ +/* #undef PACKAGE_BUGREPORT */ + +/* Define to the full name of this package. */ +/* #undef PACKAGE_NAME */ + +/* Define to the full name and version of this package. */ +/* #undef PACKAGE_STRING */ + +/* Define to the one symbol short name of this package. */ +/* #undef PACKAGE_TARNAME */ + +/* Define to the version of this package. */ +/* #undef PACKAGE_VERSION */ + +/* Define if we have QtMultimedia */ +#define QT_MULTIMEDIA_LIB 1 + +/* Define if we have QtMacExtras */ +/* #undef QT_MACEXTRAS_LIB */ + +/* Build androiddump with libpcap instead of wireshark stuff */ +/* #undef ANDROIDDUMP_USE_LIBPCAP */ + +/* Large file support */ +/* #undef _LARGEFILE_SOURCE */ +/* #undef _LARGEFILE64_SOURCE */ +/* #undef _LARGE_FILES */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +/* Note: not use in the code */ +/* #undef YYTEXT_POINTER */ + +#if defined(_WIN32) + /* + * Make sure everyone is using the same API and that it's sufficient + * for our needs. + * This should match the following: + * - The section in image\wireshark.exe.manifest.in + * - The GetWindowsVersion parts of packaging\nsis\wireshark.nsi + * - The VersionNT parts of packaging\wix\Prerequisites.wxi + */ +# if defined(NTDDI_VERSION) +# error NTDDI_VERSION already defined. +# endif +# define NTDDI_VERSION NTDDI_WIN7 +# if defined(_WIN32_WINNT) +# error _WIN32_WINNT already defined. +# endif +# define _WIN32_WINNT _WIN32_WINNT_WIN7 + + /* WpdPack/INclude/pcap/pcap.h checks for "#if defined(WIN32)" */ +# ifndef WIN32 +# define WIN32 1 +# endif + +# if !defined(QT_VERSION) || !defined(_SSIZE_T_DEFINED) + typedef int ssize_t; +# endif + + /* + * Flex (v 2.5.35) uses this symbol to "exclude" unistd.h + */ +# define YY_NO_UNISTD_H + +# define strncasecmp strnicmp +# define popen _popen +# define pclose _pclose + +# ifndef __STDC__ +# define __STDC__ 0 +# endif + /* Use Unicode in Windows runtime functions. */ +# define UNICODE 1 +# define _UNICODE 1 + +# define NEED_STRPTIME_H 1 +#endif + +#include + +#endif /* __CONFIG_H__ */ diff --git a/dissectors/h4bcm.so b/dissectors/h4bcm.so new file mode 100755 index 0000000000000000000000000000000000000000..11188a669dcfb7909ec792b21ab170301a9e6241 GIT binary patch literal 406056 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

hWEJxkOiF06AsJ$>YTE0t(fZ1H~mL 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

P)| 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 CnH~86 literal 0 HcmV?d00001 diff --git a/dissectors/packet-btbrlmp.c b/dissectors/packet-btbrlmp.c new file mode 100644 index 0000000..519aa2f --- /dev/null +++ b/dissectors/packet-btbrlmp.c @@ -0,0 +1,4987 @@ +/* packet-btbrlmp.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. + */ + +#include "config.h" + +#include +#include + +/* LMP opcodes */ +#define LMP_VSC 0 +#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 +#define LMP_PING_REQ 33 +#define LMP_PING_RES 34 + +/* initialize the protocol and registered fields */ +static int proto_btbrlmp = -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_feat_3slot = -1; +static int hf_lmp_feat_5slot = -1; +static int hf_lmp_feat_enc = -1; +static int hf_lmp_feat_slotoff = -1; +static int hf_lmp_feat_timacc = -1; +static int hf_lmp_feat_rolesw = -1; +static int hf_lmp_feat_holdmo = -1; +static int hf_lmp_feat_sniffmo = -1; +static int hf_lmp_feat_res0 = -1; +static int hf_lmp_feat_pwrctlreq = -1; +static int hf_lmp_feat_cqddr = -1; +static int hf_lmp_feat_sco = -1; +static int hf_lmp_feat_hv2 = -1; +static int hf_lmp_feat_hv3 = -1; +static int hf_lmp_feat_mulaw = -1; +static int hf_lmp_feat_alaw = -1; +static int hf_lmp_feat_cvsd = -1; +static int hf_lmp_feat_pagneg = -1; +static int hf_lmp_feat_pwrctl = -1; +static int hf_lmp_feat_transsync = -1; +static int hf_lmp_feat_flowctl1 = -1; +static int hf_lmp_feat_flowctl2 = -1; +static int hf_lmp_feat_flowctl3 = -1; +static int hf_lmp_feat_bcenc = -1; +static int hf_lmp_feat_res1 = -1; +static int hf_lmp_feat_acl2 = -1; +static int hf_lmp_feat_acl3 = -1; +static int hf_lmp_feat_eninq = -1; +static int hf_lmp_feat_intinq = -1; +static int hf_lmp_feat_intpag = -1; +static int hf_lmp_feat_rssiinq = -1; +static int hf_lmp_feat_ev3 = -1; +static int hf_lmp_feat_ev4 = -1; +static int hf_lmp_feat_ev5 = -1; +static int hf_lmp_feat_res2 = -1; +static int hf_lmp_feat_afhcapsl = -1; +static int hf_lmp_feat_afhclasl = -1; +static int hf_lmp_feat_bredrnotsup = -1; +static int hf_lmp_feat_lesup = -1; +static int hf_lmp_feat_3slotenh = -1; +static int hf_lmp_feat_5slotenh = -1; +static int hf_lmp_feat_sniffsubr = -1; +static int hf_lmp_feat_pauseenc = -1; +static int hf_lmp_feat_afhcapma = -1; +static int hf_lmp_feat_afhclama = -1; +static int hf_lmp_feat_esco2 = -1; +static int hf_lmp_feat_esco3 = -1; +static int hf_lmp_feat_3slotenhesco = -1; +static int hf_lmp_feat_extinqres = -1; +static int hf_lmp_feat_simlebredr = -1; +static int hf_lmp_feat_res3 = -1; +static int hf_lmp_feat_ssp = -1; +static int hf_lmp_feat_enpdu = -1; +static int hf_lmp_feat_edr = -1; +static int hf_lmp_feat_nonflush = -1; +static int hf_lmp_feat_res4 = -1; +static int hf_lmp_feat_lstimche = -1; +static int hf_lmp_feat_inqtxpwr = -1; +static int hf_lmp_feat_enhpwr = -1; +static int hf_lmp_feat_res5 = -1; +static int hf_lmp_feat_res6 = -1; +static int hf_lmp_feat_res7 = -1; +static int hf_lmp_feat_res8 = -1; +static int hf_lmp_feat_extfeat = -1; +static int hf_lmp_featuresext = -1; +static int hf_lmp_efeat_ssp = -1; +static int hf_lmp_efeat_lesup = -1; +static int hf_lmp_efeat_lebredr = -1; +static int hf_lmp_efeat_sch = -1; +static int hf_lmp_efeat_csbma = -1; +static int hf_lmp_efeat_csbsl = -1; +static int hf_lmp_efeat_syntr = -1; +static int hf_lmp_efeat_synsc = -1; +static int hf_lmp_efeat_inqresnote = -1; +static int hf_lmp_efeat_genintsc = -1; +static int hf_lmp_efeat_ccadj = -1; +static int hf_lmp_efeat_res0 = -1; +static int hf_lmp_efeat_scc = -1; +static int hf_lmp_efeat_ping = -1; +static int hf_lmp_efeat_res1 = -1; +static int hf_lmp_efeat_trnud = -1; +static int hf_lmp_efeat_sam = -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; + +/* supported features page 0 (standard p. 528) */ +static const int *features_fields[] = { + &hf_lmp_feat_3slot, + &hf_lmp_feat_5slot, + &hf_lmp_feat_enc, + &hf_lmp_feat_slotoff, + &hf_lmp_feat_timacc, + &hf_lmp_feat_rolesw, + &hf_lmp_feat_holdmo, + &hf_lmp_feat_sniffmo, + &hf_lmp_feat_res0, + &hf_lmp_feat_pwrctlreq, + &hf_lmp_feat_cqddr, + &hf_lmp_feat_sco, + &hf_lmp_feat_hv2, + &hf_lmp_feat_hv3, + &hf_lmp_feat_mulaw, + &hf_lmp_feat_alaw, + &hf_lmp_feat_cvsd, + &hf_lmp_feat_pagneg, + &hf_lmp_feat_pwrctl, + &hf_lmp_feat_transsync, + &hf_lmp_feat_flowctl1, + &hf_lmp_feat_flowctl2, + &hf_lmp_feat_flowctl3, + &hf_lmp_feat_bcenc, + &hf_lmp_feat_res1, + &hf_lmp_feat_acl2, + &hf_lmp_feat_acl3, + &hf_lmp_feat_eninq, + &hf_lmp_feat_intinq, + &hf_lmp_feat_intpag, + &hf_lmp_feat_rssiinq, + &hf_lmp_feat_ev3, + &hf_lmp_feat_ev4, + &hf_lmp_feat_ev5, + &hf_lmp_feat_res2, + &hf_lmp_feat_afhcapsl, + &hf_lmp_feat_afhclasl, + &hf_lmp_feat_bredrnotsup, + &hf_lmp_feat_lesup, + &hf_lmp_feat_3slotenh, + &hf_lmp_feat_5slotenh, + &hf_lmp_feat_sniffsubr, + &hf_lmp_feat_pauseenc, + &hf_lmp_feat_afhcapma, + &hf_lmp_feat_afhclama, + &hf_lmp_feat_esco2, + &hf_lmp_feat_esco3, + &hf_lmp_feat_3slotenhesco, + &hf_lmp_feat_extinqres, + &hf_lmp_feat_simlebredr, + &hf_lmp_feat_res3, + &hf_lmp_feat_ssp, + &hf_lmp_feat_enpdu, + &hf_lmp_feat_edr, + &hf_lmp_feat_nonflush, + &hf_lmp_feat_res4, + &hf_lmp_feat_lstimche, + &hf_lmp_feat_inqtxpwr, + &hf_lmp_feat_enhpwr, + &hf_lmp_feat_res5, + &hf_lmp_feat_res6, + &hf_lmp_feat_res7, + &hf_lmp_feat_res8, + &hf_lmp_feat_extfeat, + NULL}; + +/* supported features page 1+2 (standard p. 530) */ +static const int *extfeatures1_fields[] = { + + &hf_lmp_efeat_ssp, + &hf_lmp_efeat_lesup, + &hf_lmp_efeat_lebredr, + &hf_lmp_efeat_sch, + NULL}; + +static const int *extfeatures2_fields[] = { + &hf_lmp_efeat_csbma, + &hf_lmp_efeat_csbsl, + &hf_lmp_efeat_syntr, + &hf_lmp_efeat_synsc, + &hf_lmp_efeat_inqresnote, + &hf_lmp_efeat_genintsc, + &hf_lmp_efeat_ccadj, + &hf_lmp_efeat_res0, + &hf_lmp_efeat_scc, + &hf_lmp_efeat_ping, + &hf_lmp_efeat_res1, + &hf_lmp_efeat_trnud, + &hf_lmp_efeat_sam, + NULL}; + +/* 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_VSC, "LMP_Broadcom_BPCS"}, + {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"}, + {LMP_PING_REQ, "LMP_ping_req"}, + {LMP_PING_RES, "LMP_ping_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, "Bluetooth Core Specification 4.0"}, + {7, "Bluetooth Core Specification 4.1"}, + {8, "Bluetooth Core Specification 4.2"}, + {9, "Bluetooth Core Specification 5.0"}, + {10, "Bluetooth Core Specification 5.1"}, + {11, "Bluetooth Core Specification 5.2"}, + /* 12 - 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, "3DiJoyCorporation"}, + {85, "Plantronics,Inc."}, + {86, "SonyEricssonMobileCommunications"}, + {87, "HarmanInternationalIndustries,Inc."}, + {88, "Vizio,Inc."}, + {89, "NordicSemiconductorASA"}, + {90, "EMMicroelectronic-MarinSA"}, + {91, "RalinkTechnologyCorporation"}, + {92, "BelkinInternational,Inc."}, + {93, "RealtekSemiconductorCorporation"}, + {94, "StonestreetOne,LLC"}, + {95, "Wicentric,Inc."}, + {96, "RivieraWavesS.A.S"}, + {97, "RDAMicroelectronics"}, + {98, "GibsonGuitars"}, + {99, "MiCommandInc."}, + {100, "BandXIInternational,LLC"}, + {101, "Hewlett-PackardCompany"}, + {102, "9SolutionsOy"}, + {103, "GNNetcomA/S"}, + {104, "GeneralMotors"}, + {105, "A&DEngineering,Inc."}, + {106, "MindTreeLtd."}, + {107, "PolarElectroOY"}, + {108, "BeautifulEnterpriseCo.,Ltd."}, + {109, "BriarTek,Inc"}, + {110, "SummitDataCommunications,Inc."}, + {111, "SoundID"}, + {112, "Monster,LLC"}, + {113, "connectBlueAB"}, + {114, "ShangHaiSuperSmartElectronicsCo.Ltd."}, + {115, "GroupSenseLtd."}, + {116, "Zomm,LLC"}, + {117, "SamsungElectronicsCo.Ltd."}, + {118, "CreativeTechnologyLtd."}, + {119, "LairdTechnologies"}, + {120, "Nike,Inc."}, + {121, "lesswireAG"}, + {122, "MStarSemiconductor,Inc."}, + {123, "HanlynnTechnologies"}, + {124, "A&RCambridge"}, + {125, "SeersTechnologyCo.,Ltd."}, + {126, "SportsTrackingTechnologiesLtd."}, + {127, "AutonetMobile"}, + {128, "DeLormePublishingCompany,Inc."}, + {129, "WuXiVimicro"}, + {130, "SennheiserCommunicationsA/S"}, + {131, "TimeKeepingSystems,Inc."}, + {132, "LudusHelsinkiLtd."}, + {133, "BlueRadios,Inc."}, + {134, "EquinuxAG"}, + {135, "GarminInternational,Inc."}, + {136, "Ecotest"}, + {137, "GNReSoundA/S"}, + {138, "Jawbone"}, + {139, "TopconPositioningSystems,LLC"}, + {140, "GimbalInc.(formerlyQualcommLabs,Inc.andQualcommRetailSolutions,Inc.)"}, + {141, "ZscanSoftware"}, + {142, "QuinticCorp"}, + {143, "TelitWirelessSolutionsGmbH(formerlyStollmannE+VGmbH)"}, + {144, "FunaiElectricCo.,Ltd."}, + {145, "AdvancedPANMOBILsystemsGmbH&Co.KG"}, + {146, "ThinkOptics,Inc."}, + {147, "UniversalElectronics,Inc."}, + {148, "AirohaTechnologyCorp."}, + {149, "NECLighting,Ltd."}, + {150, "ODMTechnology,Inc."}, + {151, "ConnecteDeviceLtd."}, + {152, "zero1.tvGmbH"}, + {153, "i.TechDynamicGlobalDistributionLtd."}, + {154, "Alpwise"}, + {155, "JiangsuToppowerAutomotiveElectronicsCo.,Ltd."}, + {156, "Colorfy,Inc."}, + {157, "GeoforceInc."}, + {158, "BoseCorporation"}, + {159, "SuuntoOy"}, + {160, "KensingtonComputerProductsGroup"}, + {161, "SR-Medizinelektronik"}, + {162, "VertuCorporationLimited"}, + {163, "MetaWatchLtd."}, + {164, "LINAKA/S"}, + {165, "OTLDynamicsLLC"}, + {166, "PandaOceanInc."}, + {167, "VisteonCorporation"}, + {168, "ARPDevicesLimited"}, + {169, "MagnetiMarelliS.p.A"}, + {170, "CAENRFIDsrl"}, + {171, "Ingenieur-SystemgruppeZahnGmbH"}, + {172, "GreenThrottleGames"}, + {173, "PeterSystemtechnikGmbH"}, + {174, "OmegawaveOy"}, + {175, "Cinetix"}, + {176, "PassifSemiconductorCorp"}, + {177, "SarisCyclingGroup,Inc"}, + {178, "BekeyA/S"}, + {179, "ClarinoxTechnologiesPty.Ltd."}, + {180, "BDETechnologyCo.,Ltd."}, + {181, "SwirlNetworks"}, + {182, "Mesointernational"}, + {183, "TreLabLtd"}, + {184, "QualcommInnovationCenter,Inc.(QuIC)"}, + {185, "JohnsonControls,Inc."}, + {186, "StarkeyLaboratoriesInc."}, + {187, "S-PowerElectronicsLimited"}, + {188, "AceSensorInc"}, + {189, "AplixCorporation"}, + {190, "AAMPofAmerica"}, + {191, "StalmartTechnologyLimited"}, + {192, "AMICCOMElectronicsCorporation"}, + {193, "ShenzhenExcelsecuDataTechnologyCo.,Ltd"}, + {194, "GeneqInc."}, + {195, "adidasAG"}, + {196, "LGElectronics"}, + {197, "OnsetComputerCorporation"}, + {198, "SelflyBV"}, + {199, "QuuppaOy."}, + {200, "GeLoInc"}, + {201, "Evluma"}, + {202, "MC10"}, + {203, "BinauricSE"}, + {204, "BeatsElectronics"}, + {205, "MicrochipTechnologyInc."}, + {206, "ElgatoSystemsGmbH"}, + {207, "ARCHOSSA"}, + {208, "Dexcom,Inc."}, + {209, "PolarElectroEuropeB.V."}, + {210, "DialogSemiconductorB.V."}, + {211, "TaixingbangTechnology(HK)Co,.LTD."}, + {212, "Kawantech"}, + {213, "AustcoCommunicationSystems"}, + {214, "TimexGroupUSA,Inc."}, + {215, "QualcommTechnologies,Inc."}, + {216, "QualcommConnectedExperiences,Inc."}, + {217, "VoyetraTurtleBeach"}, + {218, "txtrGmbH"}, + {219, "Biosentronics"}, + {220, "Procter&Gamble"}, + {221, "HosidenCorporation"}, + {222, "MuzikLLC"}, + {223, "MisfitWearablesCorp"}, + {224, "Google"}, + {225, "DanlersLtd"}, + {226, "SemilinkInc"}, + {227, "inMusicBrands,Inc"}, + {228, "L.S.ResearchInc."}, + {229, "EdenSoftwareConsultantsLtd."}, + {230, "Freshtemp"}, + {231, "KSTechnologies"}, + {232, "ACTSTechnologies"}, + {233, "VtrackSystems"}, + {234, "Nielsen-KellermanCompany"}, + {235, "ServerTechnologyInc."}, + {236, "BioResearchAssociates"}, + {237, "JollyLogic,LLC"}, + {238, "AboveAverageOutcomes,Inc."}, + {239, "BitsplittersGmbH"}, + {240, "PayPal,Inc."}, + {241, "WitronTechnologyLimited"}, + {242, "MorseProjectInc."}, + {243, "KentDisplaysInc."}, + {244, "NautilusInc."}, + {245, "SmartifierOy"}, + {246, "ElcometerLimited"}, + {247, "VSNTechnologies,Inc."}, + {248, "AceUniCorp.,Ltd."}, + {249, "StickNFind"}, + {250, "CrystalCodeAB"}, + {251, "KOUKAAMa.s."}, + {252, "DelphiCorporation"}, + {253, "ValenceTechLimited"}, + {254, "StanleyBlackandDecker"}, + {255, "TypoProducts,LLC"}, + {256, "TomTomInternationalBV"}, + {257, "Fugoo,Inc."}, + {258, "KeiserCorporation"}, + {259, "Bang&OlufsenA/S"}, + {260, "PLUSLocationSystemsPtyLtd"}, + {261, "UbiquitousComputingTechnologyCorporation"}, + {262, "InnovativeYachtterSolutions"}, + {263, "WilliamDemantHoldingA/S"}, + {264, "ChiconyElectronicsCo.,Ltd."}, + {265, "AtusBV"}, + {266, "CodegateLtd"}, + {267, "ERi,Inc"}, + {268, "TransducersDirect,LLC"}, + {269, "FujitsuTenLImited"}, + {270, "AudiAG"}, + {271, "HiSiliconTechnologiesCol,Ltd."}, + {272, "NipponSeikiCo.,Ltd."}, + {273, "SteelseriesApS"}, + {274, "VisyblInc."}, + {275, "OpenbrainTechnologies,Co.,Ltd."}, + {276, "Xensr"}, + {277, "e.solutions"}, + {278, "10AKTechnologies"}, + {279, "WimotoTechnologiesInc"}, + {280, "RadiusNetworks,Inc."}, + {281, "WizeTechnologyCo.,Ltd."}, + {282, "QualcommLabs,Inc."}, + {283, "HewlettPackardEnterprise"}, + {284, "Baidu"}, + {285, "ArendiAG"}, + {286, "SkodaAutoa.s."}, + {287, "VolkswagenAG"}, + {288, "PorscheAG"}, + {289, "SinoWealthElectronicLtd."}, + {290, "AirTurn,Inc."}, + {291, "Kinsa,Inc"}, + {292, "HIDGlobal"}, + {293, "SEATes"}, + {294, "PrometheanLtd."}, + {295, "SaluticaAlliedSolutions"}, + {296, "GPSIGroupPtyLtd"}, + {297, "NimbleDevicesOy"}, + {298, "ChangzhouYongseInfotechCo.,Ltd."}, + {299, "SportIQ"}, + {300, "TEMECInstrumentsB.V."}, + {301, "SonyCorporation"}, + {302, "ASSAABLOY"}, + {303, "ClarionCo.Inc."}, + {304, "WarehouseInnovations"}, + {305, "CypressSemiconductor"}, + {306, "MADSInc"}, + {307, "BlueMaestroLimited"}, + {308, "ResolutionProducts,Ltd."}, + {309, "AirewareLLC"}, + {310, "Silvair,Inc."}, + {311, "PrestigioPlazaLtd."}, + {312, "NTEOInc."}, + {313, "FocusSystemsCorporation"}, + {314, "TencentHoldingsLtd."}, + {315, "Allegion"}, + {316, "MurataManufacturingCo.,Ltd."}, + {317, "WirelessWERX"}, + {318, "Nod,Inc."}, + {319, "B&BManufacturingCompany"}, + {320, "AlpineElectronics(China)Co.,Ltd"}, + {321, "FedExServices"}, + {322, "GrapeSystemsInc."}, + {323, "BkonConnect"}, + {324, "LintechGmbH"}, + {325, "NovatelWireless"}, + {326, "Ciright"}, + {327, "MightyCast,Inc."}, + {328, "AmbimatElectronics"}, + {329, "PerytonsLtd."}, + {330, "TivoliAudio,LLC"}, + {331, "MasterLock"}, + {332, "Mesh-NetLtd"}, + {333, "HUIZHOUDESAYSVAUTOMOTIVECO.,LTD."}, + {334, "Tangerine,Inc."}, + {335, "B&WGroupLtd."}, + {336, "PioneerCorporation"}, + {337, "OnBeep"}, + {338, "VernierSoftware&Technology"}, + {339, "ROLErgo"}, + {340, "PebbleTechnology"}, + {341, "NETATMO"}, + {342, "AccumulateAB"}, + {343, "AnhuiHuamiInformationTechnologyCo.,Ltd."}, + {344, "Inmites.r.o."}, + {345, "ChefSteps,Inc."}, + {346, "micasAG"}, + {347, "BiomedicalResearchLtd."}, + {348, "PitiusTecS.L."}, + {349, "Estimote,Inc."}, + {350, "UnikeyTechnologies,Inc."}, + {351, "TimerCapCo."}, + {352, "AwoX"}, + {353, "yikes"}, + {354, "MADSGlobalNZLtd."}, + {355, "PCHInternational"}, + {356, "QingdaoYeelinkInformationTechnologyCo.,Ltd."}, + {357, "MilwaukeeTool(FormallyMilwaukeeElectricTools)"}, + {358, "MISHIKPteLtd"}, + {359, "AscensiaDiabetesCareUSInc."}, + {360, "SpiceboxLLC"}, + {361, "emberlight"}, + {362, "Cooper-AtkinsCorporation"}, + {363, "Qblinks"}, + {364, "MYSPHERA"}, + {365, "LifeScanInc"}, + {366, "VolanticAB"}, + {367, "PodoLabs,Inc"}, + {368, "RocheDiabetesCareAG"}, + {369, "AmazonFulfillmentService"}, + {370, "ConnovateTechnologyPrivateLimited"}, + {371, "Kocomojo,LLC"}, + {372, "EverykeyInc."}, + {373, "DynamicControls"}, + {374, "SentriLock"}, + {375, "I-SYSTinc."}, + {376, "CASIOCOMPUTERCO.,LTD."}, + {377, "LAPISSemiconductorCo.,Ltd."}, + {378, "Telemonitor,Inc."}, + {379, "taskitGmbH"}, + {380, "DaimlerAG"}, + {381, "BatAndCat"}, + {382, "BluDotzLtd"}, + {383, "XTelWirelessApS"}, + {384, "GigasetCommunicationsGmbH"}, + {385, "GeckoHealthInnovations,Inc."}, + {386, "HOPUbiquitous"}, + {387, "WaltDisney"}, + {388, "Nectar"}, + {389, "bel'appsLLC"}, + {390, "CORELightingLtd"}, + {391, "SeraphimSenseLtd"}, + {392, "UnicoRBC"}, + {393, "PhysicalEnterprisesInc."}, + {394, "AbleTrendTechnologyLimited"}, + {395, "KonicaMinolta,Inc."}, + {396, "WiloSE"}, + {397, "ExtronDesignServices"}, + {398, "Fitbit,Inc."}, + {399, "FirefliesSystems"}, + {400, "IntellettoTechnologiesInc."}, + {401, "FDKCORPORATION"}, + {402, "Cloudleaf,Inc"}, + {403, "MavericAutomationLLC"}, + {404, "AcousticStreamCorporation"}, + {405, "Zuli"}, + {406, "PaxtonAccessLtd"}, + {407, "WiSilicaInc."}, + {408, "VENGITKorlatoltFelelosseguTarsasag"}, + {409, "SALTOSYSTEMSS.L."}, + {410, "TRONForum(formerlyT-EngineForum)"}, + {411, "CUBETECHs.r.o."}, + {412, "CokiyaIncorporated"}, + {413, "CVSHealth"}, + {414, "Ceruus"}, + {415, "StrainstallLtd"}, + {416, "ChannelEnterprises(HK)Ltd."}, + {417, "FIAMM"}, + {418, "GIGALANE.CO.,LTD"}, + {419, "EROAD"}, + {420, "MineSafetyAppliances"}, + {421, "IconHealthandFitness"}, + {422, "WilleEngineering(formelyasAsandooGmbH)"}, + {423, "ENERGOUSCORPORATION"}, + {424, "Taobao"}, + {425, "CanonInc."}, + {426, "GeophysicalTechnologyInc."}, + {427, "Facebook,Inc."}, + {428, "TrividiaHealth,Inc."}, + {429, "FlightSafetyInternational"}, + {430, "EarlensCorporation"}, + {431, "SunriseMicroDevices,Inc."}, + {432, "StarMicronicsCo.,Ltd."}, + {433, "NetizensSp.zo.o."}, + {434, "NymiInc."}, + {435, "Nytec,Inc."}, + {436, "TrineoSp.zo.o."}, + {437, "NestLabsInc."}, + {438, "LMTechnologiesLtd"}, + {439, "GeneralElectricCompany"}, + {440, "i+D3S.L."}, + {441, "HANAMicron"}, + {442, "StagesCyclingLLC"}, + {443, "CochlearBoneAnchoredSolutionsAB"}, + {444, "SenionLabAB"}, + {445, "SyszoneCo.,Ltd"}, + {446, "PulsateMobileLtd."}, + {447, "HongKongHunterSunElectronicLimited"}, + {448, "pironexGmbH"}, + {449, "BRADATECHCorp."}, + {450, "TransenergooilAG"}, + {451, "Bunch"}, + {452, "DMEMicroelectronics"}, + {453, "BitcrazeAB"}, + {454, "HASWAREInc."}, + {455, "AbiogenixInc."}, + {456, "Poly-ControlApS"}, + {457, "Avi-on"}, + {458, "LaerdalMedicalAS"}, + {459, "FetchMyPet"}, + {460, "SamLabsLtd."}, + {461, "ChengduSynwingTechnologyLtd"}, + {462, "HOUWASYSTEMDESIGN,k.k."}, + {463, "BSH"}, + {464, "PrimusInterParesLtd"}, + {465, "AugustHome,Inc"}, + {466, "GillElectronics"}, + {467, "SkyWaveDesign"}, + {468, "NewlabS.r.l."}, + {469, "ELADsrl"}, + {470, "G-wearablesinc."}, + {471, "SquadroneSystemsInc."}, + {472, "CodeCorporation"}, + {473, "SavantSystemsLLC"}, + {474, "LogitechInternationalSA"}, + {475, "InnblueConsulting"}, + {476, "iParkingLtd."}, + {477, "KoninklijkePhilipsElectronicsN.V."}, + {478, "MinelabElectronicsPtyLimited"}, + {479, "BisonGroupLtd."}, + {480, "WidexA/S"}, + {481, "JollaLtd"}, + {482, "Lectronix,Inc."}, + {483, "CaterpillarInc"}, + {484, "FreedomInnovations"}, + {485, "DynamicDevicesLtd"}, + {486, "TechnologySolutions(UK)Ltd"}, + {487, "IPSGroupInc."}, + {488, "STIR"}, + {489, "Sano,Inc."}, + {490, "AdvancedApplicationDesign,Inc."}, + {491, "AutoMapLLC"}, + {492, "SpreadtrumCommunicationsShanghaiLtd"}, + {493, "CuteCircuitLTD"}, + {494, "ValeoService"}, + {495, "FullpowerTechnologies,Inc."}, + {496, "KloudNation"}, + {497, "ZebraTechnologiesCorporation"}, + {498, "Itron,Inc."}, + {499, "TheUniversityofTokyo"}, + {500, "UTCFireandSecurity"}, + {501, "CoolWebthingsLimited"}, + {502, "DJOGlobal"}, + {503, "GellinerLimited"}, + {504, "Anyka(Guangzhou)MicroelectronicsTechnologyCo,LTD"}, + {505, "MedtronicInc."}, + {506, "GozioInc."}, + {507, "FormLifting,LLC"}, + {508, "WahooFitness,LLC"}, + {509, "KontaktMicro-LocationSp.zo.o."}, + {510, "RadioSystemsCorporation"}, + {511, "FreescaleSemiconductor,Inc."}, + {512, "VerifoneSystemsPteLtd.TaiwanBranch"}, + {513, "ARTiming"}, + {514, "RigadoLLC"}, + {515, "KemppiOy"}, + {516, "TapcentiveInc."}, + {517, "SmartboticsInc."}, + {518, "OtterProducts,LLC"}, + {519, "STEMPInc."}, + {520, "LumiGeekLLC"}, + {521, "InvisionHeartInc."}, + {522, "MacnicaInc."}, + {523, "JaguarLandRoverLimited"}, + {524, "CoroWareTechnologies,Inc"}, + {525, "SimploTechnologyCo.,LTD"}, + {526, "OmronHealthcareCo.,LTD"}, + {527, "ComoduleGMBH"}, + {528, "ikeGPS"}, + {529, "TelinkSemiconductorCo.Ltd"}, + {530, "InterplanCo.,Ltd"}, + {531, "WylerAG"}, + {532, "IKMultimediaProductionsrl"}, + {533, "LukotonExperienceOy"}, + {534, "MTILtd"}, + {535, "Tech4home,Lda"}, + {536, "HiotechAB"}, + {537, "DOTTLimited"}, + {538, "BlueSpeckLabs,LLC"}, + {539, "CiscoSystems,Inc"}, + {540, "MobicommInc"}, + {541, "Edamic"}, + {542, "Goodnet,Ltd"}, + {543, "LusterLeafProductsInc"}, + {544, "ManusMachinaBV"}, + {545, "MobiquityNetworksInc"}, + {546, "PraxisDynamics"}, + {547, "PhilipMorrisProductsS.A."}, + {548, "ComarchSA"}, + {549, "NestlNespressoS.A."}, + {550, "MerliniaA/S"}, + {551, "LifeBEAMTechnologies"}, + {552, "TwocanoesLabs,LLC"}, + {553, "MuovertiLimited"}, + {554, "StamerMusikanlagenGMBH"}, + {555, "TeslaMotors"}, + {556, "PharynksCorporation"}, + {557, "Lupine"}, + {558, "SiemensAG"}, + {559, "Huami(Shanghai)CultureCommunicationCO.,LTD"}, + {560, "FosterElectricCompany,Ltd"}, + {561, "ETASA"}, + {562, "x-SensoSolutionsKft"}, + {563, "ShenzhenSuLongCommunicationLtd"}, + {564, "FengFan(BeiJing)TechnologyCo,Ltd"}, + {565, "QrioInc"}, + {566, "PitpatpetLtd"}, + {567, "MSHelis.r.l."}, + {568, "Trakm8Ltd"}, + {569, "JINCO,Ltd"}, + {570, "AlatechTehnology"}, + {571, "BeijingCarePulseElectronicTechnologyCo,Ltd"}, + {572, "Awarepoint"}, + {573, "ViCentraB.V."}, + {574, "RavenIndustries"}, + {575, "WaveWareTechnologiesInc."}, + {576, "ArgenoxTechnologies"}, + {577, "BragiGmbH"}, + {578, "16LabInc"}, + {579, "MasimoCorp"}, + {580, "IoteraInc"}, + {581, "Endress+Hauser"}, + {582, "ACKmeNetworks,Inc."}, + {583, "FiftyThreeInc."}, + {584, "ParkerHannifinCorp"}, + {585, "TranscranialLtd"}, + {586, "UwatecAG"}, + {587, "OrlanLLC"}, + {588, "BlueCloverDevices"}, + {589, "M-WaySolutionsGmbH"}, + {590, "MicrotronicsEngineeringGmbH"}, + {591, "SchneiderSchreibgerteGmbH"}, + {592, "SapphireCircuitsLLC"}, + {593, "LumoBodytechInc."}, + {594, "UKCTechnosolution"}, + {595, "XicatoInc."}, + {596, "Playbrush"}, + {597, "DaiNipponPrintingCo.,Ltd."}, + {598, "G24PowerLimited"}, + {599, "AdBabbleLocalCommerceInc."}, + {600, "DevialetSA"}, + {601, "ALTYOR"}, + {602, "UniversityofAppliedSciencesValais/HauteEcoleValaisanne"}, + {603, "FiveInteractive,LLCdbaZendo"}, + {604, "NetEaseHangzhouNetworkco.Ltd."}, + {605, "LexmarkInternationalInc."}, + {606, "FlukeCorporation"}, + {607, "YardarmTechnologies"}, + {608, "SensaRx"}, + {609, "SECVREGmbH"}, + {610, "GlacialRidgeTechnologies"}, + {611, "Identiv,Inc."}, + {612, "DDS,Inc."}, + {613, "SMKCorporation"}, + {614, "SchawbelTechnologiesLLC"}, + {615, "XMISystemsSA"}, + {616, "Cerevo"}, + {617, "TorroxGmbH&CoKG"}, + {618, "Gemalto"}, + {619, "DEKAResearch&DevelopmentCorp."}, + {620, "DomsterTadeuszSzydlowski"}, + {621, "TechnogymSPA"}, + {622, "FLEURBAEYBVBA"}, + {623, "AptcodeSolutions"}, + {624, "LSIADLTechnology"}, + {625, "AnimasCorp"}, + {626, "AlpsElectricCo.,Ltd."}, + {627, "OCEASOFT"}, + {628, "MotsaiResearch"}, + {629, "Geotab"}, + {630, "E.G.O.Elektro-GertebauGmbH"}, + {631, "bewhereinc"}, + {632, "JohnsonOutdoorsInc"}, + {633, "steuteSchaltgerateGmbH&Co.KG"}, + {634, "Ekominiinc."}, + {635, "DEFAAS"}, + {636, "AseptikaLtd"}, + {637, "HUAWEITechnologiesCo.,Ltd.()"}, + {638, "HabitAware,LLC"}, + {639, "ruwidoaustriagmbh"}, + {640, "ITECcorporation"}, + {641, "StoneL"}, + {642, "SonovaAG"}, + {643, "MavenMachines,Inc."}, + {644, "SynapseElectronics"}, + {645, "StandardInnovationInc."}, + {646, "RFCode,Inc."}, + {647, "WallyVenturesS.L."}, + {648, "WillowbankElectronicsLtd"}, + {649, "SKTelecom"}, + {650, "JetroAS"}, + {651, "CodeGearsLTD"}, + {652, "NANOLINKAPS"}, + {653, "IF,LLC"}, + {654, "RFDigitalCorp"}, + {655, "Church&DwightCo.,Inc"}, + {656, "MultibitOy"}, + {657, "CliniCloudInc"}, + {658, "SwiftSensors"}, + {659, "BlueBite"}, + {660, "ELIASGmbH"}, + {661, "SivantosGmbH"}, + {662, "Petzl"}, + {663, "stormpowerltd"}, + {664, "EISSTLtd"}, + {665, "InexessTechnologySimmaKG"}, + {666, "Currant,Inc."}, + {667, "C2Development,Inc."}, + {668, "BlueSkyScientific,LLC"}, + {669, "ALOTTAZSLABS,LLC"}, + {670, "Kupsonspol.sr.o."}, + {671, "AreusEngineeringGmbH"}, + {672, "ImpossibleCameraGmbH"}, + {673, "InventureTrackSystems"}, + {674, "LockedUp"}, + {675, "Itude"}, + {676, "PacificLockCompany"}, + {677, "TendyronCorporation()"}, + {678, "RobertBoschGmbH"}, + {679, "IlluxtroninternationalB.V."}, + {680, "miSportLtd."}, + {681, "Chargelib"}, + {682, "DopplerLab"}, + {683, "BBPOSLimited"}, + {684, "RTBElektronikGmbH&Co.KG"}, + {685, "RxNetworks,Inc."}, + {686, "WeatherFlow,Inc."}, + {687, "TechnicolorUSAInc."}, + {688, "Bestechnic(Shanghai),Ltd"}, + {689, "RadenInc"}, + {690, "JouZenOy"}, + {691, "CLABERS.P.A."}, + {692, "Hyginex,Inc."}, + {693, "HANSHINELECTRICRAILWAYCO.,LTD."}, + {694, "SchneiderElectric"}, + {695, "OortTechnologiesLLC"}, + {696, "ChronoTherapeutics"}, + {697, "RinnaiCorporation"}, + {698, "SwissprimeTechnologiesAG"}, + {699, "Koha.,Co.Ltd"}, + {700, "GenevacLtd"}, + {701, "Chemtronics"}, + {702, "SeguroTechnologySp.zo.o."}, + {703, "RedbirdFlightSimulations"}, + {704, "DashRobotics"}, + {705, "LINECorporation"}, + {706, "GuillemotCorporation"}, + {707, "TechtronicPowerToolsTechnologyLimited"}, + {708, "WilsonSportingGoods"}, + {709, "Lenovo(Singapore)PteLtd.()"}, + {710, "AyatanSensors"}, + {711, "ElectronicsTomorrowLimited"}, + {712, "VASCODataSecurityInternational,Inc."}, + {713, "PayRangeInc."}, + {714, "ABOVSemiconductor"}, + {715, "AINA-WirelessInc."}, + {716, "EijkelkampSoil&Water"}, + {717, "BMAergonomicsb.v."}, + {718, "TevaBrandedPharmaceuticalProductsR&D,Inc."}, + {719, "Anima"}, + {720, "3M"}, + {721, "EmpaticaSrl"}, + {722, "Afero,Inc."}, + {723, "PowercastCorporation"}, + {724, "SecuyouApS"}, + {725, "OMRONCorporation"}, + {726, "SendSolutions"}, + {727, "NIPPONSYSTEMWARECO.,LTD."}, + {728, "Neosfar"}, + {729, "FlieglAgrartechnikGmbH"}, + {730, "Gilvader"}, + {731, "DigiInternationalInc(R)"}, + {732, "DeWalchTechnologies,Inc."}, + {733, "FlintRehabilitationDevices,LLC"}, + {734, "SamsungSDSCo.,Ltd."}, + {735, "BlurProductDevelopment"}, + {736, "UniversityofMichigan"}, + {737, "VictronEnergyBV"}, + {738, "NTTdocomo"}, + {739, "CarmanahTechnologiesCorp."}, + {740, "BytestormLtd."}, + {741, "EspressifIncorporated(())"}, + {742, "Unwire"}, + {743, "ConnectedYard,Inc."}, + {744, "AmericanMusicEnvironments"}, + {745, "SensogramTechnologies,Inc."}, + {746, "FujitsuLimited"}, + {747, "ArdicTechnology"}, + {748, "DeltaSystems,Inc"}, + {749, "HTCCorporation"}, + {750, "CitizenHoldingsCo.,Ltd."}, + {751, "SMART-INNOVATION.inc"}, + {752, "BlackratSoftware"}, + {753, "TheIdeaCave,LLC"}, + {754, "GoPro,Inc."}, + {755, "AuthAir,Inc"}, + {756, "Vensi,Inc."}, + {757, "IndagemTechLLC"}, + {758, "IntemoTechnologies"}, + {759, "DreamVisionsco.,Ltd."}, + {760, "RunteqOyLtd"}, + {761, "IMAGINATIONTECHNOLOGIESLTD"}, + {762, "CoSTARTEchnologies"}, + {763, "ClariusMobileHealthCorp."}, + {764, "ShanghaiFrequenMicroelectronicsCo.,Ltd."}, + {765, "Uwanna,Inc."}, + {766, "LierdaScience&TechnologyGroupCo.,Ltd."}, + {767, "SiliconLaboratories"}, + {768, "WorldMotoInc."}, + {769, "GiatecScientificInc."}, + {770, "LoopDevices,Inc"}, + {771, "IACAelectronique"}, + {772, "ProxyTechnologies,Inc."}, + {773, "SwippApS"}, + {774, "LifeLaboratoryInc."}, + {775, "FUJIINDUSTRIALCO.,LTD."}, + {776, "Surefire,LLC"}, + {777, "DolbyLabs"}, + {778, "Ellisys"}, + {779, "MagnitudeLightingConverters"}, + {780, "HiltiAG"}, + {781, "DevdataS.r.l."}, + {782, "Deviceworx"}, + {783, "ShortcutLabs"}, + {784, "SGLItaliaS.r.l."}, + {785, "PEEQDATA"}, + {786, "DucereTechnologiesPvtLtd"}, + {787, "DiveNav,Inc."}, + {788, "RIIGAISp.zo.o."}, + {789, "ThermoFisherScientific"}, + {790, "AGMeasurematicsPvt.Ltd."}, + {791, "CHUOElectronicsCO.,LTD."}, + {792, "AspentaInternational"}, + {793, "EugsterFrismagAG"}, + {794, "AmberwirelessGmbH"}, + {795, "HQInc"}, + {796, "LabSensorSolutions"}, + {797, "EnterlabApS"}, + {798, "Eyefi,Inc."}, + {799, "MetaSystemS.p.A."}, + {800, "SONOELECTRONICS.CO.,LTD"}, + {801, "Jewelbots"}, + {802, "CompumedicsLimited"}, + {803, "RotorBikeComponents"}, + {804, "Astro,Inc."}, + {805, "AmotusSolutions"}, + {806, "HealthwearTechnologies(Changzhou)Ltd"}, + {807, "EssexElectronics"}, + {808, "GrundfosA/S"}, + {809, "Eargo,Inc."}, + {810, "ElectronicDesignLab"}, + {811, "ESYLUX"}, + {812, "NIPPONSMT.CO.,Ltd"}, + {813, "BMinnovationsGmbH"}, + {814, "indoormap"}, + {815, "OttoQInc"}, + {816, "NorthPoleEngineering"}, + {817, "3flaresTechnologiesInc."}, + {818, "ElectrocompanietA.S."}, + {819, "Mul-T-Lock"}, + {820, "CorentiumAS"}, + {821, "EnlightedInc"}, + {822, "GISTIC"}, + {823, "AJP2Holdings,LLC"}, + {824, "COBIGmbH"}, + {825, "BlueSkyScientific,LLC"}, + {826, "Appception,Inc."}, + {827, "CourtneyThorneLimited"}, + {828, "Virtuosys"}, + {829, "TPVTechnologyLimited"}, + {830, "MonitraSA"}, + {831, "AutomationComponents,Inc."}, + {832, "Letsenses.r.l."}, + {833, "EtesianTechnologiesLLC"}, + {834, "GERTECBRASILLTDA."}, + {835, "DrekkerDevelopmentPty.Ltd."}, + {836, "WhirlInc"}, + {837, "LocusPositioning"}, + {838, "AcuityBrandsLighting,Inc"}, + {839, "PreventBiometrics"}, + {840, "Arioneo"}, + {841, "VersaMe"}, + {842, "Vaddio"}, + {843, "LibratoneA/S"}, + {844, "HMElectronics,Inc."}, + {845, "TASERInternational,Inc."}, + {846, "SafeTrustInc."}, + {847, "HeartlandPaymentSystems"}, + {848, "BitstrataSystemsInc."}, + {849, "PiepsGmbH"}, + {850, "iRiding(Xiamen)TechnologyCo.,Ltd."}, + {851, "AlphaAudiotronics,Inc."}, + {852, "TOPPANFORMSCO.,LTD."}, + {853, "SigmaDesigns,Inc."}, + {854, "SpectrumBrands,Inc."}, + {855, "PolymapWireless"}, + {856, "MagniWareLtd."}, + {857, "NovotecMedicalGmbH"}, + {858, "MedicomInnovationPartnera/s"}, + {859, "MatrixInc."}, + {860, "EatonCorporation"}, + {861, "KYS"}, + {862, "NayaHealth,Inc."}, + {863, "Acromag"}, + {864, "InsuletCorporation"}, + {865, "WellinksInc."}, + {866, "ONSemiconductor"}, + {867, "FREELAPSA"}, + {868, "FaveroElectronicsSrl"}, + {869, "BioMechSensorLLC"}, + {870, "BOLTTSportstechnologiesPrivatelimited"}, + {871, "SapheInternational"}, + {872, "MetormoteAB"}, + {873, "littleBits"}, + {874, "SetPointMedical"}, + {875, "BRControlsProductsBV"}, + {876, "Zipcar"}, + {877, "AirBoltPtyLtd"}, + {878, "KeepTruckinInc"}, + {879, "Motiv,Inc."}, + {880, "WazombiLabsO"}, + {881, "ORBCOMM"}, + {882, "NixieLabs,Inc."}, + {883, "AppNearMeLtd"}, + {884, "HolmanIndustries"}, + {885, "ExpainAS"}, + {886, "ElectronicTemperatureInstrumentsLtd"}, + {887, "PlejdAB"}, + {888, "PropellerHealth"}, + {889, "ShenzheniMCOElectronicTechnologyCo.,Ltd"}, + {890, "Algoria"}, + {891, "ApptionLabsInc."}, + {892, "CronologicsCorporation"}, + {893, "MICRODIALtd."}, + {894, "lulabytesS.L."}, + {895, "NestecS.A."}, + {896, "LLC\"MEGA-Fservice\""}, + {897, "SharpCorporation"}, + {898, "PrecisionOutcomesLtd"}, + {899, "KronosIncorporated"}, + {900, "OCOSMOSCo.,Ltd."}, + {901, "EmbeddedElectronicSolutionsLtd.dbae2Solutions"}, + {902, "AtericaInc."}, + {903, "BluStorPMC,Inc."}, + {904, "KapschTrafficComAB"}, + {905, "ActiveBluCorporation"}, + {906, "KohlerMiraLimited"}, + {907, "Noke"}, + {908, "AppionInc."}, + {909, "ResmedLtd"}, + {910, "CrownstoneB.V."}, + {911, "XiaomiInc."}, + {912, "INFOTECHs.r.o."}, + {913, "ThingsquareAB"}, + {914, "T&D"}, + {915, "LAVAZZAS.p.A."}, + {916, "NetclearanceSystems,Inc."}, + {917, "SDATAWAY"}, + {918, "BLOKSGmbH"}, + {919, "LEGOSystemA/S"}, + {920, "ThetatronicsLtd"}, + {921, "NikonCorporation"}, + {922, "NeST"}, + {923, "SouthSiliconValleyMicroelectronics"}, + {924, "ALEInternational"}, + {925, "CareViewCommunications,Inc."}, + {926, "SchoolBoardLimited"}, + {927, "MolexCorporation"}, + {928, "IVTWirelessLimited"}, + {929, "AlpineLabsLLC"}, + {930, "CanduraInstruments"}, + {931, "SmartMovtTechnologyCo.,Ltd"}, + {932, "TokenZeroLtd"}, + {933, "ACECADEnterpriseCo.,Ltd.(ACECAD)"}, + {934, "Medela,Inc"}, + {935, "AeroScout"}, + {936, "EsrilleInc."}, + {937, "THINKERLYSRL"}, + {938, "ExonSp.zo.o."}, + {939, "MeizuTechnologyCo.,Ltd."}, + {940, "SmabloLTD"}, + {941, "XiQ"}, + {942, "AllswellInc."}, + {943, "Comm-N-SenseCorpDBAVerigo"}, + {944, "VIBRADORMGmbH"}, + {945, "OtodataWirelessNetworkInc."}, + {946, "PropagationSystemsLimited"}, + {947, "MidwestInstruments&Controls"}, + {948, "AlphaNodus,inc."}, + {949, "petPOMM,Inc"}, + {950, "Mattel"}, + {951, "AirblyInc."}, + {952, "A-SafeLimited"}, + {953, "FREDERIQUECONSTANTSA"}, + {954, "MaxscendMicroelectronicsCompanyLimited"}, + {955, "AbbottDiabetesCare"}, + {956, "ASBBankLtd"}, + {957, "amadas"}, + {958, "AppliedScience,Inc."}, + {959, "iLumiSolutionsInc."}, + {960, "ArchSystemsInc."}, + {961, "EmberTechnologies,Inc."}, + {962, "SnapchatInc"}, + {963, "CasambiTechnologiesOy"}, + {964, "PicoTechnologyInc."}, + {965, "St.JudeMedical,Inc."}, + {966, "Intricon"}, + {967, "StructuralHealthSystems,Inc."}, + {968, "AvvelInternational"}, + {969, "GallagherGroup"}, + {970, "In2thingsAutomationPvt.Ltd."}, + {971, "SYSDEVSrl"}, + {972, "VonkilTechnologiesLtd"}, + {973, "WyndTechnologies,Inc."}, + {974, "CONTRINEXS.A."}, + {975, "MIRA,Inc."}, + {976, "WatteamLtd"}, + {977, "DensityInc."}, + {978, "IOTPotIndiaPrivateLimited"}, + {979, "SigmaConnectivityAB"}, + {980, "PEGPEREGOSPA"}, + {981, "WyzelinkSystemsInc."}, + {982, "YotaDevicesLTD"}, + {983, "FINSECUR"}, + {984, "Zen-MeLabsLtd"}, + {985, "3IWareCo.,Ltd."}, + {986, "EnOceanGmbH"}, + {987, "Instabeat,Inc"}, + {988, "NimaLabs"}, + {989, "AndreasStihlAG&Co.KG"}, + {990, "NathanRhoadesLLC"}, + {991, "GrobTechnologies,LLC"}, + {992, "Actions(Zhuhai)TechnologyCo.,Limited"}, + {993, "SPDDevelopmentCompanyLtd"}, + {994, "SensoanOy"}, + {995, "QualcommLifeInc"}, + {996, "Chip-ingAG"}, + {997, "ffly4u"}, + {998, "IoTInstrumentsOy"}, + {999, "TRUEFitnessTechnology"}, + {1000, "ReinerKartengeraeteGmbH&Co.KG."}, + {1001, "SHENZHENLEMONJOYTECHNOLOGYCO.,LTD."}, + {1002, "HelloInc."}, + {1003, "EvollveInc."}, + {1004, "JigowattsInc."}, + {1005, "BASICMICRO.COM,INC."}, + {1006, "CUBETECHNOLOGIES"}, + {1007, "foolographyGmbH"}, + {1008, "CLINK"}, + {1009, "HestanSmartCookingInc."}, + {1010, "WindowMasterA/S"}, + {1011, "FlowscapeAB"}, + {1012, "PALTechnologiesLtd"}, + {1013, "WHERE,Inc."}, + {1014, "ItonTechnologyCorp."}, + {1015, "OwlLabsInc."}, + {1016, "RockfordCorp."}, + {1017, "BeconTechnologiesCo.,Ltd."}, + {1018, "VyassoftTechnologiesInc"}, + {1019, "NoxMedical"}, + {1020, "Kimberly-Clark"}, + {1021, "TrimbleNavigationLtd."}, + {1022, "Littelfuse"}, + {1023, "Withings"}, + {1024, "i-developerITBeratungUG"}, + {1025, ""}, + {1026, "SearsHoldingsCorporation"}, + {1027, "GantnerElectronicGmbH"}, + {1028, "AuthomateInc"}, + {1029, "VertexInternational,Inc."}, + {1030, "Airtago"}, + {1031, "SwissAudioSA"}, + {1032, "ToGetHomeInc."}, + {1033, "AXIS"}, + {1034, "Openmatics"}, + {1035, "JanaCareInc."}, + {1036, "SenixCorporation"}, + {1037, "NorthStarBatteryCompany,LLC"}, + {1038, "SKF(U.K.)Limited"}, + {1039, "CO-AXTechnology,Inc."}, + {1040, "FenderMusicalInstruments"}, + {1041, "LuidiaInc"}, + {1042, "SEFAM"}, + {1043, "WirelessCablesInc"}, + {1044, "LightningProtectionInternationalPtyLtd"}, + {1045, "UberTechnologiesInc"}, + {1046, "SODAGmbH"}, + {1047, "FatigueScience"}, + {1048, "AlpineElectronicsInc."}, + {1049, "NovalogyLTD"}, + {1050, "FridayLabsLimited"}, + {1051, "OrthoAccelTechnologies"}, + {1052, "WaterGuru,Inc."}, + {1053, "BenningElektrotechnikundElektronikGmbH&Co.KG"}, + {1054, "DellComputerCorporation"}, + {1055, "KopinCorporation"}, + {1056, "TecBakeryGmbH"}, + {1057, "BackboneLabs,Inc."}, + {1058, "DELSEYSA"}, + {1059, "ChargifiLimited"}, + {1060, "TrainesenseLtd."}, + {1061, "UnifySoftwareandSolutionsGmbH&Co.KG"}, + {1062, "HusqvarnaAB"}, + {1063, "Focusfleetandfuelmanagementinc"}, + {1064, "SmallLoop,LLC"}, + {1065, "ProlonInc."}, + {1066, "BDMedical"}, + {1067, "iMicroMedIncorporated"}, + {1068, "TictoN.V."}, + {1069, "MeshtechAS"}, + {1070, "MemCachierInc."}, + {1071, "DanfossA/S"}, + {1072, "SnapStykInc."}, + {1073, "AmwayCorporation"}, + {1074, "SilkLabs,Inc."}, + {1075, "PillsyInc."}, + {1076, "HatchBaby,Inc."}, + {1077, "BlocksWearablesLtd."}, + {1078, "DraysonTechnologies(Europe)Limited"}, + {1079, "eBestIOTInc."}, + {1080, "HelvarLtd"}, + {1081, "RadianceTechnologies"}, + {1082, "NuhearaLimited"}, + {1083, "Appsideco.,ltd."}, + {1084, "DeLaval"}, + {1085, "CoilerCorporation"}, + {1086, "Thermomedics,Inc."}, + {1087, "TentacleSyncGmbH"}, + {1088, "Valencell,Inc."}, + {1089, "iProtoXiOy"}, + {1090, "SECOMCO.,LTD."}, + {1091, "TuckerInternationalLLC"}, + {1092, "MetanateLimited"}, + {1093, "KobianCanadaInc."}, + {1094, "NETGEAR,Inc."}, + {1095, "FabtronicsAustraliaPtyLtd"}, + {1096, "GrandCentrixGmbH"}, + {1097, "1UPUSA.comllc"}, + {1098, "SHIMANOINC."}, + {1099, "NainInc."}, + {1100, "LifeStyleLock,LLC"}, + {1101, "VEGAGrieshaberKG"}, + {1102, "XtravaInc."}, + {1103, "TTSTooltechnicSystemsAG&Co.KG"}, + {1104, "TeenageEngineeringAB"}, + {1105, "TunstallNordicAB"}, + {1106, "SvepDesignCenterAB"}, + {1107, "GreenPeakTechnologiesBV"}, + {1108, "SphinxElectronicsGmbH&CoKG"}, + {1109, "Atomation"}, + {1110, "NemikConsultingInc"}, + {1111, "RFINNOVATION"}, + {1112, "MiniSolutionCo.,Ltd."}, + {1113, "Lumenetix,Inc"}, + {1114, "2048450OntarioInc"}, + {1115, "SPACEEKLTD"}, + {1116, "DeltaTCorporation"}, + {1117, "BostonScientificCorporation"}, + {1118, "Nuviz,Inc."}, + {1119, "RealTimeAutomation,Inc."}, + {1120, "Kolibree"}, + {1121, "vhfelektronikGmbH"}, + {1122, "BonsaiSystemsGmbH"}, + {1123, "FathomSystemsInc."}, + {1124, "Bellman&Symfon"}, + {1125, "InternationalForteGroupLLC"}, + {1126, "CycleLabsSolutionsinc."}, + {1127, "CodenexOy"}, + {1128, "KynesimLtd"}, + {1129, "PalagoAB"}, + {1130, "INSIGMAINC."}, + {1131, "PMDSolutions"}, + {1132, "QingdaoRealtimeTechnologyCo.,Ltd."}, + {1133, "BEGAGantenbrink-LeuchtenKG"}, + {1134, "PamborLtd."}, + {1135, "DevelcoProductsA/S"}, + {1136, "iDesigns.r.l."}, + {1137, "TiVoCorp"}, + {1138, "Control-JPtyLtd"}, + {1139, "Steelcase,Inc."}, + {1140, "iApartmentco.,ltd."}, + {1141, "Icominc."}, + {1142, "OxstrenWearableTechnologiesPrivateLimited"}, + {1143, "BlueSparkTechnologies"}, + {1144, "FarSiteCommunicationsLimited"}, + {1145, "mywerksystemGmbH"}, + {1146, "SinosunTechnologyCo.,Ltd."}, + {1147, "MIYOSHIELECTRONICSCORPORATION"}, + {1148, "POWERMATLTD"}, + {1149, "OcclyLLC"}, + {1150, "OurHubDevIvS"}, + {1151, "Pro-Mark,Inc."}, + {1152, "DynometricsInc."}, + {1153, "QuintraxLimited"}, + {1154, "POSTuningUdoVosshenrichGmbH&Co.KG"}, + {1155, "MultiCareSystemsB.V."}, + {1156, "RevolTechnologiesInc"}, + {1157, "SKIDATAAG"}, + {1158, "DEVTECNOLOGIAINDUSTRIA,COMERCIOEMANUTENCAODEEQUIPAMENTOSLTDA.-ME"}, + {1159, "CentricaConnectedHome"}, + {1160, "AutomotiveDataSolutionsInc"}, + {1161, "IgarashiEngineering"}, + {1162, "TaelekOy"}, + {1163, "CPElectronicsLimited"}, + {1164, "VectronixAG"}, + {1165, "S-LabsSp.zo.o."}, + {1166, "CompanionMedical,Inc."}, + {1167, "BlueKitchenGmbH"}, + {1168, "MattingAB"}, + {1169, "SOREX-WirelessSolutionsGmbH"}, + {1170, "ADCTechnology,Inc."}, + {1171, "LynxemiPteLtd"}, + {1172, "SENNHEISERelectronicGmbH&Co.KG"}, + {1173, "LMTMercerGroup,Inc"}, + {1174, "PolymorphicLabsLLC"}, + {1175, "CochlearLimited"}, + {1176, "METERGroup,Inc.USA"}, + {1177, "RuuviInnovationsLtd."}, + {1178, "SituneAS"}, + {1179, "nVisti,LLC"}, + {1180, "DyOcean"}, + {1181, "Uhlmann&ZacherGmbH"}, + {1182, "AND!XORLLC"}, + {1183, "tictoteAB"}, + {1184, "Vypin,LLC"}, + {1185, "PNISensorCorporation"}, + {1186, "ovrEngineered,LLC"}, + {1187, "GT-tronicsHKLtd"}, + {1188, "HerbertWaldmannGmbH&Co.KG"}, + {1189, "GuangzhouFiiOElectronicsTechnologyCo.,Ltd"}, + {1190, "VinetechCo.,Ltd"}, + {1191, "DallasLogicCorporation"}, + {1192, "BioTex,Inc."}, + {1193, "DISCOVERYSOUNDTECHNOLOGY,LLC"}, + {1194, "LINKIOSAS"}, + {1195, "Harbortronics,Inc."}, + {1196, "UndagridB.V."}, + {1197, "ShureInc"}, + {1198, "ERMElectronicSystemsLTD"}, + {1199, "BIOROWERHandelsagenturGmbH"}, + {1200, "WebaSportundMed.ArtikelGmbH"}, + {1201, "KartographersTechnologiesPvt.Ltd."}, + {1202, "TheShadowontheMoon"}, + {1203, "mobike(HongKong)Limited"}, + {1204, "InuheatGroupAB"}, + {1205, "SwiftronixAB"}, + {1206, "DiagnopticsTechnologies"}, + {1207, "AnalogDevices,Inc."}, + {1208, "SoraaInc."}, + {1209, "CSRBuildingProductsLimited"}, + {1210, "CrestronElectronics,Inc."}, + {1211, "NeateboxLtd"}, + {1212, "DraegerwerkAG&Co.KGaA"}, + {1213, "AlbynMedical"}, + {1214, "AverosFZCO"}, + {1215, "VITInitiative,LLC"}, + {1216, "StatsportsInternational"}, + {1217, "Sospitas,s.r.o."}, + {1218, "DmetProductsCorp."}, + {1219, "MantracourtElectronicsLimited"}, + {1220, "TeAMHutchinsAB"}, + {1221, "SeibertWilliamsGlass,LLC"}, + {1222, "InstaGmbH"}, + {1223, "SvantekSp.zo.o."}, + {1224, "ShanghaiFlycoElectricalApplianceCo.,Ltd."}, + {1225, "ThornwaveLabsInc"}, + {1226, "Steiner-OptikGmbH"}, + {1227, "NovoNordiskA/S"}, + {1228, "EnfluxInc."}, + {1229, "SafetechProductsLLC"}, + {1230, "GOOOLEDS.R.L."}, + {1231, "DOMSicherheitstechnikGmbH&Co.KG"}, + {1232, "OlympusCorporation"}, + {1233, "KTSGmbH"}, + {1234, "AnloqTechnologiesInc."}, + {1235, "Queercon,Inc"}, + {1236, "5thElementLtd"}, + {1237, "GooeeLimited"}, + {1238, "LUGLOCLLC"}, + {1239, "Blincam,Inc."}, + {1240, "FUJIFILMCorporation"}, + {1241, "RandMcNally"}, + {1242, "FranceschiMarinasnc"}, + {1243, "EngineeredAudio,LLC."}, + {1244, "IOTTIVE(OPC)PRIVATELIMITED"}, + {1245, "4MODTechnology"}, + {1246, "LutronElectronicsCo.,Inc."}, + {1247, "Emerson"}, + {1248, "Guardtec,Inc."}, + {1249, "REACTECLIMITED"}, + {1250, "EllieGrid"}, + {1251, "UnderArmour"}, + {1252, "Woodenshark"}, + {1253, "AvackOy"}, + {1254, "SmartSolutionTechnology,Inc."}, + {1255, "REHABTRONICSINC."}, + {1256, "STABILOInternational"}, + {1257, "BuschJaegerElektroGmbH"}, + {1258, "PacificBioscienceLaboratories,Inc"}, + {1259, "BirdHomeAutomationGmbH"}, + {1260, "MotorolaSolutions"}, + {1261, "R9Technology,Inc."}, + {1262, "Auxivia"}, + {1263, "DaisyWorks,Inc"}, + {1264, "KosiLimited"}, + {1265, "ThebenAG"}, + {1266, "InDreamerTechsolPrivateLimited"}, + {1267, "CerevastMedical"}, + {1268, "ZanComputeInc."}, + {1269, "PirelliTyreS.P.A."}, + {1270, "McLearLimited"}, + {1271, "ShenzhenHuidingTechnologyCo.,Ltd."}, + {1272, "ConvergenceSystemsLimited"}, + {1273, "Interactio"}, + {1274, "AndrotecGmbH"}, + {1275, "BenchmarkDrivesGmbH&Co.KG"}, + {1276, "SwingLyncL.L.C."}, + {1277, "TapkeyGmbH"}, + {1278, "WoosimSystemsInc."}, + {1279, "MicrosemiCorporation"}, + {1280, "WiliotLTD."}, + {1281, "PolarisIND"}, + {1282, "Specifi-KaliLLC"}, + {1283, "Locoroll,Inc"}, + {1284, "PHYPLUSInc"}, + {1285, "InplayTechnologiesLLC"}, + {1286, "Hager"}, + {1287, "Yellowcog"}, + {1288, "AxesSystemsp.zo.o."}, + {1289, "myLIFTERInc."}, + {1290, "Shake-onB.V."}, + {1291, "VibrissaInc."}, + {1292, "OSRAMGmbH"}, + {1293, "TRSystemsGmbH"}, + {1294, "YichipMicroelectronics(Hangzhou)Co.,Ltd."}, + {1295, "FoundationEngineeringLLC"}, + {1296, "UNI-ELECTRONICS,INC."}, + {1297, "BrookfieldEquinoxLLC"}, + {1298, "SoprodSA"}, + {1299, "9974091CanadaInc."}, + {1300, "FIBROGmbH"}, + {1301, "RBControlsCo.,Ltd."}, + {1302, "Footmarks"}, + {1303, "AmtronicSverigeAB(formerlyAmcoreAB)"}, + {1304, "MAMORIO.inc"}, + {1305, "TytoLifeLLC"}, + {1306, "LeicaCameraAG"}, + {1307, "AngeeTechnologiesLtd."}, + {1308, "EDPS"}, + {1309, "OFFLineCo.,Ltd."}, + {1310, "DetectBlueLimited"}, + {1311, "SetecPtyLtd"}, + {1312, "TargetCorporation"}, + {1313, "IAICorporation"}, + {1314, "NSTech,Inc."}, + {1315, "MTGCo.,Ltd."}, + {1316, "HangzhouiMagicTechnologyCo.,Ltd"}, + {1317, "HONGKONGNANOICTECHNOLOGIESCO.,LIMITED"}, + {1318, "HoneywellInternationalInc."}, + {1319, "AlbrechtJUNG"}, + {1320, "LuneraLightingInc."}, + {1321, "LumenUAB"}, + {1322, "KeynesControlsLtd"}, + {1323, "NovartisAG"}, + {1324, "GeosatisSA"}, + {1325, "EXFO,Inc."}, + {1326, "LEDVANCEGmbH"}, + {1327, "CenterIDCorp."}, + {1328, "Adolene,Inc."}, + {1329, "D&MHoldingsInc."}, + {1330, "CRESCOWireless,Inc."}, + {1331, "NuraOperationsPtyLtd"}, + {1332, "Frontiergadget,Inc."}, + {1333, "SmartComponentTechnologiesLimited"}, + {1334, "ZTRControlSystemsLLC"}, + {1335, "MetaLogicsCorporation"}, + {1336, "MedelaAG"}, + {1337, "OPPLELightingCo.,Ltd"}, + {1338, "SavitechCorp.,"}, + {1339, "prodigy"}, + {1340, "ScreenovateTechnologiesLtd"}, + {1341, "TESASA"}, + {1342, "CLIM8LIMITED"}, + {1343, "SilergyCorp"}, + {1344, "SilverPlus,Inc"}, + {1345, "Sharknetsrl"}, + {1346, "MistSystems,Inc."}, + {1347, "MIWALOCKCO.,Ltd"}, + {1348, "OrthoSensor,Inc."}, + {1349, "CandyHooverGroups.r.l"}, + {1350, "ApexarTechnologiesS.A."}, + {1351, "LOGICDATAd.o.o."}, + {1352, "KnickElektronischeMessgeraeteGmbH&Co.KG"}, + {1353, "SmartTechnologiesandInvestmentLimited"}, + {1354, "LinoughInc."}, + {1355, "AdvancedElectronicDesigns,Inc."}, + {1356, "CarefreeScottFetzerCoInc"}, + {1357, "Sensome"}, + {1358, "FORTRONIKstoritved.o.o."}, + {1359, "Sinnoz"}, + {1360, "VersaNetworks,Inc."}, + {1361, "Sylero"}, + {1362, "AvempaceSARL"}, + {1363, "NintendoCo.,Ltd."}, + {1364, "NationalInstruments"}, + {1365, "KROHNEMesstechnikGmbH"}, + {1366, "OtodynamicsLtd"}, + {1367, "ArwinTechnologyLimited"}, + {1368, "benegear,inc."}, + {1369, "NewconOptik"}, + {1370, "CANDYHOUSE,Inc."}, + {1371, "FRANKLINTECHNOLOGYINC"}, + {1372, "Lely"}, + {1373, "ValveCorporation"}, + {1374, "HekatronVertriebsGmbH"}, + {1375, "PROTECHS.A.S.DIGIRARDIANDREA&C."}, + {1376, "SaritaCareTechAPS(formerlySaritaCareTechIVS)"}, + {1377, "FinderS.p.A."}, + {1378, "ThalmicLabsInc."}, + {1379, "SteinelVertriebGmbH"}, + {1380, "BeghelliSpa"}, + {1381, "BeijingSmartspaceTechnologiesInc."}, + {1382, "CORETRANSPORTTECHNOLOGIESNZLIMITED"}, + {1383, "XiamenEveresportsGoodsCo.,Ltd"}, + {1384, "BodyportInc."}, + {1385, "AudionicsSystem,INC."}, + {1386, "FlipnaviCo.,Ltd."}, + {1387, "RionCo.,Ltd."}, + {1388, "LongRangeSystems,LLC"}, + {1389, "RedmondIndustrialGroupLLC"}, + {1390, "VIZPININC."}, + {1391, "BikeFinderAS"}, + {1392, "ConsumerSleepSolutionsLLC"}, + {1393, "PSIKICK,INC."}, + {1394, "AntTail.com"}, + {1395, "LightingScienceGroupCorp."}, + {1396, "AFFORDABLEELECTRONICSINC"}, + {1397, "IntegralMemroyPlc"}, + {1398, "Globalstar,Inc."}, + {1399, "TrueWearables,Inc."}, + {1400, "WellingtonDriveTechnologiesLtd"}, + {1401, "EnsembleTechPrivateLimited"}, + {1402, "OMNIRemotes"}, + {1403, "DuracellU.S.OperationsInc."}, + {1404, "ToorTechnologiesLLC"}, + {1405, "InstinctPerformance"}, + {1406, "Beco,Inc"}, + {1407, "ScufGamingInternational,LLC"}, + {1408, "ARANZMedicalLimited"}, + {1409, "LYSTECHNOLOGIESLTD"}, + {1410, "BreakwallAnalytics,LLC"}, + {1411, "CodeBlueCommunications"}, + {1412, "GiraGiersiepenGmbH&Co.KG"}, + {1413, "HearingLabTechnology"}, + {1414, "LEGRAND"}, + {1415, "DerichsGmbH"}, + {1416, "ALT-TEKNIKLLC"}, + {1417, "StarTechnologies"}, + {1418, "STARTTODAYCO.,LTD."}, + {1419, "MaximIntegratedProducts"}, + {1420, "MERCKKommanditgesellschaftaufAktien"}, + {1421, "JungheinrichAktiengesellschaft"}, + {1422, "OculusVR,LLC"}, + {1423, "HENDONSEMICONDUCTORSPTYLTD"}, + {1424, "Pur3Ltd"}, + {1425, "ViasatGroupS.p.A."}, + {1426, "IZITHERM"}, + {1427, "SpauldingClinicalResearch"}, + {1428, "KohlerCompany"}, + {1429, "InorProcessAB"}, + {1430, "MySmartBlinds"}, + {1431, "RadioPulseInc"}, + {1432, "rapitagGmbH"}, + {1433, "Lazlo326,LLC."}, + {1434, "TeledyneLecroy,Inc."}, + {1435, "DataflowSystemsLimited"}, + {1436, "MacrogigaElectronics"}, + {1437, "TandemDiabetesCare"}, + {1438, "Polycom,Inc."}, + {1439, "Fisher&PaykelHealthcare"}, + {1440, "RCPSoftwareOy"}, + {1441, "ShanghaiXiaoyiTechnologyCo.,Ltd."}, + {1442, "ADHERIUM(NZ)LIMITED"}, + {1443, "AxiomwareSystemsIncorporated"}, + {1444, "O.E.M.Controls,Inc."}, + {1445, "KiirooBV"}, + {1446, "TeleconMobileLimited"}, + {1447, "SonosInc"}, + {1448, "TomAllebrandiConsulting"}, + {1449, "Monidor"}, + {1450, "TramexLimited"}, + {1451, "NofenceAS"}, + {1452, "GoerTekDynaudioCo.,Ltd."}, + {1453, "INIA"}, + {1454, "CARMATEMFG.CO.,LTD"}, + {1455, "ONvocal"}, + {1456, "NewTecGmbH"}, + {1457, "MedallionInstrumentationSystems"}, + {1458, "CARELINDUSTRIESS.P.A."}, + {1459, "ParabitSystems,Inc."}, + {1460, "WhiteHorseScientificltd"}, + {1461, "verisilicon"}, + {1462, "ElecsIndustryCo.,Ltd."}, + {1463, "BeijingPineconeElectronicsCo.,Ltd."}, + {1464, "AmbystomaLabsInc."}, + {1465, "SuzhouPairlinkNetworkTechnology"}, + {1466, "igloohome"}, + {1467, "OxfordMetricsplc"}, + {1468, "LevitonMfg.Co.,Inc."}, + {1469, "ULCRoboticsInc."}, + {1470, "RFIDGlobalbySoftworkSrL"}, + {1471, "Real-World-SystemsCorporation"}, + {1472, "NaluMedical,Inc."}, + {1473, "P.I.Engineering"}, + {1474, "GroteIndustries"}, + {1475, "Runtime,Inc."}, + {1476, "Codecoupsp.zo.o.sp.k."}, + {1477, "SELVEGmbH&Co.KG"}, + {1478, "SmartAnimalTrainingSystems,LLC"}, + {1479, "LippertComponents,INC"}, + {1480, "SOMFYSAS"}, + {1481, "TBSElectronicsB.V."}, + {1482, "MHLCustomInc"}, + {1483, "LucentWearLLC"}, + {1484, "WATTSELECTRONICS"}, + {1485, "RJBrandsLLC"}, + {1486, "V-ZUGLtd"}, + {1487, "BiowatchSA"}, + {1488, "AnovaAppliedElectronics"}, + {1489, "LindabAB"}, + {1490, "frogblueTECHNOLOGYGmbH"}, + {1491, "AcurableLimited"}, + {1492, "LAMPLIGHTCo.,Ltd."}, + {1493, "TEGAM,Inc."}, + {1494, "ZhuhaiJielitechnologyCo.,Ltd"}, + {1495, "modum.ioAG"}, + {1496, "FarmJennyLLC"}, + {1497, "ToyoElectronicsCorporation"}, + {1498, "AppliedNeuralResearchCorp"}, + {1499, "AvidIdentificationSystems,Inc."}, + {1500, "PetronicsInc."}, + {1501, "essentimGmbH"}, + {1502, "QTMedicalINC."}, + {1503, "VIRTUALCLINIC.DIRECTLIMITED"}, + {1504, "ViperDesignLLC"}, + {1505, "Human,Incorporated"}, + {1506, "stAPPtronicsGmbH"}, + {1507, "ElementalMachines,Inc."}, + {1508, "TaiyoYudenCo.,Ltd"}, + {1509, "INEOENERGY&SYSTEMS"}, + {1510, "MotionInstrumentsInc."}, + {1511, "PressurePro"}, + {1512, "COWBOY"}, + {1513, "iconmobileGmbH"}, + {1514, "ACS-Control-SystemGmbH"}, + {1515, "BayerischeMotorenWerkeAG"}, + {1516, "GycomSvenskaAB"}, + {1517, "FujiXeroxCo.,Ltd"}, + {1518, "GlideInc."}, + {1519, "SIKOMAS"}, + {1520, "beken"}, + {1521, "TheLinuxFoundation"}, + {1522, "TryandECO.,LTD."}, + {1523, "SeeScan"}, + {1524, "Clearity,LLC"}, + {1525, "GSTAG"}, + {1526, "DPTechnics"}, + {1527, "TRACMO,INC."}, + {1528, "AnkiInc."}, + {1529, "HagleitnerHygieneInternationalGmbH"}, + {1530, "KonamiSportsLifeCo.,Ltd."}, + {1531, "ArbletInc."}, + {1532, "MasbandoGmbH"}, + {1533, "Innoseis"}, + {1534, "Niko"}, + {1535, "WellnomicsLtd"}, + {1536, "iRobotCorporation"}, + {1537, "SchraderElectronics"}, + {1538, "GeberitInternationalAG"}, + {1539, "FourthEvolutionInc"}, + {1540, "Cell2JackLLC"}, + {1541, "FMWelectronicFuttereru.Maier-WolfOHG"}, + {1542, "JohnDeere"}, + {1543, "RookeryTechnologyLtd"}, + {1544, "KeySafe-Cloud"}, + {1545, "BUCHILabortechnikAG"}, + {1546, "IQAirAG"}, + {1547, "TriaxTechnologiesInc"}, + {1548, "VuzixCorporation"}, + {1549, "TDKCorporation"}, + {1550, "BlueairAB"}, + {1551, "SignifyNetherlands"}, + {1552, "ADHGUARDIANUSALLC"}, + {1553, "BeurerGmbH"}, + {1554, "PlayfinityAS"}, + {1555, "HansDinslageGmbH"}, + {1556, "OnAssetIntelligence,Inc."}, + {1557, "INTERACTIONCorporation"}, + {1558, "OS42UG(haftungsbeschraenkt)"}, + {1559, "WIZCONNECTEDCOMPANYLIMITED"}, + {1560, "Audio-TechnicaCorporation"}, + {1561, "SixGuysLabs,s.r.o."}, + {1562, "R.W.BeckettCorporation"}, + {1563, "silextechnology,inc."}, + {1564, "UnivationsLimited"}, + {1565, "SENSInnovationApS"}, + {1566, "DiamondKinetics,Inc."}, + {1567, "PhrameInc."}, + {1568, "ForciotOy"}, + {1569, "Noordungd.o.o."}, + {1570, "BeamLabs,LLC"}, + {1571, "PhiladelphiaScientific(U.K.)Limited"}, + {1572, "BiovotionAG"}, + {1573, "SquarePanda,Inc."}, + {1574, "Amplifico"}, + {1575, "WEGS.A."}, + {1576, "EnstoOy"}, + {1577, "PHONEPEPVTLTD"}, + {1578, "LunaticoAstronomiaSL"}, + {1579, "MinebeaMitsumiInc."}, + {1580, "ASPionGmbH"}, + {1581, "Vossloh-SchwabeDeutschlandGmbH"}, + {1582, "Procept"}, + {1583, "ONKYOCorporation"}, + {1584, "AsthreaD.O.O."}, + {1585, "FortioriDesignLLC"}, + {1586, "HugoMullerGmbH&CoKG"}, + {1587, "WangiLaiPLT"}, + {1588, "FanstelCorp"}, + {1589, "Crookwood"}, + {1590, "ELECTRONICAINTEGRALDESONIDOS.A."}, + {1591, "GiPInnovationToolsGmbH"}, + {1592, "LXSOLUTIONSPTYLIMITED"}, + {1593, "ShenzhenMinewTechnologiesCo.,Ltd."}, + {1594, "ProlojikLimited"}, + {1595, "KromekGroupPlc"}, + {1596, "ContecMedicalSystemsCo.,Ltd."}, + {1597, "XradioTechnologyCo.,Ltd."}, + {1598, "TheIndoorLab,LLC"}, + {1599, "LDLTECHNOLOGY"}, + {1600, "Parkifi"}, + {1601, "RevenueCollectionSystemsFRANCESAS"}, + {1602, "BluetrumTechnologyCo.,Ltd"}, + {1603, "makitacorporation"}, + {1604, "ApogeeInstruments"}, + {1605, "BM3"}, + {1606, "SGVGroupHoldingGmbH&Co.KG"}, + {1607, "MED-EL"}, + {1608, "UltuneTechnologies"}, + {1609, "RyeexTechnologyCo.,Ltd."}, + {1610, "OpenResearchInstitute,Inc."}, + {1611, "Scale-Tec,Ltd"}, + {1612, "ZumtobelGroupAG"}, + {1613, "iLOQOy"}, + {1614, "KRUXWorksTechnologiesPrivateLimited"}, + {1615, "DigitalMatterPtyLtd"}, + {1616, "Coravin,Inc."}, + {1617, "StasisLabs,Inc."}, + {1618, "ITZInnovations-undTechnologiezentrumGmbH"}, + {1619, "MeggittSA"}, + {1620, "LedlenserGmbH&Co.KG"}, + {1621, "RenishawPLC"}, + {1622, "ZhuHaiAdvanProTechnologyCompanyLimited"}, + {1623, "MeshtronixLimited"}, + {1624, "PayexNorgeAS"}, + {1625, "UnSeenTechnologiesOy"}, + {1626, "ZoundIndustriesInternationalAB"}, + {1627, "SesamSolutionsBV"}, + {1628, "PixArtImagingInc."}, + {1629, "PanduitCorp."}, + {1630, "AloAB"}, + {1631, "RicohCompanyLtd"}, + {1632, "RTCIndustries,Inc."}, + {1633, "ModeLightingLimited"}, + {1634, "ParticleIndustries,Inc."}, + {1635, "AdvancedTelemetrySystems,Inc."}, + {1636, "RHATECHNOLOGIESLTD"}, + {1637, "PureInternationalLimited"}, + {1638, "WTOWerkzeug-EinrichtungenGmbH"}, + {1639, "SparkTechnologyLabsInc."}, + {1640, "BlebTechnologysrl"}, + {1641, "LivanovaUSA,Inc."}, + {1642, "BradyWorldwideInc."}, + {1643, "DewertOkinGmbH"}, + {1644, "ZtoveApS"}, + {1645, "VensoEcoSolutionsAB"}, + {1646, "EurotronikKranjd.o.o."}, + {1647, "HugTechnologyLtd"}, + {1648, "GemaSwitzerlandGmbH"}, + {1649, "BuzzProductsLtd."}, + {1650, "Kopi"}, + {1651, "InnovaIdeasLimited"}, + {1652, "BeSpoon"}, + {1653, "DecoEnterprises,Inc."}, + {1654, "ExpaiSolutionsPrivateLimited"}, + {1655, "InnovationFirst,Inc."}, + {1656, "SABIKOffshoreGmbH"}, + {1657, "4iiiiInnovationsInc."}, + {1658, "TheEnergyConservatory,Inc."}, + {1659, "I.FARM,INC."}, + {1660, "Tile,Inc."}, + {1661, "FormAthleticaInc."}, + {1662, "MbientLabInc"}, + {1663, "NETGRIDS.N.C.DIBISSOLIMATTEO,CAMPOREALESIMONE,TOGNETTIFEDERICO"}, + {1664, "MannkindCorporation"}, + {1665, "TradeFIDESa.s."}, + {1666, "PhotronLimited"}, + {1667, "EltakoGmbH"}, + {1668, "Dermalapps,LLC"}, + {1669, "GreenwaldIndustries"}, + {1670, "inQsCo.,Ltd."}, + {1671, "CherryGmbH"}, + {1672, "AmstedDigitalSolutionsInc."}, + {1673, "Tacxb.v."}, + {1674, "RaytacCorporation"}, + {1675, "JiangsuTeranovoTechCo.,Ltd."}, + {1676, "ChangzhouSoundDragonElectronicsandAcousticsCo.,Ltd"}, + {1677, "JetBeepInc."}, + {1678, "RazerInc."}, + {1679, "JRMGroupLimited"}, + {1680, "EccrineSystems,Inc."}, + {1681, "CuriePointAB"}, + {1682, "GeorgFischerAG"}, + {1683, "Hach-Danaher"}, + {1684, "T&ALaboratoriesLLC"}, + {1685, "KokiHoldingsCo.,Ltd."}, + {1686, "GunakarPrivateLimited"}, + {1687, "StemcoProductsInc"}, + {1688, "WoodITSecurity,LLC"}, + {1689, "RandomLabSAS"}, + {1690, "Adero,Inc.(formerlyasTrackR,Inc.)"}, + {1691, "DragonchipLimited"}, + {1692, "NoomiAB"}, + {1693, "VakarosLLC"}, + {1694, "DeltaElectronics,Inc."}, + {1695, "FlowMotionTechnologiesAS"}, + {1696, "OBIQLocationTechnologyInc."}, + {1697, "CardoSystems,Ltd"}, + {1698, "GlobalworxGmbH"}, + {1699, "Nymbus,LLC"}, + {1700, "SanyoTechnoSolutionsTottoriCo.,Ltd."}, + {1701, "TEKZITELPTYLTD"}, + {1702, "RoambeeCorporation"}, + {1703, "ChipseaTechnologies(ShenZhen)Corp."}, + {1704, "GDMideaAir-ConditioningEquipmentCo.,Ltd."}, + {1705, "SoundmaxElectronicsLimited"}, + {1706, "ProdualOy"}, + {1707, "HMSIndustrialNetworksAB"}, + {1708, "IngchipsTechnologyCo.,Ltd."}, + {1709, "InnovaSeaSystemsInc."}, + {1710, "SenseQInc."}, + {1711, "ShoofTechnologies"}, + {1712, "BRKBrands,Inc."}, + {1713, "SimpliSafe,Inc."}, + {1714, "TussockInnovation2013Limited"}, + {1715, "TheHablabApS"}, + {1716, "SencilionOy"}, + {1717, "WabilogicLtd."}, + {1718, "SociometricSolutions,Inc."}, + {1719, "iCOGNIZEGmbH"}, + {1720, "ShadeCraft,Inc"}, + {1721, "BeflexInc."}, + {1722, "BeaconzoneLtd"}, + {1723, "LeaftronixAnalogicSolutionsPrivateLimited"}, + {1724, "TWSSrl"}, + {1725, "ABBOy"}, + {1726, "HitSeedOy"}, + {1727, "DelcomProductsInc."}, + {1728, "CAMES.p.A."}, + {1729, "Alarm.comHoldings,Inc"}, + {1730, "MeasurlogicInc."}, + {1731, "KingIElectronics.Co.,Ltd"}, + {1732, "DreamLabsGmbH"}, + {1733, "UrbanCompass,Inc"}, + {1734, "SimmTronicLimited"}, + {1735, "SomatixInc"}, + {1736, "Storz&BickelGmbH&Co.KG"}, + {1737, "MYLAPSB.V."}, + {1738, "ShenzhenZhongguangInfotechTechnologyDevelopmentCo.,Ltd"}, + {1739, "Dyeware,LLC"}, + {1740, "DongguanSmartActionTechnologyCo.,Ltd."}, + {1741, "DIGCorporation"}, + {1742, "FIOR&GENTZ"}, + {1743, "BelpartsN.V."}, + {1744, "EtekcityCorporation"}, + {1745, "MeyerSoundLaboratories,Incorporated"}, + {1746, "CeoTronicsAG"}, + {1747, "TriTeqLockandSecurity,LLC"}, + {1748, "DYNAKODETECHNOLOGYPRIVATELIMITED"}, + {1749, "SensirionAG"}, + {1750, "JCTHealthcarePtyLtd"}, + {1751, "FUBAAutomotiveElectronicsGmbH"}, + {1752, "AWCompany"}, + {1753, "ShanghaiMountainViewSiliconCo.,Ltd."}, + {1754, "ZliideTechnologiesApS"}, + {1755, "AutomaticLabs,Inc."}, + {1756, "IndustrialNetworkControls,LLC"}, + {1757, "IntellithingsLtd."}, + {1758, "Navcast,Inc."}, + {1759, "HubbellLighting,Inc."}, + {1760, "Avaya"}, + {1761, "MilestoneAVTechnologiesLLC"}, + {1762, "AlangoTechnologiesLtd"}, + {1763, "SpinlockLtd"}, + {1764, "Aluna"}, + {1765, "OPTEXCO.,LTD."}, + {1766, "NIHONDENGYOKOUSAKU"}, + {1767, "VELUXA/S"}, + {1768, "AlmendoTechnologiesGmbH"}, + {1769, "ZmartfunElectronics,Inc."}, + {1770, "SafeLineSwedenAB"}, + {1771, "HoustonRadarLLC"}, + {1772, "Sigur"}, + {1773, "JNeadesLtd"}, + {1774, "AvantisSystemsLimited"}, + {1775, "ALCARECo.,Ltd."}, + {1776, "ChargyTechnologies,SL"}, + {1777, "ShibutaniCo.,Ltd."}, + {1778, "TrapperDataAB"}, + {1779, "AlfredInternationalInc."}, + {1780, "NearFieldSolutionsLtd"}, + {1781, "VigilTechnologiesInc."}, + {1782, "VituloPlusBV"}, + {1783, "WILKASchliesstechnikGmbH"}, + {1784, "BodyPlusTechnologyCo.,Ltd"}, + {1785, "happybrushGmbH"}, + {1786, "EnequiAB"}, + {1787, "SartoriusAG"}, + {1788, "TomCommunicationIndustrialCo.,Ltd."}, + {1789, "ESSEmbeddedSystemSolutionsInc."}, + {1790, "MahrGmbH"}, + {1791, "RedpineSignalsInc"}, + {1792, "TraqFreqLLC"}, + {1793, "PAFERSTECH"}, + {1794, "Akcijusabiedriba\"SAFTEHNIKA\""}, + {1795, "BeijingJingdongCenturyTradingCo.,Ltd."}, + {1796, "JBXDesignsInc."}, + {1797, "ABElectrolux"}, + {1798, "WernhervonBraunCenterforASdvancedResearch"}, + {1799, "EssityHygieneandHealthAktiebolag"}, + {1800, "BeInteractiveCo.,Ltd"}, + {1801, "CarewearCorp."}, + {1802, "HufHlsbeck&FrstGmbH&Co.KG"}, + {1803, "ElementProducts,Inc."}, + {1804, "BeijingWinnerMicroelectronicsCo.,Ltd"}, + {1805, "SmartSnuggPtyLtd"}, + {1806, "FiveCoSarl"}, + {1807, "CaliforniaThingsInc."}, + {1808, "AudiodoAB"}, + {1809, "ABAXAS"}, + {1810, "BullGroupCompanyLimited"}, + {1811, "RespiriLimited"}, + {1812, "MindPeaceSafetyLLC"}, + {1813, "VgyanSolutions"}, + {1814, "Altonics"}, + {1815, "iQsquareBV"}, + {1816, "IDIBAIXenginneering"}, + {1817, "ECSG"}, + {1818, "REVSMARTWEARABLEHKCOLTD"}, + {1819, "Precor"}, + {1820, "F5Sports,Inc"}, + /* 1821 - 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, "extended features 64-67"}, + {2, "extended features 128-140"}, + /* 3 - 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; +static gint ett_lmp_features = -1; +static gint ett_lmp_featuresext = -1; + +/* LMP PDUs with short opcodes */ +void dissect_vsc(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + /* TODO implement Broadcom VSC opcodes here: + * 0: Features Request + * 1: Features Response + * 0 and 1: Features: 0x%02X%02X%02X%02X + * 2: Not Accept + * Rejection BPCS Opcode: 0x%02X + * Rejection Error Code: 0x%02X + * 3: BFC Suspend + * 4: BFC Resume Request + * if receive direction: + * BFC Resume Response (instead) + * BFC Link State: 0x%02X + * BFC Stack State: 0x%02X + * BFC Reserved: 0x%02X\ + * 5: BFC Accept + * BPCS Accepted Opcode: 0x%02X + * + */ +} + +void dissect_name_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 2); + DISSECTOR_ASSERT(tvb_reported_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); + + 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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_length_remaining(tvb, offset) >= 1); + proto_tree_add_item(tree, hf_lmp_keysz, tvb, offset, 1, ENC_LITTLE_ENDIAN); + int ret = tvb_get_guint8(tvb, offset); + DISSECTOR_ASSERT(ret >= 7); +} + +void dissect_start_encryption_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 17); + DISSECTOR_ASSERT(tvb_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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; + + DISSECTOR_ASSERT(tvb_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_length_remaining(tvb, offset) >= 8); + + proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_features, + ett_lmp_features, features_fields, ENC_LITTLE_ENDIAN); +} + +void dissect_features_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 9); + DISSECTOR_ASSERT(tvb_reported_length_remaining(tvb, offset) >= 8); + + proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_features, + ett_lmp_features, features_fields, ENC_LITTLE_ENDIAN); +} + +void dissect_quality_of_service(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 4); + DISSECTOR_ASSERT(tvb_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_length_remaining(tvb, offset) >= 9); + + proto_tree_add_uint(tree, hf_lmp_testscen, tvb, offset, 1, tvb_get_guint8(tvb, offset) ^ 0x55); + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_hopmode, tvb, offset, 1, tvb_get_guint8(tvb, offset) ^ 0x55); + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_txfreq, tvb, offset, 1, (tvb_get_guint8(tvb, offset) ^ 0x55) + 2402); //MHz + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_rxfreq, tvb, offset, 1, (tvb_get_guint8(tvb, offset) ^ 0x55) + 2402); + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_pcmode, tvb, offset, 1, tvb_get_guint8(tvb, offset) ^ 0x55); + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_pollper, tvb, offset, 1, (tvb_get_guint8(tvb, offset) ^ 0x55) * 1.25); //ms + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_pkttype, tvb, offset, 1, tvb_get_guint8(tvb, offset) ^ 0x55); + offset += 1; + + proto_tree_add_uint(tree, hf_lmp_testlen, tvb, offset, 2, tvb_get_bits16(tvb, offset * 8, 16, ENC_LITTLE_ENDIAN) ^ 0x5555); +} + +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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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 == 5); + DISSECTOR_ASSERT(tvb_reported_length_remaining(tvb, offset) >= 3); + + 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) +{ + int feat_page = 0; + + DISSECTOR_ASSERT(len == 12); + DISSECTOR_ASSERT(tvb_reported_length_remaining(tvb, offset) >= 10); + + proto_tree_add_item(tree, hf_lmp_fpage, tvb, offset, 1, ENC_LITTLE_ENDIAN); + feat_page = tvb_get_guint8(tvb, offset); + offset += 1; + + proto_tree_add_item(tree, hf_lmp_maxsp, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + if (feat_page == 1) + { + proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_featuresext, + ett_lmp_featuresext, extfeatures1_fields, ENC_LITTLE_ENDIAN); + } + else + { + proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_featuresext, + ett_lmp_featuresext, extfeatures2_fields, ENC_LITTLE_ENDIAN); + } +} + +void dissect_features_res_ext(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + int feat_page = 0; + DISSECTOR_ASSERT(len == 12); + DISSECTOR_ASSERT(tvb_reported_length_remaining(tvb, offset) >= 10); + + proto_tree_add_item(tree, hf_lmp_fpage, tvb, offset, 1, ENC_LITTLE_ENDIAN); + feat_page = tvb_get_guint8(tvb, offset); + offset += 1; + + proto_tree_add_item(tree, hf_lmp_maxsp, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + if (feat_page == 1) + { + proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_featuresext, + ett_lmp_featuresext, extfeatures1_fields, ENC_LITTLE_ENDIAN); + } + else + { + proto_tree_add_bitmask(tree, tvb, offset, hf_lmp_featuresext, + ett_lmp_featuresext, extfeatures2_fields, ENC_LITTLE_ENDIAN); + } +} + +void dissect_packet_type_table_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 3); + DISSECTOR_ASSERT(tvb_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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_reported_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); +} + +void dissect_ping_req(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 2); +} + +void dissect_ping_res(proto_tree *tree, tvbuff_t *tvb, int offset, int len) +{ + DISSECTOR_ASSERT(len == 2); +} + +/* Link Manager Protocol */ +static int +dissect_btbrlmp(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 */ + + // struct timespec start_time; + // struct timespec end_time; + // clock_gettime(CLOCK_MONOTONIC, &start_time); + + offset = 0; + len = tvb_reported_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); + // printf("pinfo->p2p_dir:%d\n",pinfo->p2p_dir); + switch (pinfo->p2p_dir) + { + case P2P_DIR_SENT: + col_set_str(pinfo->cinfo, COL_INFO, "TX --> "); + break; + case P2P_DIR_RECV: + col_set_str(pinfo->cinfo, COL_INFO, "RX <-- "); + break; + default: + break; + } + + op = tvb_get_guint8(tvb, offset) >> 1; + + if (op == LMP_ESCAPE_4) + { + DISSECTOR_ASSERT(len >= 2); + + eop = tvb_get_guint8(tvb, offset + 1); + + col_append_str(pinfo->cinfo, COL_INFO, val_to_str(eop, ext_opcode, "Unknown Extended Opcode (%d)")); + } + else + { + col_append_str(pinfo->cinfo, COL_INFO, val_to_str(op, opcode, "Unknown Opcode (%d)")); + } + + /* see if we are being asked for details */ + if (!tree) + return tvb_reported_length(tvb); + + lmp_item = proto_tree_add_item(tree, proto_btbrlmp, 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; + /* + If the initial 7 bits + of the opcode have one of the special escape values 124-127 then an + additional byte of opcode is located in the second byte of the payload + */ + 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; + case LMP_PING_REQ: + dissect_ping_req(lmp_tree, tvb, offset, len); + break; + case LMP_PING_RES: + dissect_ping_res(lmp_tree, tvb, offset, len); + break; + default: + break; + } + default: + break; + } + + // clock_gettime(CLOCK_MONOTONIC, &end_time); + // long measured_latency_ns = ((end_time.tv_sec - start_time.tv_sec) * 1000000000UL) + (end_time.tv_nsec - start_time.tv_nsec) / 1000; + // printf("lmp=%ld\n", measured_latency_ns); + + /* Return the amount of data this dissector was able to dissect */ + return tvb_reported_length(tvb); +}; + +/* register the protocol with Wireshark */ +void proto_register_btbrlmp(void) +{ + + /* list of fields */ + static hf_register_info hf[] = { + {&hf_lmp_accscheme, + {"Access Scheme", "btbrlmp.accscheme", + FT_UINT8, BASE_DEC, VALS(access_scheme), 0xf0, + NULL, HFILL}}, + {&hf_lmp_afhchmap, + {"AFH Channel Map", "btbrlmp.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", "btbrlmp.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", "btbrlmp.afhinst", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Adaptive Frequency Hopping Instant (slot)", HFILL}}, + {&hf_lmp_afhmaxintvl, + {"AFH Max Interval", "btbrlmp.maxintvl", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Adaptive Maximum Interval in slots", HFILL}}, + {&hf_lmp_afhminintvl, + {"AFH Min Interval", "btbrlmp.minintvl", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Adaptive Minimum Interval in slots", HFILL}}, + {&hf_lmp_afhmode, + {"AFH Mode", "btbrlmp.afhmode", + FT_UINT8, BASE_DEC, VALS(afh_mode), 0x0, + "Adaptive Frequency Hopping Mode", HFILL}}, + {&hf_lmp_afhrptmode, + {"AFH Reporting Mode", "btbrlmp.afhrptmode", + FT_UINT8, BASE_DEC, VALS(afh_reporting_mode), 0x0, + "Adaptive Frequency Hopping Reporting Mode", HFILL}}, + {&hf_lmp_airmode, + {"Air Mode", "btbrlmp.airmode", + FT_UINT8, BASE_HEX, VALS(air_mode), 0x0, + NULL, HFILL}}, + {&hf_lmp_araddr, + {"AR_ADDR", "btbrlmp.araddr", + FT_UINT8, BASE_HEX, NULL, 0xfe, + NULL, HFILL}}, + {&hf_lmp_authreqs, + {"Authentication Requirements", "btbrlmp.authreqs", + FT_UINT8, BASE_HEX, VALS(auth_requirements), 0x00, + NULL, HFILL}}, + {&hf_lmp_authres, + {"Authentication Response", "btbrlmp.authres", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_bdaddr, + {"BD_ADDR", "btbrlmp.bdaddr", + FT_UINT64, BASE_HEX, NULL, 0x0000ffffffffffff, + NULL, HFILL}}, + {&hf_lmp_bdaddr1, + {"BD_ADDR 1", "btbrlmp.bdaddr", + FT_UINT64, BASE_HEX, NULL, 0x0000ffffffffffff, + NULL, HFILL}}, + {&hf_lmp_bdaddr2, + {"BD_ADDR2", "btbrlmp.bdaddr", + FT_UINT64, BASE_HEX, NULL, 0x0000ffffffffffff, + "BD_ADDR 2", HFILL}}, + {&hf_lmp_bsw, + {"Broadcast Scan Window", "btbrlmp.bsw", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Broadcast Scan Window in slots", HFILL}}, + {&hf_lmp_clkoffset, + {"Clock Offset", "btbrlmp.clkoffset", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Clock Offset in units of 1.25 ms", HFILL}}, + {&hf_lmp_commit, + {"Commitment Value", "btbrlmp.commit", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_confirm, + {"Confirmation Value", "btbrlmp.confirm", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_compid, + {"Company ID", "btbrlmp.compid", + FT_UINT16, BASE_DEC, VALS(compid), 0x0, + NULL, HFILL}}, + {&hf_lmp_cryptmode, + {"Encryption Mode", "btbrlmp.cryptmode", + FT_UINT8, BASE_DEC, VALS(encryption_mode), 0x0, + NULL, HFILL}}, + {&hf_lmp_daccess, + {"Daccess", "btbrlmp.daccess", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Daccess in slots", HFILL}}, + {&hf_lmp_db, + {"Db", "btbrlmp.db", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Db in slots", HFILL}}, + {&hf_lmp_dbsleep, + {"Dbsleep", "btbrlmp.dbsleep", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_deltab, + {"Deltab", "btbrlmp.deltab", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Deltab in slots", HFILL}}, + {&hf_lmp_desco, + {"Desco", "btbrlmp.desco", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Desco in slots", HFILL}}, + {&hf_lmp_drift, + {"Drift", "btbrlmp.drift", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Drift in ppm", HFILL}}, + {&hf_lmp_dsco, + {"Dsco", "btbrlmp.dsco", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Dsco in slots", HFILL}}, + {&hf_lmp_dsniff, + {"Dsniff", "btbrlmp.dsniff", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Dsniff in slots", HFILL}}, + {&hf_lmp_encdata, + {"Encapsulated Data", "btbrlmp.encdata", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_enclen, + {"Encapsulated Length", "btbrlmp.enclen", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_encmaj, + {"Encapsulated Major Type", "btbrlmp.encmaj", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_encmin, + {"Encapsulated Minor Type", "btbrlmp.encmin", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_eop, + {"Extended Opcode", "btbrlmp.eop", + FT_UINT8, BASE_DEC, VALS(ext_opcode), 0x0, + NULL, HFILL}}, + {&hf_lmp_eopinre, + {"In Response To", "btbrlmp.eopinre", + FT_UINT8, BASE_DEC, VALS(ext_opcode), 0x0, + "Extended Opcode this is in response to", HFILL}}, + {&hf_lmp_escolenms, + {"Packet Length M -> S", "btbrlmp.escolenms", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Packet Length in bytes Master to Slave", HFILL}}, + {&hf_lmp_escolensm, + {"Packet Length S -> M", "btbrlmp.escolensm", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Packet Length in bytes Slave to Master", HFILL}}, + {&hf_lmp_escotypems, + {"eSCO Packet Type M -> S", "btbrlmp.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", "btbrlmp.escotypesm", + FT_UINT8, BASE_HEX, VALS(esco_packet_type), 0x0, + "eSCO Packet Type Slave to Master", HFILL}}, + {&hf_lmp_err, + {"Error Code", "btbrlmp.err", + FT_UINT8, BASE_HEX, VALS(error_code), 0x0, + NULL, HFILL}}, + {&hf_lmp_escohdl, + {"eSCO Handle", "btbrlmp.escohdl", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_escoltaddr, + {"eSCO LT_ADDR", "btbrlmp.escoltaddr", + FT_UINT8, BASE_HEX, NULL, 0x0, + "eSCO Logical Transport Address", HFILL}}, + {&hf_lmp_features, + {"Features", "btbrlmp.features", + FT_UINT64, BASE_HEX, NULL, 0x0, + "Feature Mask", HFILL}}, + {&hf_lmp_feat_3slot, + {"3 slot packets", "btbrlmp.feat.3slot", + FT_BOOLEAN, 64, NULL, 0x1, + NULL, HFILL}}, + {&hf_lmp_feat_5slot, + {"5 slot packets", "btbrlmp.feat.5slot", + FT_BOOLEAN, 64, NULL, 0x1 << 1, + NULL, HFILL}}, + {&hf_lmp_feat_enc, + {"Encryption", "btbrlmp.feat.enc", + FT_BOOLEAN, 64, NULL, 0x1 << 2, + NULL, HFILL}}, + {&hf_lmp_feat_slotoff, + {"Slot offset", "btbrlmp.feat.slotoff", + FT_BOOLEAN, 64, NULL, 0x1 << 3, + NULL, HFILL}}, + {&hf_lmp_feat_timacc, + {"Timing accuracy", "btbrlmp.feat.timacc", + FT_BOOLEAN, 64, NULL, 0x1 << 4, + NULL, HFILL}}, + {&hf_lmp_feat_rolesw, + {"Role switch", "btbrlmp.feat.rolesw", + FT_BOOLEAN, 64, NULL, 0x1 << 5, + NULL, HFILL}}, + {&hf_lmp_feat_holdmo, + {"Hold mode", "btbrlmp.feat.holdmo", + FT_BOOLEAN, 64, NULL, 0x1 << 6, + NULL, HFILL}}, + {&hf_lmp_feat_sniffmo, + {"Sniff mode", "btbrlmp.feat.sniffmo", + FT_BOOLEAN, 64, NULL, 0x1 << 7, + NULL, HFILL}}, + {&hf_lmp_feat_res0, + {"Reserved", "btbrlmp.feat.res0", + FT_BOOLEAN, 64, NULL, 0x1 << 8, + NULL, HFILL}}, + {&hf_lmp_feat_pwrctlreq, + {"Power control requests", "btbrlmp.feat.pwrctlreq", + FT_BOOLEAN, 64, NULL, 0x1 << 9, + NULL, HFILL}}, + {&hf_lmp_feat_cqddr, + {"Channel quality driven data rate (CQDDR)", "btbrlmp.feat.cqddr", + FT_BOOLEAN, 64, NULL, 0x1 << 10, + NULL, HFILL}}, + {&hf_lmp_feat_sco, + {"SCO link", "btbrlmp.feat.sco", + FT_BOOLEAN, 64, NULL, 0x1 << 11, + NULL, HFILL}}, + {&hf_lmp_feat_hv2, + {"HV2 packets", "btbrlmp.feat.hv2", + FT_BOOLEAN, 64, NULL, 0x1 << 12, + NULL, HFILL}}, + {&hf_lmp_feat_hv3, + {"HV3 packets", "btbrlmp.feat.hv3", + FT_BOOLEAN, 64, NULL, 0x1 << 13, + NULL, HFILL}}, + {&hf_lmp_feat_mulaw, + {"u-law log synchronous data", "btbrlmp.feat.mulaw", + FT_BOOLEAN, 64, NULL, 0x1 << 14, + NULL, HFILL}}, + {&hf_lmp_feat_alaw, + {"A-law log synchronous data", "btbrlmp.feat.alaw", + FT_BOOLEAN, 64, NULL, 0x1 << 15, + NULL, HFILL}}, + {&hf_lmp_feat_cvsd, + {"CVSD synchronous data", "btbrlmp.feat.cvsd", + FT_BOOLEAN, 64, NULL, 0x1 << 16, + NULL, HFILL}}, + {&hf_lmp_feat_pagneg, + {"Paging parameter negotiation", "btbrlmp.feat.pagneg", + FT_BOOLEAN, 64, NULL, 0x1 << 17, + NULL, HFILL}}, + {&hf_lmp_feat_pwrctl, + {"Power control", "btbrlmp.feat.pwrctl", + FT_BOOLEAN, 64, NULL, 0x1 << 18, + NULL, HFILL}}, + {&hf_lmp_feat_transsync, + {"Transparent synchronous data", "btbrlmp.feat.transsync", + FT_BOOLEAN, 64, NULL, 0x1 << 19, + NULL, HFILL}}, + {&hf_lmp_feat_flowctl1, + {"Flow control lag (least significant bit)", "btbrlmp.feat.flowctl1", + FT_BOOLEAN, 64, NULL, 0x1 << 20, + NULL, HFILL}}, + {&hf_lmp_feat_flowctl2, + {"Flow control lag (middle bit)", "btbrlmp.feat.flowctl2", + FT_BOOLEAN, 64, NULL, 0x1 << 21, + NULL, HFILL}}, + {&hf_lmp_feat_flowctl3, + {"Flow control lag (most significant bit)", "btbrlmp.feat.flowctl3", + FT_BOOLEAN, 64, NULL, 0x1 << 22, + NULL, HFILL}}, + {&hf_lmp_feat_bcenc, + {"Broadcast Encryption", "btbrlmp.feat.bcenc", + FT_BOOLEAN, 64, NULL, 0x1 << 23, + NULL, HFILL}}, + {&hf_lmp_feat_res1, + {"Reserved for future use", "btbrlmp.feat.res1", + FT_BOOLEAN, 64, NULL, 0x1 << 24, + NULL, HFILL}}, + {&hf_lmp_feat_acl2, + {"Enhanced Data Rate ACL 2 Mb/s mode", "btbrlmp.feat.acl2", + FT_BOOLEAN, 64, NULL, 0x1 << 25, + NULL, HFILL}}, + {&hf_lmp_feat_acl3, + {"Enhanced Data Rate ACL 3 Mb/s mode", "btbrlmp.feat.acl3", + FT_BOOLEAN, 64, NULL, 0x1 << 26, + NULL, HFILL}}, + {&hf_lmp_feat_eninq, + {"Enhanced inquiry scan", "btbrlmp.feat.eninq", + FT_BOOLEAN, 64, NULL, 0x1 << 27, + NULL, HFILL}}, + {&hf_lmp_feat_intinq, + {"Interlaced inquiry scan", "btbrlmp.feat.intinq", + FT_BOOLEAN, 64, NULL, 0x1 << 28, + NULL, HFILL}}, + {&hf_lmp_feat_intpag, + {"Interlaced page scan", "btbrlmp.feat.intpag", + FT_BOOLEAN, 64, NULL, 0x1 << 29, + NULL, HFILL}}, + {&hf_lmp_feat_rssiinq, + {"RSSI with inquiry results", "btbrlmp.feat.rssiinq", + FT_BOOLEAN, 64, NULL, 0x1 << 30, + NULL, HFILL}}, + {&hf_lmp_feat_ev3, + {"Extended SCO link (EV3 packets)", "btbrlmp.feat.ev3", + FT_BOOLEAN, 64, NULL, 0x80000000, + NULL, HFILL}}, + {&hf_lmp_feat_ev4, + {"EV4 packets", "btbrlmp.feat.ev4", + FT_BOOLEAN, 64, NULL, 0x100000000, + NULL, HFILL}}, + {&hf_lmp_feat_ev5, + {"EV5 packets", "btbrlmp.feat.ev5", + FT_BOOLEAN, 64, NULL, 0x100000000 << 1, + NULL, HFILL}}, + {&hf_lmp_feat_res2, + {"Reserved", "btbrlmp.feat.res2", + FT_BOOLEAN, 64, NULL, 0x100000000 << 2, + NULL, HFILL}}, + {&hf_lmp_feat_afhcapsl, + {"AFH capable slave", "btbrlmp.feat.afhcapsl", + FT_BOOLEAN, 64, NULL, 0x100000000 << 3, + NULL, HFILL}}, + {&hf_lmp_feat_afhclasl, + {"AFH classification slave", "btbrlmp.feat.afhclasl", + FT_BOOLEAN, 64, NULL, 0x100000000 << 4, + NULL, HFILL}}, + {&hf_lmp_feat_bredrnotsup, + {"BR/EDR Not Supported", "btbrlmp.feat.bredrnotsup", + FT_BOOLEAN, 64, NULL, 0x100000000 << 5, + NULL, HFILL}}, + {&hf_lmp_feat_lesup, + {"LE Supported (Controller)", "btbrlmp.feat.lesup", + FT_BOOLEAN, 64, NULL, 0x100000000 << 6, + NULL, HFILL}}, + {&hf_lmp_feat_3slotenh, + {"3-slot Enhanced Data Rate ACL packets", "btbrlmp.feat.3slotenh", + FT_BOOLEAN, 64, NULL, 0x100000000 << 7, + NULL, HFILL}}, + {&hf_lmp_feat_5slotenh, + {"5-slot Enhanced Data Rate ACL packets", "btbrlmp.feat.5slotenh", + FT_BOOLEAN, 64, NULL, 0x100000000 << 8, + NULL, HFILL}}, + {&hf_lmp_feat_sniffsubr, + {"Sniff subrating", "btbrlmp.feat.sniffsubr", + FT_BOOLEAN, 64, NULL, 0x100000000 << 9, + NULL, HFILL}}, + {&hf_lmp_feat_pauseenc, + {"Pause encryption", "btbrlmp.feat.pauseenc", + FT_BOOLEAN, 64, NULL, 0x100000000 << 10, + NULL, HFILL}}, + {&hf_lmp_feat_afhcapma, + {"AFH capable master", "btbrlmp.feat.afhcapma", + FT_BOOLEAN, 64, NULL, 0x100000000 << 11, + NULL, HFILL}}, + {&hf_lmp_feat_afhclama, + {"AFH classification master", "btbrlmp.feat.afhclama", + FT_BOOLEAN, 64, NULL, 0x100000000 << 12, + NULL, HFILL}}, + {&hf_lmp_feat_esco2, + {"Enhanced Data Rate eSCO 2 Mb/s mode", "btbrlmp.feat.esco2", + FT_BOOLEAN, 64, NULL, 0x100000000 << 13, + NULL, HFILL}}, + {&hf_lmp_feat_esco3, + {"Enhanced Data Rate eSCO 3 Mb/s mode", "btbrlmp.feat.esco3", + FT_BOOLEAN, 64, NULL, 0x100000000 << 14, + NULL, HFILL}}, + {&hf_lmp_feat_3slotenhesco, + {"3-slot Enhanced Data Rate eSCO packets", "btbrlmp.feat.3slotenhesco", + FT_BOOLEAN, 64, NULL, 0x100000000 << 15, + NULL, HFILL}}, + {&hf_lmp_feat_extinqres, + {"Extended Inquiry Response", "btbrlmp.feat.extinqres", + FT_BOOLEAN, 64, NULL, 0x100000000 << 16, + NULL, HFILL}}, + {&hf_lmp_feat_simlebredr, + {"Simultaneous LE and BR/EDR to Same Device Capable (Controller)", "btbrlmp.feat.simlebredr", + FT_BOOLEAN, 64, NULL, 0x100000000 << 17, + NULL, HFILL}}, + {&hf_lmp_feat_res3, + {"Reserved", "btbrlmp.feat.res3", + FT_BOOLEAN, 64, NULL, 0x100000000 << 18, + NULL, HFILL}}, + {&hf_lmp_feat_ssp, + {"Secure Simple Pairing", "btbrlmp.feat.ssp", + FT_BOOLEAN, 64, NULL, 0x100000000 << 19, + NULL, HFILL}}, + {&hf_lmp_feat_enpdu, + {"Encapsulated PDU", "btbrlmp.feat.enpdu", + FT_BOOLEAN, 64, NULL, 0x100000000 << 20, + NULL, HFILL}}, + {&hf_lmp_feat_edr, + {"Erroneous Data Reporting", "btbrlmp.feat.edr", + FT_BOOLEAN, 64, NULL, 0x100000000 << 21, + NULL, HFILL}}, + {&hf_lmp_feat_nonflush, + {"Non-flushable Packet Boundary Flag", "btbrlmp.feat.nonflush", + FT_BOOLEAN, 64, NULL, 0x100000000 << 22, + NULL, HFILL}}, + {&hf_lmp_feat_res4, + {"Reserved", "btbrlmp.feat.res4", + FT_BOOLEAN, 64, NULL, 0x100000000 << 23, + NULL, HFILL}}, + {&hf_lmp_feat_lstimche, + {"Link Supervision Timeout Changed Event", "btbrlmp.feat.lstimche", + FT_BOOLEAN, 64, NULL, 0x100000000 << 24, + NULL, HFILL}}, + {&hf_lmp_feat_inqtxpwr, + {"Inquiry TX Power Level", "btbrlmp.feat.inqtxpwr", + FT_BOOLEAN, 64, NULL, 0x100000000 << 25, + NULL, HFILL}}, + {&hf_lmp_feat_enhpwr, + {"Enhanced Power Control", "btbrlmp.feat.enhpwr", + FT_BOOLEAN, 64, NULL, 0x100000000 << 26, + NULL, HFILL}}, + {&hf_lmp_feat_res5, + {"Reserved", "btbrlmp.feat.res5", + FT_BOOLEAN, 64, NULL, 0x100000000 << 27, + NULL, HFILL}}, + {&hf_lmp_feat_res6, + {"Reserved", "btbrlmp.feat.res6", + FT_BOOLEAN, 64, NULL, 0x100000000 << 28, + NULL, HFILL}}, + {&hf_lmp_feat_res7, + {"Reserved", "btbrlmp.feat.res7", + FT_BOOLEAN, 64, NULL, 0x100000000 << 29, + NULL, HFILL}}, + {&hf_lmp_feat_res8, + {"Reserved", "btbrlmp.feat.res8", + FT_BOOLEAN, 64, NULL, 0x100000000 << 30, + NULL, HFILL}}, + {&hf_lmp_feat_extfeat, + {"Extended features", "btbrlmp.feat.extfeat", + FT_BOOLEAN, 64, NULL, 0x100000000 << 31, + NULL, HFILL}}, + {&hf_lmp_featuresext, + {"Extended Features", "btbrlmp.featuresext", + FT_UINT64, BASE_HEX, NULL, 0x0, + "Extended Feature Mask", HFILL}}, + /* extended features page 1 */ + {&hf_lmp_efeat_ssp, + {"Secure Simple Pairing (Host Support)", "btbrlmp.efeat.ssp", + FT_BOOLEAN, 64, NULL, 0x1 << 0, + NULL, HFILL}}, + {&hf_lmp_efeat_lesup, + {"LE Supported (Host)", "btbrlmp.efeat.lesup", + FT_BOOLEAN, 64, NULL, 0x1 << 1, + NULL, HFILL}}, + {&hf_lmp_efeat_lebredr, + {"Simultaneous LE and BR/EDR to Same Device Capable (Host)", "btbrlmp.efeat.lebredr", + FT_BOOLEAN, 64, NULL, 0x1 << 2, + NULL, HFILL}}, + {&hf_lmp_efeat_sch, + {"Secure Connections (Host Support)", "btbrlmp.efeat.sch", + FT_BOOLEAN, 64, NULL, 0x1 << 3, + NULL, HFILL}}, + /* extended features page 2 */ + {&hf_lmp_efeat_csbma, + {"Connectionless Slave Broadcast - Master Operation", "btbrlmp.efeat.csbma", + FT_BOOLEAN, 64, NULL, 0x1 << 0, + NULL, HFILL}}, + {&hf_lmp_efeat_csbsl, + {"Connectionless Slave Broadcast - Slave Operation", "btbrlmp.efeat.csbsl", + FT_BOOLEAN, 64, NULL, 0x1 << 1, + NULL, HFILL}}, + {&hf_lmp_efeat_syntr, + {"Synchronization Train", "btbrlmp.efeat.syntr", + FT_BOOLEAN, 64, NULL, 0x1 << 2, + NULL, HFILL}}, + {&hf_lmp_efeat_synsc, + {"Synchronization Scan", "btbrlmp.efeat.synsc", + FT_BOOLEAN, 64, NULL, 0x1 << 3, + NULL, HFILL}}, + {&hf_lmp_efeat_inqresnote, + {"Inquiry Response Notification Event", "btbrlmp.efeat.inqresnote", + FT_BOOLEAN, 64, NULL, 0x1 << 4, + NULL, HFILL}}, + {&hf_lmp_efeat_genintsc, + {"Generalized interlaced scan", "btbrlmp.efeat.genintsc", + FT_BOOLEAN, 64, NULL, 0x1 << 5, + NULL, HFILL}}, + {&hf_lmp_efeat_ccadj, + {"Coarse Clock Adjustment", "btbrlmp.efeat.ccadj", + FT_BOOLEAN, 64, NULL, 0x1 << 6, + NULL, HFILL}}, + {&hf_lmp_efeat_res0, + {"Reserved for future use", "btbrlmp.efeat.res0", + FT_BOOLEAN, 64, NULL, 0x1 << 7, + NULL, HFILL}}, + {&hf_lmp_efeat_scc, + {"Secure Connections (Controller Support)", "btbrlmp.efeat.scc", + FT_BOOLEAN, 64, NULL, 0x1 << 8, + NULL, HFILL}}, + {&hf_lmp_efeat_ping, + {"Ping", "btbrlmp.efeat.ping", + FT_BOOLEAN, 64, NULL, 0x1 << 9, + NULL, HFILL}}, + {&hf_lmp_efeat_res1, + {"Reserved for future use", "btbrlmp.efeat.res1", + FT_BOOLEAN, 64, NULL, 0x1 << 10, + NULL, HFILL}}, + {&hf_lmp_efeat_trnud, + {"Train nudging", "btbrlmp.efeat.trnud", + FT_BOOLEAN, 64, NULL, 0x1 << 11, + NULL, HFILL}}, + {&hf_lmp_efeat_sam, + {"Slot Availability Mask", "btbrlmp.efeat.sam", + FT_BOOLEAN, 64, NULL, 0x1 << 12, //typo in the BT standard defines this as >>10 ... + NULL, HFILL}}, + {&hf_lmp_fpage, + {"Features Page", "btbrlmp.fpage", + FT_UINT8, BASE_DEC, VALS(features_page), 0x0, + NULL, HFILL}}, + {&hf_lmp_htime, + {"Hold Time", "btbrlmp.htime", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Hold Time in slots", HFILL}}, + {&hf_lmp_hinst, + {"Hold Instant", "btbrlmp.hinst", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Hold Instant (slot)", HFILL}}, + {&hf_lmp_hopmode, + {"Hopping Mode", "btbrlmp.hopmode", + FT_UINT8, BASE_DEC, VALS(hopping_mode), 0x0, + NULL, HFILL}}, + {&hf_lmp_iocaps, + {"IO Capabilities", "btbrlmp.iocaps", + FT_UINT8, BASE_DEC, VALS(io_capabilities), 0x0, + "Input/Output Capabilities", HFILL}}, + {&hf_lmp_jitter, + {"Jitter", "btbrlmp.jitter", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Jitter in microseconds", HFILL}}, + {&hf_lmp_key, + {"Key", "btbrlmp.key", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_keysz, + {"Key Size", "btbrlmp.keysz", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Key Size in bytes", HFILL}}, + {&hf_lmp_ksmask, + {"Key Size Mask", "btbrlmp.ksmask", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_ltaddr1, + {"LT_ADDR 1", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0x0f, + "Logical Transport Address 1", HFILL}}, + {&hf_lmp_ltaddr2, + {"LT_ADDR 2", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0xf0, + "Logical Transport Address 2", HFILL}}, + {&hf_lmp_ltaddr3, + {"LT_ADDR 3", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0x0f, + "Logical Transport Address 3", HFILL}}, + {&hf_lmp_ltaddr4, + {"LT_ADDR 4", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0xf0, + "Logical Transport Address 4", HFILL}}, + {&hf_lmp_ltaddr5, + {"LT_ADDR 5", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0x0f, + "Logical Transport Address 5", HFILL}}, + {&hf_lmp_ltaddr6, + {"LT_ADDR 6", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0xf0, + "Logical Transport Address 6", HFILL}}, + {&hf_lmp_ltaddr7, + {"LT_ADDR 7", "btbrlmp.ltaddr", + FT_UINT8, BASE_HEX, NULL, 0x0f, + "Logical Transport Address 7", HFILL}}, + {&hf_lmp_maccess, + {"Maccess", "btbrlmp.maccess", + FT_UINT8, BASE_HEX, NULL, 0x0f, + "Number of access windows", HFILL}}, + {&hf_lmp_maxslots, + {"Max Slots", "btbrlmp.maxslots", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_maxsp, + {"Max Supported Page", "btbrlmp.maxsp", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Highest extended features page with non-zero bit", HFILL}}, + {&hf_lmp_maxss, + {"Max Sniff Subrate", "btbrlmp.maxss", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_minsmt, + {"Min Sniff Mode Timeout", "btbrlmp.minsmt", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Min Sniff Mode Timeout in slots", HFILL}}, + {&hf_lmp_naccslots, + {"Nacc-slots", "btbrlmp.naccslots", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_namefrag, + {"Name Fragment", "btbrlmp.namefrag", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_namelen, + {"Name Length", "btbrlmp.namelen", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Name Length in bytes", HFILL}}, + {&hf_lmp_nameoffset, + {"Name Offset", "btbrlmp.nameoffset", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Name Offset in bytes", HFILL}}, + {&hf_lmp_nb, + {"Nb", "btbrlmp.nb", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_nbc, + {"Nbc", "btbrlmp.nbc", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_nbsleep, + {"Nbsleep", "btbrlmp.nbsleep", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_negstate, + {"Negotiation State", "btbrlmp.negstate", + FT_UINT8, BASE_DEC, VALS(negotiation_state), 0x0, + NULL, HFILL}}, + {&hf_lmp_nonce, + {"Nonce Value", "btbrlmp.nonce", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_nottype, + {"Notification Type", "btbrlmp.nottype", + FT_UINT8, BASE_DEC, VALS(notification_value), 0x0, + NULL, HFILL}}, + {&hf_lmp_npoll, + {"Npoll", "btbrlmp.npoll", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_oobauthdata, + {"OOB Authentication Data", "btbrlmp.oobauthdata", + FT_UINT8, BASE_DEC, VALS(oob_auth_data), 0x00, + NULL, HFILL}}, + {&hf_lmp_op, + {"Opcode", "btbrlmp.op", + FT_UINT8, BASE_DEC, VALS(opcode), 0xfe, + NULL, HFILL}}, + {&hf_lmp_opinre, + {"In Response To", "btbrlmp.opinre", + FT_UINT8, BASE_DEC, VALS(opcode), 0x7f, + "Opcode this is in response to", HFILL}}, + {&hf_lmp_pagesch, + {"Paging Scheme", "btbrlmp.pagesch", + FT_UINT8, BASE_DEC, VALS(paging_scheme), 0x0, + NULL, HFILL}}, + {&hf_lmp_pcmode, + {"Power Control Mode", "btbrlmp.pcmode", + FT_UINT8, BASE_DEC, VALS(power_control_mode), 0x0, + NULL, HFILL}}, + {&hf_lmp_pkttype, + {"Packet Type", "btbrlmp.pkttype", + /* FIXME break out further */ + FT_UINT8, BASE_HEX, NULL, 0x0, + "Packet Type", HFILL}}, + {&hf_lmp_pkttypetbl, + {"Packet Type Table", "btbrlmp.pkttypetbl", + FT_UINT8, BASE_DEC, VALS(packet_type_table), 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr, + {"PM_ADDR", "btbrlmp.pmaddr", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr1, + {"PM_ADDR 1", "btbrlmp.pmaddr1", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr2, + {"PM_ADDR 2", "btbrlmp.pmaddr2", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr3, + {"PM_ADDR 3", "btbrlmp.pmaddr3", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr4, + {"PM_ADDR 4", "btbrlmp.pmaddr4", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr5, + {"PM_ADDR 5", "btbrlmp.pmaddr5", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr6, + {"PM_ADDR 6", "btbrlmp.pmaddr6", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pmaddr7, + {"PM_ADDR 7", "btbrlmp.pmaddr7", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pollintvl, + {"Poll Interval", "btbrlmp.pollintvl", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Poll Interval in slots", HFILL}}, + {&hf_lmp_pollper, + {"Poll Period (ms)", "btbrlmp.pollper", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Poll Period in units of 1.25 ms", HFILL}}, + {&hf_lmp_pssettings, + {"Paging Scheme Settings", "btbrlmp.pssettings", + FT_UINT8, BASE_DEC, VALS(paging_scheme_settings), 0x0, + NULL, HFILL}}, + {&hf_lmp_pwradjreq, + {"Power Adjustment Request", "btbrlmp.pwradjreq", + FT_UINT8, BASE_DEC, VALS(power_adjust_req), 0x0, + NULL, HFILL}}, + {&hf_lmp_pwradjres, + {"Power Adjustment Response", "btbrlmp.pwradjres", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_pwradj_8dpsk, + {"8DPSK", "btbrlmp.pwradj_8dpsk", + FT_UINT8, BASE_DEC, VALS(power_adjust_res), 0x30, + "8DPSK Power Adjustment Response", HFILL}}, + {&hf_lmp_pwradj_dqpsk, + {"DQPSK", "btbrlmp.pwradj_dqpsk", + FT_UINT8, BASE_DEC, VALS(power_adjust_res), 0x0C, + "DQPSK Power Adjustment Response", HFILL}}, + {&hf_lmp_pwradj_gfsk, + {"GFSK", "btbrlmp.pwradj_gfsk", + FT_UINT8, BASE_DEC, VALS(power_adjust_res), 0x03, + "GFSK Power Adjustment Response", HFILL}}, + {&hf_lmp_rand, + {"Random Number", "btbrlmp.rand", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_rate, + {"Data Rate", "btbrlmp.rate", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_rate_fec, + {"FEC", "btbrlmp.rate.fec", + FT_BOOLEAN, BASE_DEC, TFS(&fec), 0x01, + "Forward Error Correction", HFILL}}, + {&hf_lmp_rate_size, + {"Packet Size", "btbrlmp.rate.size", + FT_UINT8, BASE_HEX, VALS(packet_size), 0x06, + "Basic Rate Packet Size", HFILL}}, + {&hf_lmp_rate_type, + {"EDR Type", "btbrlmp.rate.type", + FT_UINT8, BASE_HEX, VALS(edr_type), 0x18, + "Enhanced Data Rate type", HFILL}}, + {&hf_lmp_rate_edrsize, + {"EDR Size", "btbrlmp.rate.edrsize", + FT_UINT8, BASE_HEX, VALS(packet_size), 0x60, + "Enhanced Data Rate packet size", HFILL}}, + {&hf_lmp_rxfreq, + {"RX Frequency (MHz)", "btbrlmp.rxfreq", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Receive Frequency in MHz above 2402", HFILL}}, + {&hf_lmp_scohdl, + {"SCO Handle", "btbrlmp.scohdl", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_scopkt, + {"SCO Packet", "btbrlmp.scopkt", + FT_UINT8, BASE_DEC, VALS(sco_packet), 0x0, + NULL, HFILL}}, + {&hf_lmp_slotoffset, + {"Slot Offset", "btbrlmp.slotoffset", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Slot Offset in microseconds", HFILL}}, + {&hf_lmp_sniffatt, + {"Sniff Attempt", "btbrlmp.sniffatt", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Number of receive slots", HFILL}}, + {&hf_lmp_sniffsi, + {"Sniff Subrating Instant", "btbrlmp.sniffsi", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Sniff Subrating Instant (slot)", HFILL}}, + {&hf_lmp_sniffto, + {"Sniff Timeout", "btbrlmp.sniffto", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Number of receive slots", HFILL}}, + {&hf_lmp_subversnr, + {"SubVersNr", "btbrlmp.subversnr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "SubVersion", HFILL}}, + {&hf_lmp_suptimeout, + {"Supervision Timeout", "btbrlmp.suptimeout", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Supervision Timeout in slots", HFILL}}, + {&hf_lmp_swinst, + {"Switch Instant", "btbrlmp.swinst", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Switch Instant (slot)", HFILL}}, + {&hf_lmp_taccess, + {"Taccess", "btbrlmp.taccess", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Taccess in slots", HFILL}}, + {&hf_lmp_tb, + {"Tb", "btbrlmp.tb", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Tb in slots", HFILL}}, + {&hf_lmp_tesco, + {"Tesco", "btbrlmp.tesco", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Tesco in slots", HFILL}}, + {&hf_lmp_testlen, + {"Test Length", "btbrlmp.testlen", + FT_UINT16, BASE_DEC, NULL, 0x00, + "Length of test sequence in bytes", HFILL}}, + {&hf_lmp_testscen, + {"Test Scenario", "btbrlmp.testscen", + FT_UINT8, BASE_DEC, VALS(test_scenario), 0x00, + NULL, HFILL}}, + {&hf_lmp_tid, + {"TID", "btbrlmp.tid", + FT_BOOLEAN, BASE_DEC, TFS(&tid), 0x01, + "Transaction ID", HFILL}}, + {&hf_lmp_timectrl, + {"Timing Control Flags", "btbrlmp.timectrl", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_lmp_time_change, + {"Timing Change", "btbrlmp.time.change", + FT_BOOLEAN, 8, TFS(&time_change), 0x01, + NULL, HFILL}}, + {&hf_lmp_time_init, + {"Initialization", "btbrlmp.time.init", + FT_BOOLEAN, 8, TFS(&time_init), 0x02, + NULL, HFILL}}, + {&hf_lmp_time_accwin, + {"Access Window", "btbrlmp.time.accwin", + FT_BOOLEAN, 8, TFS(&time_accwin), 0x04, + NULL, HFILL}}, + {&hf_lmp_tsco, + {"Tsco", "btbrlmp.tsco", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Tsco in slots", HFILL}}, + {&hf_lmp_tsniff, + {"Tsniff", "btbrlmp.tsniff", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Tsniff in slots", HFILL}}, + {&hf_lmp_txfreq, + {"TX Frequency (MHz)", "btbrlmp.txfreq", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Transmit Frequency in MHz above 2402", HFILL}}, + {&hf_lmp_versnr, + {"VersNr", "btbrlmp.versnr", + FT_UINT8, BASE_DEC, VALS(versnr), 0x0, + "Version", HFILL}}, + {&hf_lmp_wesco, + {"Wesco", "btbrlmp.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, + &ett_lmp_features, + &ett_lmp_featuresext, + }; + + /* register the protocol name and description */ + proto_btbrlmp = proto_register_protocol( + "Bluetooth Link Manager Protocol", /* full name */ + "btlmp", /* short name */ + "btlmp" /* abbreviation (e.g. for filters) */ + ); + + register_dissector("btlmp", dissect_btbrlmp, proto_btbrlmp); + + /* register the header fields and subtrees used */ + proto_register_field_array(proto_btbrlmp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + +void proto_reg_handoff_btbrlmp(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: + */ diff --git a/dissectors/packet-h4bcm.c b/dissectors/packet-h4bcm.c new file mode 100644 index 0000000..a158322 --- /dev/null +++ b/dissectors/packet-h4bcm.c @@ -0,0 +1,1570 @@ +/* packet-h4bcm.c + * Routines for Bluetooth H4 Broadcom vendor specific additions + * Copyright 2019, Jiska Classen / Secure Mobile Networking Lab + * + * $Id$ + * + * 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. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +/* type definitions for Broadcom diagnostics */ +#define DIA_LM_SENT 0x00 +#define DIA_LM_RECV 0x01 +#define DIA_MEM_PEEK_RESP 0x03 +#define DIA_MEM_DUMP_RESP 0x04 +#define DIA_TEST_COMPL 0x0a +#define DIA_MEM_POKE_RESP 0x11 +#define DIA_CPU_LOAD_RESP 0x15 +#define DIA_ACL_BR_RESP 0x16 +#define DIA_ACL_EDR_RESP 0x17 +#define DIA_AUX_RESP 0x18 +#define DIA_ACL_UNKN1_RESP 0x1a +#define DIA_ACL_UNKN2_RESP 0x1b +#define DIA_CON_RESP 0x1f +#define DIA_LE_SENT 0x80 +#define DIA_LE_RECV 0x81 +#define DIA_ACL_BR_RESET 0xb9 +#define DIA_ACL_BR_GET 0xc1 +#define DIA_ACL_EDR_GET 0xc2 +#define DIA_AUX_GET 0xc3 +#define DIA_ACL_UNKN1_GET 0xc5 +#define DIA_ACL_UNKN2_GET 0xc6 +#define DIA_CON_GET 0xcf +#define DIA_LM_ENABLE 0xf0 +#define DIA_MEM_PEEK_GET 0xf1 +#define DIA_MEM_POKE_GET 0xf2 +#define DIA_MEM_DUMP_GET 0xf3 +#define DIA_PKT_TEST 0xf6 + +/* function prototypes */ +void proto_reg_handoff_h4bcm(void); + +/* initialize the protocol and registered fields */ +static int proto_h4bcm = -1; +static int hf_h4bcm_type = -1; +static int hf_h4bcm_clock = -1; +static int hf_h4bcm_maclow = -1; +static int hf_h4bcm_pldhdr = -1; +static int hf_h4bcm_aclhdr = -1; +static int hf_h4bcm_llid = -1; +static int hf_h4bcm_llid_acl = -1; +static int hf_h4bcm_acl_fragment = -1; +static int hf_h4bcm_pldflow = -1; +static int hf_h4bcm_pldflow_acl = -1; +static int hf_h4bcm_length = -1; +static int hf_h4bcm_length_acl = -1; +static int hf_h4bcm_rfu = -1; +static int hf_h4bcm_payload = -1; +static int hf_h4bcm_lm_toggle = -1; +static int hf_h4bcm_stats_null_rcvd = -1; +static int hf_h4bcm_stats_poll_rcvd = -1; +static int hf_h4bcm_stats_dm1_rcvd = -1; +static int hf_h4bcm_stats_dh1_rcvd = -1; +static int hf_h4bcm_stats_dv_rcvd = -1; +static int hf_h4bcm_stats_aux1_rcvd = -1; +static int hf_h4bcm_stats_dm3_rcvd = -1; +static int hf_h4bcm_stats_dh3_rcvd = -1; +static int hf_h4bcm_stats_dm5_rcvd = -1; +static int hf_h4bcm_stats_dh5_rcvd = -1; +static int hf_h4bcm_stats_null_tx = -1; +static int hf_h4bcm_stats_poll_tx = -1; +static int hf_h4bcm_stats_dm1_tx = -1; +static int hf_h4bcm_stats_dh1_tx = -1; +static int hf_h4bcm_stats_dv_tx = -1; +static int hf_h4bcm_stats_aux1_tx = -1; +static int hf_h4bcm_stats_dm3_tx = -1; +static int hf_h4bcm_stats_dh3_tx = -1; +static int hf_h4bcm_stats_dm5_tx = -1; +static int hf_h4bcm_stats_dh5_tx = -1; +static int hf_h4bcm_stats_acl_rx = -1; +static int hf_h4bcm_stats_acl_tx = -1; +static int hf_h4bcm_stats_hec_err = -1; +static int hf_h4bcm_stats_crc_err = -1; +static int hf_h4bcm_stats_seqn_rep = -1; +static int hf_h4bcm_stats_soft_rst = -1; +static int hf_h4bcm_stats_test_tx = -1; + +static int hf_h4bcm_stats_test_rx = -1; +static int hf_h4bcm_stats_test_err = -1; +static int hf_h4bcm_stats_2dh1_rcvd = -1; +static int hf_h4bcm_stats_3dh1_rcvd = -1; +static int hf_h4bcm_stats_2dh3_rcvd = -1; +static int hf_h4bcm_stats_3dh3_rcvd = -1; +static int hf_h4bcm_stats_2dh5_rcvd = -1; +static int hf_h4bcm_stats_3dh5_rcvd = -1; +static int hf_h4bcm_stats_2dh1_tx = -1; +static int hf_h4bcm_stats_3dh1_tx = -1; +static int hf_h4bcm_stats_2dh3_tx = -1; +static int hf_h4bcm_stats_3dh3_tx = -1; +static int hf_h4bcm_stats_2dh5_tx = -1; +static int hf_h4bcm_stats_3dh5_tx = -1; +static int hf_h4bcm_le_ether = -1; +static int hf_h4bcm_le_handle = -1; +static int hf_h4bcm_le_opcode = -1; +static int hf_h4bcm_le_opcode_ext = -1; +static int hf_h4bcm_ll_version_ind_versnr = -1; +static int hf_h4bcm_ll_version_ind_compid = -1; +static int hf_h4bcm_ll_version_ind_subversnr = -1; +// Baseband +static int hf_btbbd = -1; +// Baseband Metadata +static int hf_btbbd_meta = -1; +static int hf_btbbd_clk = -1; +static int hf_btbbd_channel = -1; +static int hf_btbbd_ptt = -1; +static int hf_btbbd_role = -1; +static int hf_btbbd_tx_encrypted = -1; +static int hf_btbbd_rx_encrypted = -1; +static int hf_btbbd_is_eir = -1; +// Baseband Packet Header +static int hf_btbbd_pkthdr = -1; +static int hf_btbbd_ltaddr = -1; +static int hf_btbbd_type = -1; +static int hf_btbbd_type_br = -1; +static int hf_btbbd_type_edr = -1; +static int hf_btbbd_flags = -1; +static int hf_btbbd_flow = -1; +static int hf_btbbd_arqn = -1; +static int hf_btbbd_seqn = -1; +static int hf_btbbd_hec = -1; +// FHS +static int hf_btbbd_fhs = -1; +static int hf_btbbd_fhs_parity = -1; +static int hf_btbbd_fhs_lap = -1; +static int hf_btbbd_fhs_eir = -1; +static int hf_btbbd_fhs_sr = -1; +static int hf_btbbd_fhs_uap = -1; +static int hf_btbbd_fhs_nap = -1; +static int hf_btbbd_fhs_class = -1; +static int hf_btbbd_fhs_ltaddr = -1; +static int hf_btbbd_fhs_clk = -1; +static int hf_btbbd_fhs_psmode = -1; + +/* initialize the subtree pointers */ +static gint ett_h4bcm = -1; +static gint ett_h4bcm_pldhdr = -1; +static gint ett_h4bcm_aclhdr = -1; +static gint ett_h4bcm_acl_br_stats = -1; +static gint ett_h4bcm_acl_edr_stats = -1; +static gint ett_btbbd = -1; +static gint ett_btbbd_meta = -1; +static gint ett_btbbd_pkthdr = -1; +static gint ett_btbbd_fhs = -1; + +/* subdissectors */ +static dissector_handle_t btlmp_handle = NULL; +static dissector_handle_t btl2cap_handle = NULL; +static dissector_handle_t packetlogger_handle = NULL; + +/* reversed Broadcom diagnostic types */ +static const value_string h4bcm_types[] = { + {DIA_LM_SENT, "LM Sent"}, + {DIA_LM_RECV, "LM Received"}, + {DIA_MEM_PEEK_RESP, "Memory Access Response to Peek"}, + {DIA_MEM_DUMP_RESP, "Memory Hex Dump Response"}, + {DIA_TEST_COMPL, "Reported Completed Test"}, + {DIA_MEM_POKE_RESP, "Memory Access Response to Poke"}, + {DIA_CPU_LOAD_RESP, "CPU Load"}, + {DIA_ACL_BR_RESP, "Basic Rate ACL Stats Data"}, + {DIA_ACL_EDR_RESP, "EDR ACL Stats Data"}, + {DIA_AUX_RESP, "Received Aux Response"}, + {DIA_ACL_UNKN1_RESP, "ACL Stats Data (Type 0x1A)"}, + {DIA_ACL_UNKN2_RESP, "ACL Stats Data (Type 0x1B)"}, + {DIA_CON_RESP, "Get Connection Response"}, + {DIA_LE_SENT, "LE LM Sent"}, // Low Energy LL Control PDU LMP Message + {DIA_LE_RECV, "LE LM Received"}, + {DIA_ACL_BR_RESET, "Reset Basic Rate ACL Stats"}, // memclr(DHM_ACLPktStats) + {DIA_ACL_BR_GET, "Get Basic Rate ACL Stats"}, + {DIA_ACL_EDR_GET, "Get EDR ACL Stats"}, + {DIA_ACL_UNKN1_GET, "Get ACL Stats (Type 0x1A)"}, // BTMUtil_Send_2045_ACL_Stats(0x1a, cmd) + {DIA_ACL_UNKN2_GET, "Get ACL Stats (Type 0x1B)"}, + {DIA_AUX_GET, "Get Aux Stats"}, // BTMUtil_SendAuxStats + {DIA_CON_GET, "Get Connection Stats"}, // ulp_send_connection_stats(0x1F) + {DIA_LM_ENABLE, "Toggle LMP Logging"}, + {DIA_MEM_PEEK_GET, "Memory Peek"}, + {DIA_MEM_POKE_GET, "Memory Poke"}, + {DIA_MEM_DUMP_GET, "Memory Hex Dump"}, + {DIA_PKT_TEST, "BTMMstr_BBPktTest"}, +}; + +static const value_string llid_codes[] = { + {0x0, "undefined"}, + {0x1, "Continuation fragment of an L2CAP message (ACL-U)"}, + {0x2, "Start of an L2CAP message or no fragmentation (ACL-U)"}, + {0x3, "LMP message (ACL-C)"}, + {0, NULL}}; + +/* This table is needed due to Brodcoms wrong LMP length passing... */ +static const int lmp_lengths[] = { + 0, /* LMP_VSC */ + 2, /* LMP_NAME_REQ */ + 17, /* LMP_NAME_RES */ + 2, /* LMP_ACCEPTED */ + 3, /* LMP_NOT_ACCEPTED */ + 1, /* LMP_CLKOFFSET_REQ */ + 3, /* LMP_CLKOFFSET_RES */ + 2, /* LMP_DETACH */ + 17, /* LMP_IN_RAND */ + 17, /* LMP_COMB_KEY */ + 17, /* LMP_UNIT_KEY */ + 17, /* LMP_AU_RAND */ + 5, /* LMP_SRES */ + 17, /* LMP_TEMP_RAND */ + 17, /* LMP_TEMP_KEY */ + 2, /* LMP_ENCRYPTION_MODE_REQ */ + 2, /* LMP_ENCRYPTION_KEY_SIZE_REQ */ + 17, /* LMP_START_ENCRYPTION_REQ */ + 1, /* LMP_STOP_ENCRYPTION_REQ */ + 5, /* LMP_SWITCH_REQ */ + 7, /* LMP_HOLD */ + 7, /* LMP_HOLD_REQ */ + 10, /* LMP_SNIFF_REQ */ + 0, + 1, /* LMP_UNSNIFF_REQ */ + 17, /* LMP_PARK_REQ */ + 0, + 4, /* LMP_SET_BROADCAST_SCAN_WINDOW */ + 11, /* LMP_MODIFY_BEACON */ + 15, /* LMP_UNPARK_BD_ADDR_REQ */ + 13, /* LMP_UNPARK_PM_ADDR_REQ */ + 2, /* LMP_INCR_POWER_REQ */ + 2, /* LMP_DECR_POWER_REQ */ + 1, /* LMP_MAX_POWER */ + 1, /* LMP_MIN_POWER */ + 1, /* LMP_AUTO_RATE */ + 2, /* LMP_PREFERRED_RATE */ + 6, /* LMP_VERSION_REQ */ + 6, /* LMP_VERSION_RES */ + 9, /* LMP_FEATURES_REQ */ + 9, /* LMP_FEATURES_RES */ + 4, /* LMP_QUALITY_OF_SERVICE */ + 4, /* LMP_QUALITY_OF_SERVICE_REQ */ + 7, /* LMP_SCO_LINK_REQ */ + 3, /* LMP_REMOVE_SCO_LINK_REQ */ + 2, /* LMP_MAX_SLOT */ + 2, /* LMP_MAX_SLOT_REQ */ + 1, /* LMP_TIMING_ACCURACY_REQ */ + 3, /* LMP_TIMING_ACCURACY_RES */ + 1, /* LMP_SETUP_COMPLETE */ + 1, /* LMP_USE_SEMI_PERMANENT_KEY */ + 1, /* LMP_HOST_CONNECTION_REQ */ + 9, /* LMP_SLOT_OFFSET */ + 3, /* LMP_PAGE_MODE_REQ */ + 3, /* LMP_PAGE_SCAN_MODE_REQ */ + 3, /* LMP_SUPERVISION_TIMEOUT */ + 1, /* LMP_TEST_ACTIVATE */ + 10, /* LMP_TEST_CONTROL */ + 1, /* LMP_ENCRYPTION_KEY_SIZE_MASK_REQ */ + 3, /* LMP_ENCRYPTION_KEY_SIZE_MASK_RES */ + 16, /* LMP_SET_AFH */ + 4, /* LMP_ENCAPSULATED_HEADER */ + 17, /* LMP_ENCAPSULATED_PAYLOAD */ + 17, /* LMP_SIMPLE_PAIRING_CONFIRM */ + 17, /* LMP_SIMPLE_PAIRING_NUMBER */ + 17, /* LMP_DHKEY_CHECK */ +}; + +static const int lmp_lengths_ext[] = { + 0, + 4, /* LMP_ACCEPTED_EXT */ + 5, /* LMP_NOT_ACCEPTED_EXT */ + 12, /* LMP_FEATURES_REQ_EXT */ + 12, /* LMP_FEATURES_RES_EXT */ + 0, + 0, + 0, + 0, + 0, + 0, + 3, /* LMP_PACKET_TYPE_TABLE_REQ */ + 16, /* LMP_ESCO_LINK_REQ */ + 4, /* LMP_REMOVE_ESCO_LINK_REQ */ + 0, + 0, + 7, /* LMP_CHANNEL_CLASSIFICATION_REQ */ + 12, /* LMP_CHANNEL_CLASSIFICATION */ + 0, + 0, + 0, + 9, /* LMP_SNIFF_SUBRATING_REQ */ + 9, /* LMP_SNIFF_SUBRATING_RES */ + 2, /* LMP_PAUSE_ENCRYPTION_REQ */ + 2, /* LMP_RESUME_ENCRYPTION_REQ */ + 5, /* LMP_IO_CAPABILITY_REQ */ + 5, /* LMP_IO_CAPABILITY_RES */ + 2, /* LMP_NUMERIC_COMPARISON_FAILED */ + 2, /* LMP_PASSKEY_FAILED */ + 2, /* LMP_OOB_FAILED */ + 3, /* LMP_KEYPRESS_NOTIFICATION */ + 3, /* LMP_POWER_CONTROL_REQ */ + 3, /* LMP_POWER_CONTROL_RES */ + 2, /* LMP_PING_REQ */ + 2, /* LMP_PING_RES */ +}; + +/* Bluetooth 5.0 specification p. 2589 */ +static const value_string lm_le_opcodes[] = { + {0x0, "LE LL Connection Update Request"}, + {0x1, "LE LL Channel Map Request"}, + {0x2, "LE LL Terminate Indication"}, + {0x3, "LE LL Encryption Request"}, + {0x4, "LE LL Encryption Response"}, + {0x5, "LE LL Start Encryption Request"}, + {0x6, "LE LL Start Encryption Response"}, + {0x7, "LE LL Unknown Response"}, + {0x8, "LE LL Feature Request"}, + {0x9, "LE LL Feature Response"}, + {0xa, "LE LL Pause Encryption Request"}, + {0xb, "LE LL Pause Encryption Response"}, + {0xc, "LE LL Version Indication"}, + {0xd, "LE LL Reject Indication"}, + {0xe, "LE LL Slave Feture Request"}, + {0xf, "LE LL Connection Parameter Request"}, + {0x10, "LE LL Connection Parameter Response"}, + {0x11, "LE LL Extended Reject Indication"}, + {0x12, "LE LL Ping Request"}, + {0x13, "LE LL Ping Response"}, + {0x14, "LE LL Length Request"}, + {0x15, "LE LL Length Response"}, + {0x16, "LE LL Update Indication"}, + {0x17, "LE LL Physical Layers Request"}, + {0x18, "LE LL Physical Layers Response"}, + {0x19, "LE LL Minimum Number of Used Channels Indication"}, + {0xff, "LE LL Broadcom Vendor Specific"}, + {0, NULL}}; + +static const value_string lm_le_opcodes_ext[] = { + {0x1, "LE LL Vendor Specific Feature Request"}, + {0x2, "LE LL Vendor Specific Feature Response"}, + {0x3, "LE LL Vendor Specific Enable Bcs Timeline"}, + {0x4, "LE LL Random Address Change"}, + {0, NULL}}; + +static const true_false_string lm_toggle = { + "true", + "false"}; + +static const true_false_string packet_table_type_bits = { + "EDR", // Enhanced Data Rate + "BR", // Basic Rate +}; + +static const true_false_string packet_role_bits = { + "Slave", + "Master", +}; + +static const value_string packet_types[] = { + /* generic names for unknown logical transport */ + {0x0, "NULL"}, + {0x1, "POLL"}, + {0x2, "FHS"}, + {0x3, "DM1"}, + {0x4, "DH1/2-DH1"}, + {0x5, "HV1"}, + {0x6, "HV2/2-EV3"}, + {0x7, "HV3/EV3/3-EV3"}, + {0x8, "DV/3-DH1"}, + {0x9, "AUX1"}, + {0xa, "DM3/2-DH3"}, + {0xb, "DH3/3-DH3"}, + {0xc, "EV4/2-EV5"}, + {0xd, "EV5/3-EV5"}, + {0xe, "DM5/2-DH5"}, + {0xf, "DH5/3-DH5"}, + {0, NULL}}; + +static const value_string packet_types_br[] = { + /* generic names for unknown logical transport */ + {0x0, "NULL"}, + {0x1, "POLL"}, + {0x2, "FHS"}, + {0x3, "DM1"}, + {0x4, "DH1"}, + {0x9, "AUX1"}, + {0xa, "DM3"}, + {0xb, "DH3"}, + {0xe, "DM5"}, + {0xf, "DH5"}, + {0, NULL}}; + +static const value_string packet_types_edr[] = { + /* generic names for unknown logical transport */ + {0x0, "NULL"}, + {0x1, "POLL"}, + {0x2, "FHS"}, + {0x3, "DM1"}, + {0x4, "2-DH1"}, + {0x8, "3-DH1"}, + {0x9, "AUX1"}, + {0xa, "2-DH3"}, + {0xb, "3-DH3"}, + {0xe, "2-DH5"}, + {0xf, "3-DH5"}, + {0, NULL}}; + +static const value_string sr_modes[] = { + {0x0, "R0"}, + {0x1, "R1"}, + {0x2, "R2"}, + {0x3, "Reserved"}, + {0, NULL}}; + +static const range_string ps_modes[] = { + {0x0, 0x0, "Mandatory scan mode"}, + {0x1, 0x7, "Reserved"}, + {0, 0, NULL}}; + +/* one byte payload header */ +static int dissect_payload_header1(proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *hdr_item; + proto_tree *hdr_tree; + + hdr_item = proto_tree_add_item(tree, hf_h4bcm_pldhdr, tvb, offset, 1, ENC_NA); + hdr_tree = proto_item_add_subtree(hdr_item, ett_h4bcm_pldhdr); + + proto_tree_add_item(hdr_tree, hf_h4bcm_llid, tvb, offset, 1, ENC_NA); + proto_tree_add_item(hdr_tree, hf_h4bcm_pldflow, tvb, offset, 1, ENC_NA); + proto_tree_add_item(hdr_tree, hf_h4bcm_length, tvb, offset, 1, ENC_NA); + + /* payload length */ + return tvb_get_guint8(tvb, offset) >> 3; +} + +/* two byte payload header */ +static int dissect_payload_header_acl_edr(proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *hdr_item; + proto_tree *hdr_tree; + + hdr_item = proto_tree_add_item(tree, hf_h4bcm_aclhdr, tvb, offset, 2, ENC_LITTLE_ENDIAN); + hdr_tree = proto_item_add_subtree(hdr_item, ett_h4bcm_aclhdr); + + proto_tree_add_item(hdr_tree, hf_h4bcm_llid_acl, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(hdr_tree, hf_h4bcm_pldflow_acl, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(hdr_tree, hf_h4bcm_length_acl, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(hdr_tree, hf_h4bcm_rfu, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN); + + /* payload length */ + return (tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN) >> 3) & 0x3FF; +} + +/* Dissect common LM and LE LM header */ +static void dissect_lm_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int is_sent) +{ + guint32 mac; + gchar *mac_string = (gchar *)g_malloc(12); + + /* LMP and LCP are only transmitted within full diagnostic reports */ + DISSECTOR_ASSERT(tvb_reported_length(tvb) == 63); + + /* clock of the BT master */ + proto_tree_add_item(tree, hf_h4bcm_clock, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* decode and display MAC address in src/dst fields */ + mac = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN); + g_snprintf(mac_string, 12, + "%02x:%02x:%02x:%02x", + (mac & 0xff000000) >> 24, + (mac & 0x00ff0000) >> 16, + (mac & 0x0000ff00) >> 8, + (mac & 0x000000ff)); + + proto_tree_add_item(tree, hf_h4bcm_maclow, tvb, offset, 4, ENC_LITTLE_ENDIAN); + + if (is_sent == 1) + { + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "controller"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, mac_string); + } + else + { + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, mac_string); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "controller"); + } +} + +/* Pass LMP handling to existing dissector if available */ +static void dissect_lmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + int len; + int opcode; + int dm1_hdr; + tvbuff_t *pld_tvb; + + /* LMP is only transmitted within full diagnostic reports */ + DISSECTOR_ASSERT(tvb_reported_length(tvb) == 63); + + /* DM1 header is common in both directions */ + dm1_hdr = tvb_get_guint8(tvb, offset); + len = dissect_payload_header1(tree, tvb, offset); + + /* Longest LMP packet is 17 bytes */ + DISSECTOR_ASSERT(len <= 17); + + offset += 1; + + /* In receive direction, diagnostic LMP always sends a packet length 17, + * which makes failed assertions inside the LMP decoder... + * The fixed length corresponds to a DM1 header of 0x8f in flow direction + * receive, so we can check this directly instead of maybe re-checking + * valid length 17 in sent direction. + * This fix is really ugly, but it makes the LMP decoders assertions pass. + */ + if (dm1_hdr == 0x8f) + { + /* Get normal / extended opcode length. Will be 0 if undefined. */ + len = 0; + opcode = tvb_get_guint8(tvb, offset) >> 1; + if (opcode <= 65) + { + len = lmp_lengths[opcode]; + } + else if (opcode == 127) + { + opcode = tvb_get_guint8(tvb, offset + 1); + if (opcode <= 32) + { + len = lmp_lengths_ext[opcode]; + } + } + } + + /* Check that we have a LMP dissector or else just display raw payload */ + if (btlmp_handle && len != 0) + { + pld_tvb = tvb_new_subset_length_caplen(tvb, offset, len, len); + call_dissector(btlmp_handle, pld_tvb, pinfo, tree); + } + else + { + /* Maximum (constant) LMP length is 17 */ + proto_tree_add_item(tree, hf_h4bcm_payload, tvb, offset, 17, ENC_LITTLE_ENDIAN); + } +} + +/* Pass ACL handling to existing dissector if available */ +static int dissect_acl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + tvbuff_t *pld_tvb; + int len; + int opcode; + int offset = 0; + int llid; + + // struct timespec start_time; + // struct timespec end_time; + // clock_gettime(CLOCK_MONOTONIC, &start_time); + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACL"); + + len = dissect_payload_header_acl_edr(tree, tvb, offset); + llid = tvb_get_guint8(tvb, offset) & 0x03; + + offset += 2; + + if (len) + { + pld_tvb = tvb_new_subset_length(tvb, offset, len); + switch (llid) + { + case 1: + proto_tree_add_item(tree, hf_h4bcm_acl_fragment, tvb, offset, len, ENC_LITTLE_ENDIAN); + switch (pinfo->p2p_dir) + { + case P2P_DIR_SENT: + col_set_str(pinfo->cinfo, COL_INFO, "TX --> Fragment"); + break; + case P2P_DIR_RECV: + col_set_str(pinfo->cinfo, COL_INFO, "RX <-- Fragment"); + break; + default: + break; + } + break; + + case 2: + call_dissector(btl2cap_handle, pld_tvb, pinfo, tree); + break; + + case 3: + call_dissector(btlmp_handle, pld_tvb, pinfo, tree); + break; + + default: + proto_tree_add_item(tree, hf_h4bcm_payload, tvb, offset, len, ENC_LITTLE_ENDIAN); + break; + } + } + else + { + proto_tree_add_item(tree, hf_h4bcm_payload, tvb, offset, len, ENC_LITTLE_ENDIAN); + } + + return tvb_reported_length(tvb); +} + +static void dissect_fhs(proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *fhs_item, *psmode_item; + proto_tree *fhs_tree; + const gchar *description; + guint8 psmode; + + fhs_item = proto_tree_add_item(tree, hf_btbbd_fhs, tvb, offset, -1, ENC_NA); + fhs_tree = proto_item_add_subtree(fhs_item, ett_btbbd_fhs); + + /* Use proto_tree_add_bits_item() to get around 32bit limit on bitmasks */ + proto_tree_add_bits_item(fhs_tree, hf_btbbd_fhs_parity, tvb, offset * 8, 34, ENC_LITTLE_ENDIAN); + /* proto_tree_add_item(fhs_tree, hf_btbb_fhs_parity, tvb, offset, 5, ENC_LITTLE_ENDIAN); */ + offset += 4; + + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_lap, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 3; + + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_eir, tvb, offset, 1, ENC_NA); + /* skipping 1 undefined bit */ + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_sr, tvb, offset, 1, ENC_NA); + /* skipping 2 reserved bits */ + offset += 1; + + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_uap, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_nap, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_class, tvb, offset, 3, ENC_LITTLE_ENDIAN); + offset += 3; + + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_ltaddr, tvb, offset, 1, ENC_NA); + proto_tree_add_item(fhs_tree, hf_btbbd_fhs_clk, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 3; + + psmode = tvb_get_guint8(tvb, offset); + description = try_rval_to_str(psmode, ps_modes); + psmode_item = proto_tree_add_item(fhs_tree, hf_btbbd_fhs_psmode, tvb, offset, 1, ENC_NA); + if (description) + proto_item_append_text(psmode_item, " (%s)", description); + offset += 1; +} + +static int dissect_bt_baseband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + tvbuff_t *pld_tvb; + int offset = 0; + int bb_type; + int ptt; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Baseband"); + + // // Baseband protocol + proto_item *btbb_item = proto_tree_add_item(tree, hf_btbbd, tvb, offset, 11, ENC_LITTLE_ENDIAN); + proto_tree *btbb_tree = proto_item_add_subtree(btbb_item, ett_btbbd); + // // Baseband Metadata + proto_item *btbb_meta_item = proto_tree_add_item(btbb_tree, hf_btbbd_meta, tvb, offset, 5, ENC_LITTLE_ENDIAN); + proto_tree *btbb_meta_tree = proto_item_add_subtree(btbb_meta_item, ett_btbbd_meta); + proto_tree_add_item(btbb_meta_tree, hf_btbbd_clk, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + proto_tree_add_item(btbb_meta_tree, hf_btbbd_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + proto_tree_add_item(btbb_meta_tree, hf_btbbd_ptt, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(btbb_meta_tree, hf_btbbd_role, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(btbb_meta_tree, hf_btbbd_tx_encrypted, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(btbb_meta_tree, hf_btbbd_rx_encrypted, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(btbb_meta_tree, hf_btbbd_is_eir, tvb, offset, 1, ENC_LITTLE_ENDIAN); + // ptt = tvb_get_guint8(tvb, offset) & 0b1; + offset += 1; + // Baseband Packet Header + proto_item *btbb_pkthdr_item = proto_tree_add_item(btbb_tree, hf_btbbd_pkthdr, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree *btbb_pkthdr_tree = proto_item_add_subtree(btbb_pkthdr_item, ett_btbbd_pkthdr); + proto_tree_add_item(btbb_pkthdr_tree, hf_btbbd_ltaddr, tvb, offset, 1, ENC_NA); + proto_tree_add_item_ret_uint(btbb_pkthdr_tree, hf_btbbd_type, tvb, offset, 1, ENC_NA, &bb_type); + // if (!ptt) + // proto_tree_add_item_ret_uint(btbb_pkthdr_tree, hf_btbbd_type_br, tvb, offset, 1, ENC_NA, &bb_type); + // else + // proto_tree_add_item_ret_uint(btbb_pkthdr_tree, hf_btbbd_type_edr, tvb, offset, 1, ENC_NA, &bb_type); + proto_tree_add_item(btbb_pkthdr_tree, hf_btbbd_flow, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(btbb_pkthdr_tree, hf_btbbd_arqn, tvb, offset, 1, ENC_NA); + proto_tree_add_item(btbb_pkthdr_tree, hf_btbbd_seqn, tvb, offset, 1, ENC_NA); + proto_tree_add_item(btbb_pkthdr_tree, hf_btbbd_hec, tvb, offset, 1, ENC_NA); + offset += 1; + + switch (pinfo->p2p_dir) + { + case P2P_DIR_SENT: + col_set_str(pinfo->cinfo, COL_INFO, "TX --> "); + break; + case P2P_DIR_RECV: + col_set_str(pinfo->cinfo, COL_INFO, "RX <-- "); + break; + default: + break; + } + + /* payload */ + switch (bb_type) + { + case 0x0: /* NULL */ + col_append_str(pinfo->cinfo, COL_INFO, "NULL"); + break; + case 0x1: /* POLL */ + col_append_str(pinfo->cinfo, COL_INFO, "POLL"); + break; + case 0x2: /* FHS */ + col_append_str(pinfo->cinfo, COL_INFO, "FHS"); + dissect_fhs(tree, tvb, offset); + break; + case 0x3: /* DM1 */ + case 0x4: /* DH1/2-DH1 */ + case 0x5: /* HV1 */ + case 0x6: /* HV2/2-EV3 */ + case 0x7: /* HV3/EV3/3-EV3 */ + case 0x8: /* DV/3-DH1 */ + case 0x9: /* AUX1 */ + case 0xa: /* DM3/2-DH3 */ + case 0xb: /* DH3/3-DH3 */ + case 0xc: /* EV4/2-EV5 */ + case 0xd: /* EV5/3-EV5 */ + case 0xe: /* DM5/2-DH5 */ + case 0xf: /* DH5/3-DH5 */ + pld_tvb = tvb_new_subset_remaining(tvb, offset); + dissect_acl(pld_tvb, pinfo, tree, &ptt); + break; + default: + break; + } + + return tvb_reported_length(tvb); +} + +/* TODO placeholder for responses we don't know yet */ +static void dissect_unkn_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + DISSECTOR_ASSERT(tvb_reported_length(tvb) == 63); + + proto_tree_add_item(tree, hf_h4bcm_type, tvb, offset - 1, 1, ENC_NA); + + /* Sent from chip to host */ + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "controller"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "host"); +} + +/* TODO placeholder for commands with arguments that are none or unknown */ +static void dissect_unkn_get(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1); + + proto_tree_add_item(tree, hf_h4bcm_type, tvb, offset - 1, 1, ENC_NA); + + /* Sent from host to chip */ + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "host"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "controller"); +} + +/* ACL BR stats */ +static void dissect_acl_br_stats(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) + +{ + proto_item *stats_item; + proto_tree *stats_tree; + + DISSECTOR_ASSERT(tvb_reported_length(tvb) == 63); + + /* Sent from chip to host */ + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "controller"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "host"); + + /* Display previous item as tree header */ + stats_item = proto_tree_add_item(tree, hf_h4bcm_type, tvb, offset - 1, 1, ENC_NA); + + /* Make stats subtree */ + stats_tree = proto_item_add_subtree(stats_item, ett_h4bcm_acl_br_stats); + + proto_tree_add_item(stats_tree, hf_h4bcm_stats_null_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_poll_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm1_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dh1_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dv_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_aux1_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm3_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dh3_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm5_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dh5_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_null_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_poll_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm1_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dh1_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dv_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_aux1_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm3_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dh3_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm5_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dh5_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + /* FIXME within the next 16 bytes, some are 4 bytes long ... not 100% sure which */ + proto_tree_add_item(stats_tree, hf_h4bcm_stats_acl_rx, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_acl_tx, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_hec_err, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_crc_err, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_seqn_rep, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_soft_rst, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_test_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_test_rx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_test_err, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; +} + +/* ACL EDR stats */ +static void dissect_acl_edr_stats(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + proto_item *stats_item; + proto_tree *stats_tree; + + DISSECTOR_ASSERT(tvb_reported_length(tvb) == 63); + + /* Sent from chip to host */ + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "controller"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "host"); + + /* Display previous item as tree header */ + stats_item = proto_tree_add_item(tree, hf_h4bcm_type, tvb, offset - 1, 1, ENC_NA); + + /* Make stats subtree */ + stats_tree = proto_item_add_subtree(stats_item, ett_h4bcm_acl_edr_stats); + + proto_tree_add_item(stats_tree, hf_h4bcm_stats_null_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_poll_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm1_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_2dh1_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_3dh1_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_2dh3_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_3dh3_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_2dh5_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_3dh5_rcvd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + offset += 2; /* with this offset, null packets match */ + proto_tree_add_item(stats_tree, hf_h4bcm_stats_null_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_poll_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_dm1_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_2dh1_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_3dh1_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_2dh3_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_3dh3_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_2dh5_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_3dh5_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + offset += 2; /* with this offset, acl bytes are correct */ + proto_tree_add_item(stats_tree, hf_h4bcm_stats_acl_rx, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_acl_tx, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_hec_err, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_crc_err, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_seqn_rep, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_soft_rst, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_test_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_test_rx, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(stats_tree, hf_h4bcm_stats_test_err, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; +} + +/* LL_VERSION_IND p. 2594 + */ +static void dissect_ll_version_ind(proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_tree_add_item(tree, hf_h4bcm_ll_version_ind_versnr, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_h4bcm_ll_version_ind_compid, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_h4bcm_ll_version_ind_subversnr, tvb, offset, 2, ENC_LITTLE_ENDIAN); +} + +/* LM LE + * Most of this is already implemented in "btle" in Wireshark... + * But somewhat different format :( So we do it here. + */ +static void dissect_lm_le(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int is_sent) +{ + int opcode; + int opcode_ext; + guint64 mac; + gchar *mac_string = (gchar *)g_malloc(18); + + /* LMP and LCP are only transmitted within full diagnostic reports */ + DISSECTOR_ASSERT(tvb_reported_length(tvb) == 63); + + /* clock of the BT master */ + proto_tree_add_item(tree, hf_h4bcm_clock, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* standard MAC address this time */ + mac = tvb_get_guint64(tvb, offset - 2, ENC_BIG_ENDIAN); + g_snprintf(mac_string, 18, + "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int)((mac & 0xff0000000000) >> 40), + (unsigned int)((mac & 0x00ff00000000) >> 32), + (unsigned int)((mac & 0x0000ff000000) >> 24), + (unsigned int)((mac & 0x000000ff0000) >> 16), + (unsigned int)((mac & 0x00000000ff00) >> 8), + (unsigned int)((mac & 0x0000000000ff))); + proto_tree_add_item(tree, hf_h4bcm_le_ether, tvb, offset, 6, ENC_LITTLE_ENDIAN); + offset += 6; + + if (is_sent == 1) + { + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "controller"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, mac_string); + } + else + { + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, mac_string); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "controller"); + } + + /* Handle (only 1 byte, even though it can be 2 bytes long?!) */ + proto_tree_add_item(tree, hf_h4bcm_le_handle, tvb, offset, 1, ENC_NA); + offset += 1; + + opcode = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_h4bcm_le_opcode, tvb, offset, 1, ENC_NA); + col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, lm_le_opcodes, "LE LL Unknown Opcode (%d)")); + offset += 1; + + switch (opcode) + { + case 0x0c: + dissect_ll_version_ind(tree, tvb, offset); + break; + /* Broadcom vendor specific stuff... */ + case 0xff: + opcode_ext = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_h4bcm_le_opcode_ext, tvb, offset, 1, ENC_NA); + col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode_ext, lm_le_opcodes_ext, "LE LL Unknown VSC Opcode (%d)")); + offset += 1; + break; + default: + break; + } +} + +/* Show if LM + LM LE logging was enabled or disabled */ +static void dissect_lm_toggle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1); + + /* Sent from host UART to chip */ + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "host"); + col_set_str(pinfo->cinfo, COL_RES_DL_DST, "controller"); + + /* OFF and ON */ + proto_tree_add_item(tree, hf_h4bcm_lm_toggle, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; +} + +/* dissect a packet */ +static int +dissect_h4bcm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + proto_item *h4bcm_item; + proto_tree *h4bcm_tree; + int offset; + int h4bcm_type; + + /* sanity check: length */ + if (tvb_reported_length(tvb) < 1) + /* bad length: look for a different dissector */ + return 0; + + /* fprintf(stderr, "total len %d\n", tvb_reported_length(tvb)); */ + + /* make entries in protocol column and info column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI H4 Broadcom"); + + /* create display subtree for the protocol */ + offset = 0; + h4bcm_item = proto_tree_add_item(tree, proto_h4bcm, tvb, offset, -1, ENC_NA); + h4bcm_tree = proto_item_add_subtree(h4bcm_item, ett_h4bcm); + + h4bcm_type = tvb_get_guint8(tvb, offset); + col_add_str(pinfo->cinfo, COL_INFO, val_to_str(h4bcm_type, h4bcm_types, "Unknown Type (%d)")); + offset += 1; + + switch (h4bcm_type) + { + case DIA_LM_SENT: + dissect_lm_header(tvb, pinfo, h4bcm_tree, offset, 1); + offset += 8; + dissect_lmp(tvb, pinfo, h4bcm_tree, offset); + break; + case DIA_LM_RECV: + dissect_lm_header(tvb, pinfo, h4bcm_tree, offset, 0); + offset += 11; + dissect_lmp(tvb, pinfo, h4bcm_tree, offset); + break; + case DIA_ACL_BR_RESP: + dissect_acl_br_stats(tvb, pinfo, h4bcm_tree, offset); + break; + case DIA_ACL_EDR_RESP: + dissect_acl_edr_stats(tvb, pinfo, h4bcm_tree, offset); + break; + case DIA_LE_SENT: + dissect_lm_le(tvb, pinfo, h4bcm_tree, offset, 1); + break; + case DIA_LE_RECV: + dissect_lm_le(tvb, pinfo, h4bcm_tree, offset, 0); + break; + case DIA_LM_ENABLE: + dissect_lm_toggle(tvb, pinfo, h4bcm_tree, offset); + break; + case DIA_MEM_PEEK_RESP: + case DIA_MEM_DUMP_RESP: + case DIA_TEST_COMPL: + case DIA_MEM_POKE_RESP: + case DIA_CPU_LOAD_RESP: + case DIA_AUX_RESP: + case DIA_ACL_UNKN1_RESP: + case DIA_ACL_UNKN2_RESP: + dissect_unkn_resp(tvb, pinfo, h4bcm_tree, offset); + break; + case DIA_ACL_BR_RESET: + case DIA_ACL_BR_GET: + case DIA_ACL_EDR_GET: + case DIA_AUX_GET: + case DIA_ACL_UNKN1_GET: + case DIA_ACL_UNKN2_GET: + case DIA_CON_GET: + case DIA_MEM_PEEK_GET: + case DIA_MEM_POKE_GET: + case DIA_MEM_DUMP_GET: + case DIA_PKT_TEST: + dissect_unkn_get(tvb, pinfo, h4bcm_tree, offset); + break; + default: + break; + } + + /* Return the amount of data this dissector was able to dissect */ + return tvb_reported_length(tvb); +} + +/* register the protocol with Wireshark */ +void proto_register_h4bcm(void) +{ + /* list of fields */ + static hf_register_info hf[] = { + {&hf_h4bcm_type, + {"Type", "h4bcm.type", + FT_UINT8, BASE_HEX, VALS(h4bcm_types), 0x0, + "Diagnostic Information Type", HFILL}}, + {&hf_h4bcm_clock, + {"Clock", "h4bcm.clock", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Bluetooth Master Clock", HFILL}}, + {&hf_h4bcm_maclow, + {"Remote MAC Address", "h4bcm.maclow", + FT_BYTES, SEP_COLON, NULL, 0x0, + "Lower MAC address part, sufficient for l2ping ff:ff:maclow", HFILL}}, + {&hf_h4bcm_pldhdr, + {"Payload Header", "h4bcm.pldhdr", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_aclhdr, + {"ACL Header", "h4bcm.aclhdr", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_llid, + {"LLID", "h4bcm.llid", + FT_UINT8, BASE_HEX, VALS(llid_codes), 0x03, + "Logical Link ID", HFILL}}, + {&hf_h4bcm_llid_acl, + {"LLID", "h4bcm.llid_acl", + FT_UINT16, BASE_HEX, VALS(llid_codes), 0x03, + "Logical Link ID", HFILL}}, + {&hf_h4bcm_pldflow_acl, + {"Flow", "h4bcm.flow_acl", + FT_BOOLEAN, 16, NULL, 0x04, + "Payload Flow indication", HFILL}}, + {&hf_h4bcm_rfu, + {"RFU", "h4bcm.rfu_acl", + FT_UINT16, BASE_HEX, 0, 0xE000, + "RFU", HFILL}}, + {&hf_h4bcm_pldflow, + {"Flow", "h4bcm.flow", + FT_BOOLEAN, 8, NULL, 0x04, + "Payload Flow indication", HFILL}}, + {&hf_h4bcm_length, + {"Length", "h4bcm.length", + FT_UINT8, BASE_DEC, NULL, 0xf8, + "Payload Length", HFILL}}, + {&hf_h4bcm_length_acl, + {"Length", "h4bcm.length_acl", + FT_UINT16, BASE_DEC, NULL, 0x1ff8, + "Payload Length", HFILL}}, + {&hf_h4bcm_payload, + {"Payload", "h4bcm.payload", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_acl_fragment, + {"Payload", "h4bcm.acl_fragment", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_lm_toggle, + {"LM and LM LE Logging", "h4bcm.logging", + FT_BOOLEAN, 8, TFS(&lm_toggle), 0x01, + NULL, HFILL}}, + {&hf_h4bcm_stats_null_rcvd, + {"Null Packets Received", "h4bcm.stats.null_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_poll_rcvd, + {"Poll Packets Received", "h4bcm.stats.poll_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dm1_rcvd, + {"DM1 Packets Received", "h4bcm.stats.dm1_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dh1_rcvd, + {"DH1 Packets Received", "h4bcm.stats.dh1_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dv_rcvd, + {"DV Packets Received", "h4bcm.stats.dv_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_aux1_rcvd, + {"AUX1 Packets Received", "h4bcm.stats.aux1_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dm3_rcvd, + {"DM3 Packets Received", "h4bcm.stats.dm3_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dh3_rcvd, + {"DH3 Packets Received", "h4bcm.stats.dh3_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dm5_rcvd, + {"DM5 Packets Received", "h4bcm.stats.dm5_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dh5_rcvd, + {"DH5 Packets Received", "h4bcm.stats.dh5_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_null_tx, + {"Null Packets Transmitted", "h4bcm.stats.null_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_poll_tx, + {"Poll Packets Transmitted", "h4bcm.stats.poll_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dm1_tx, + {"DM1 Packets Transmitted", "h4bcm.stats.dm1_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dh1_tx, + {"DH1 Packets Transmitted", "h4bcm.stats.dh1_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dv_tx, + {"DV Packets Transmitted", "h4bcm.stats.dv_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_aux1_tx, + {"AUX1 Packets Transmitted", "h4bcm.stats.aux1_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dm3_tx, + {"DM3 Packets Transmitted", "h4bcm.stats.dm3_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dh3_tx, + {"DH3 Packets Transmitted", "h4bcm.stats.dh3_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dm5_tx, + {"DM5 Packets Transmitted", "h4bcm.stats.dm5_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_dh5_tx, + {"DH5 Packets Transmitted", "h4bcm.stats.dh5_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_acl_rx, + {"Total Received ACL Bytes", "h4bcm.stats.acl_rx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_acl_tx, + {"Total Transmitted ACL Bytes", "h4bcm.stats.acl_tx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_hec_err, + {"HEC Errors", "h4bcm.stats.hec_err", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_crc_err, + {"CRC Errors", "h4bcm.stats.crc_err", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_seqn_rep, + {"Seqn Repeat", "h4bcm.stats.seqn_rep", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_soft_rst, + {"Soft Reset", "h4bcm.stats.soft_rst", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_test_tx, + {"TestMode Transmitted Packets", "h4bcm.stats.test_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_test_rx, + {"TestMode Received Packets", "h4bcm.stats.test_rx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_test_err, + {"TestMode Packet Errors", "h4bcm.stats.test_err", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_2dh1_rcvd, + {"2DH1 Packets Received", "h4bcm.stats.2dh1_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_3dh1_rcvd, + {"3DH1 Packets Received", "h4bcm.stats.3dh1_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_2dh3_rcvd, + {"2DH3 Packets Received", "h4bcm.stats.2dh3_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_3dh3_rcvd, + {"3DH3 Packets Received", "h4bcm.stats.3dh3_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_2dh5_rcvd, + {"2DH5 Packets Received", "h4bcm.stats.2dh5_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_3dh5_rcvd, + {"3DH5 Packets Received", "h4bcm.stats.3dh5_rcvd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_2dh1_tx, + {"2DH1 Packets Transmitted", "h4bcm.stats.2dh1_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_3dh1_tx, + {"3DH1 Packets Transmitted", "h4bcm.stats.3dh1_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_2dh3_tx, + {"2DH3 Packets Transmitted", "h4bcm.stats.2dh3_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_3dh3_tx, + {"3DH3 Packets Transmitted", "h4bcm.stats.3dh3_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_2dh5_tx, + {"2DH5 Packets Transmitted", "h4bcm.stats.2dh5_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_stats_3dh5_tx, + {"3DH5 Packets Transmitted", "h4bcm.stats.3dh5_tx", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_le_ether, + {"Remote MAC Address", "h4bcm.le.address", + FT_BYTES, SEP_COLON, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_le_handle, + {"Handle", "h4bcm.le.handle", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_h4bcm_le_opcode, + {"Opcode", "h4bcm.le.opcode", + FT_UINT8, BASE_HEX, VALS(lm_le_opcodes), 0x0, + NULL, HFILL}}, + {&hf_h4bcm_le_opcode_ext, + {"Broadcom Specific Opcode", "h4bcm.le.opcodeext", + FT_UINT8, BASE_HEX, VALS(lm_le_opcodes_ext), 0x0, + NULL, HFILL}}, + {&hf_h4bcm_ll_version_ind_versnr, + {"VersNr", "h4bcm.le.versnr", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Version", HFILL}}, + {&hf_h4bcm_ll_version_ind_subversnr, + {"SubVersNr", "h4bcm.le.subversnr", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Subversion", HFILL}}, + {&hf_h4bcm_ll_version_ind_compid, + {"CompID", "h4bcm.le.compid", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Company", HFILL}}, + {&hf_btbbd, + {"Baseband", "btbbd", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_meta, + {"Meta Data", "btbbd.meta", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_clk, + {"CLK", "btbbd.clk", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_channel, + {"Channel", "btbbd.ch", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_ptt, + {"Table Type", "btbbd.ptt", + FT_BOOLEAN, 8, TFS(&packet_table_type_bits), 0b00000001, + NULL, HFILL}}, + {&hf_btbbd_role, + {"Role", "btbbd.role", + FT_BOOLEAN, 8, TFS(&packet_role_bits), 0b00000010, + NULL, HFILL}}, + {&hf_btbbd_tx_encrypted, + {"TX Enc.", "btbbd.txenc", + FT_BOOLEAN, 8, TFS(&lm_toggle), 0b00100000, + NULL, HFILL}}, + {&hf_btbbd_rx_encrypted, + {"RX Enc.", "btbbd.rxenc", + FT_BOOLEAN, 8, TFS(&lm_toggle), 0b01000000, + NULL, HFILL}}, + {&hf_btbbd_is_eir, + {"Is EIR", "btbbd.iseir", + FT_BOOLEAN, 8, TFS(&lm_toggle), 0b10000000, + NULL, HFILL}}, + {&hf_btbbd_pkthdr, + {"Packet Header", "btbbd.pkthdr", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_ltaddr, + {"LT_ADDR", "btbbd.lt_addr", + FT_UINT16, BASE_HEX, NULL, 0x07, + NULL, HFILL}}, + {&hf_btbbd_type, + {"Type", "btbbd.type", + FT_UINT16, BASE_HEX, VALS(packet_types), 0x78, + NULL, HFILL}}, + {&hf_btbbd_type_br, + {"Type", "btbbd.type_br", + FT_UINT16, BASE_HEX, VALS(packet_types_br), 0x78, + NULL, HFILL}}, + {&hf_btbbd_type_edr, + {"Type", "btbbd.type_edr", + FT_UINT16, BASE_HEX, VALS(packet_types_edr), 0x78, + NULL, HFILL}}, + {&hf_btbbd_flow, + {"FLOW", "btbbd.flow", + FT_BOOLEAN, 16, NULL, 0x80, + NULL, HFILL}}, + {&hf_btbbd_arqn, + {"ARQN", "btbbd.arqn", + FT_BOOLEAN, 8, NULL, 0x1, + NULL, HFILL}}, + {&hf_btbbd_seqn, + {"SEQN", "btbbd.seqn", + FT_BOOLEAN, 8, NULL, 0x2, + NULL, HFILL}}, + {&hf_btbbd_hec, + {"HEC", "btbbd.hec", + FT_UINT8, BASE_HEX, NULL, 0xFC, + NULL, HFILL}}, + {&hf_btbbd_fhs, + {"FHS", "fhs", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_fhs_parity, + {"Parity", "fhs.parity", + /* FIXME this doesn't work because bitmasks can only be 32 bits */ + FT_UINT64, BASE_HEX, NULL, /*0x00000003ffffffffULL,*/ 0x0, + "LAP parity", HFILL}}, + {&hf_btbbd_fhs_lap, + {"LAP", "fhs.lap", + FT_UINT24, BASE_HEX, NULL, 0x03fffffc, + "Lower Address Part", HFILL}}, + {&hf_btbbd_fhs_eir, + {"EIR", "fhs.eir", + FT_BOOLEAN, 8, NULL, 0x04, + "Extended Inquiry Response packet may follow", HFILL}}, + {&hf_btbbd_fhs_sr, + {"SR", "fhs.sr", + FT_UINT8, BASE_HEX, VALS(sr_modes), 0x30, + "Scan Repetition", HFILL}}, + {&hf_btbbd_fhs_uap, + {"UAP", "fhs.uap", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Upper Address Part", HFILL}}, + {&hf_btbbd_fhs_nap, + {"NAP", "fhs.nap", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Non-Significant Address Part", HFILL}}, + {&hf_btbbd_fhs_class, /* TODO: More options */ + {"Class of Device", "fhs.class", + FT_UINT24, BASE_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_btbbd_fhs_ltaddr, + {"LT_ADDR", "fhs.lt_addr", + FT_UINT8, BASE_HEX, NULL, 0x07, + "Logical Transport Address", HFILL}}, + {&hf_btbbd_fhs_clk, + {"CLK", "fhs.clk", + FT_UINT32, BASE_HEX, NULL, 0x1ffffff8, + "Clock bits 2 through 27", HFILL}}, + {&hf_btbbd_fhs_psmode, + {"Page Scan Mode", "fhs.psmode", + FT_UINT8, BASE_HEX, NULL, 0xe0, + NULL, HFILL}}, + }; + + /* protocol subtree arrays */ + static gint *ett[] = { + &ett_h4bcm, + &ett_h4bcm_pldhdr, + &ett_h4bcm_aclhdr, + &ett_h4bcm_acl_br_stats, + &ett_h4bcm_acl_edr_stats, + &ett_btbbd, + &ett_btbbd_meta, + &ett_btbbd_pkthdr, + &ett_btbbd_fhs, + }; + + /* register the protocol name and description */ + proto_h4bcm = proto_register_protocol( + "Bluetooth H4 Serial Broadcom Vendor Specific", /* full name */ + "H4 Broadcom", /* short name */ + "h4bcm" /* abbreviation (e.g. for filters) */ + ); + + register_dissector("btacl", dissect_acl, proto_h4bcm); + + /* register the header fields and subtrees used */ + proto_register_field_array(proto_h4bcm, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + +void proto_reg_handoff_h4bcm(void) +{ + dissector_handle_t h4bcm_handle; + + // Original InternalBlue Broadcom dissector + h4bcm_handle = create_dissector_handle(dissect_h4bcm, proto_h4bcm); + dissector_add_uint("hci_h4.type", 0x07, h4bcm_handle); + + // Bluetooth ACL Header (Payload Header) + h4bcm_handle = create_dissector_handle(dissect_acl, proto_h4bcm); + dissector_add_uint("hci_h4.type", 0x08, h4bcm_handle); + + // Bluetooth Baseband (Packet Header) + h4bcm_handle = create_dissector_handle(dissect_bt_baseband, proto_h4bcm); + dissector_add_uint("hci_h4.type", 0x09, h4bcm_handle); + + // PacketLogger + packetlogger_handle = find_dissector("packetlogger"); + dissector_add_uint("hci_h4.type", 0x0A, packetlogger_handle); + + /* LMP dissector from https://github.com/greatscottgadgets/libbtbb */ + btlmp_handle = find_dissector("btlmp"); + btl2cap_handle = find_dissector("btl2cap"); + + // dissector_add_uint("wtap_encap", WTAP_ENCAP_ESPRESSIF_BT, h4bcm_handle); +} + +/* + * 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: + */ diff --git a/dissectors/plugin.c b/dissectors/plugin.c new file mode 100644 index 0000000..6b2b02f --- /dev/null +++ b/dissectors/plugin.c @@ -0,0 +1,40 @@ +/* + * Do not modify this file. Changes will be overwritten. + * + * Generated automatically from /home/matheus/5g/wdissector/libs/wireshark/tools/make-plugin-reg.py. + */ + +#include "config.h" + +#include + +/* plugins are DLLs */ +#define WS_BUILD_DLL +#include "ws_symbol_export.h" + +#include "epan/proto.h" + +WS_DLL_PUBLIC void proto_register_btbrlmp(void); +WS_DLL_PUBLIC void proto_register_h4bcm(void); +WS_DLL_PUBLIC void proto_reg_handoff_btbrlmp(void); +WS_DLL_PUBLIC void proto_reg_handoff_h4bcm(void); + +WS_DLL_PUBLIC const gchar plugin_version[] = PLUGIN_VERSION; +WS_DLL_PUBLIC const int plugin_want_major = VERSION_MAJOR; +WS_DLL_PUBLIC const int plugin_want_minor = VERSION_MINOR; + +WS_DLL_PUBLIC void plugin_register(void); + +void plugin_register(void) +{ + static proto_plugin plug_btbrlmp; + + plug_btbrlmp.register_protoinfo = proto_register_btbrlmp; + plug_btbrlmp.register_handoff = proto_reg_handoff_btbrlmp; + proto_register_plugin(&plug_btbrlmp); + static proto_plugin plug_h4bcm; + + plug_h4bcm.register_protoinfo = proto_register_h4bcm; + plug_h4bcm.register_handoff = proto_reg_handoff_h4bcm; + proto_register_plugin(&plug_h4bcm); +}