ubertooth script

master
Paul Walko 2016-12-17 04:18:30 -05:00
parent 91dc86c072
commit 6330636b28
148 changed files with 26913 additions and 49 deletions

11
ethernet_dhcp Normal file
View File

@ -0,0 +1,11 @@
Description='A basic dhcp ethernet connection'
Interface=eno1
Connection=ethernet
IP=dhcp
#DHCPClient=dhcpcd
#DHCPReleaseOnStop=no
## for DHCPv6
IP6=dhcp
DHCP6Client=dhclient
## for IPv6 autoconfiguration
IP6=stateless

11
ethernet_usb_dhcp Normal file
View File

@ -0,0 +1,11 @@
Description='A basic dhcp ethernet connection'
Interface=enp0s20u1u3
Connection=ethernet
IP=dhcp
#DHCPClient=dhcpcd
#DHCPReleaseOnStop=no
## for DHCPv6
IP6=dhcp
DHCP6Client=dhclient
## for IPv6 autoconfiguration
IP6=stateless

1
install Executable file
View File

@ -0,0 +1 @@
sudo pacman -S syncthing alsa alsa-utils pulseaudio pavucontrol i3 xf86-86-video-amdgpu mesa-libgl lib32-mesa-libgl mesa-vdpau lib32-mesa-vdpau firefox openssh flashplugin

1
install.sh Executable file
View File

@ -0,0 +1 @@
sudo pacman -S syncthing alsa alsa-utils pulseaudio pavucontrol i3 xf86-86-video-amdgpu mesa-libgl lib32-mesa-libgl mesa-vdpau lib32-mesa-vdpau firefox openssh flashplugin

BIN
libbtbb-2015-10-R1.tar.gz Normal file

Binary file not shown.

17
libbtbb-2015-10-R1/.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
*.o
*.so.*
*.so
*.pyc
# Output directory
build/
# wireshark plugins
CMakeCache.txt
CMakeFiles
cmake_install.cmake
install_manifest.txt
plugin.c
wireshark/plugins/btatt/Makefile
wireshark/plugins/btle/Makefile
wireshark/plugins/btsm/Makefile

View File

@ -0,0 +1,21 @@
language: c
cache: apt
sudo: false
addons:
apt:
packages:
- libpcap-dev
compiler:
- clang
- gcc
before_script:
- mkdir build
- cd build
- CFLAGS="-g -Wall -Wextra -Werror -Wno-zero-length-array" cmake ..
script: make

View File

@ -0,0 +1,50 @@
#
# Copyright 2013 Dominic Spill
#
# This file is part of Libbtbb.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
#top level cmake project for libbtbb lib + tools
cmake_minimum_required(VERSION 2.8)
set(MAJOR_VERSION 0)
set(MINOR_VERSION 3)
project(libbtbb_all)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)
set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX")
set( VERSION ${MAJOR_VERSION}.${MINOR_VERSION} )
add_definitions( -DVERSION="${VERSION}" )
# Comment the following out for releases.
set(CMAKE_C_FLAGS "$ENV{CFLAGS}")
add_subdirectory(lib)
if(NOT DISABLE_PYTHON)
add_subdirectory(python)
endif()
# Create uninstall target
configure_file(
${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)
add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)

View File

@ -0,0 +1,12 @@
CMake Settings
==============
The following are flags that may be of use when configuing this project.
* DISABLE_PYTHON
* A boolean flag for building and installing btaptap python tool.
* USE_PCAP
* USE_PCAP=ON - Build with pcap support, the build will fail if
libpcap is not found.
* USE_PCAP=OFF - Disable pcap support will be disabled.
* If left undefined pcap support will be enabled if libpcap is present.

View File

@ -0,0 +1,43 @@
libbtbb
=======
This is the Bluetooth baseband decoding library, forked from the GR-Bluetooth
project. It can be used to extract Bluetooth packet and piconet information
from Ubertooth devices as well as GR-Bluetooth/USRP.
This code is incomplete, it is still under active development. Patches and
bug reports should be submitted to the bug tracker on GitHub:
https://github.com/greatscottgadgets/libbtbb/issues
This software has been developed and tested on Linux, it should work on other
platforms but this has yet to be tested.
Build Instructions
==================
Libbtbb can be built and installed as follows:
```
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
```
This will install the library to /usr/local/lib and the headers to
/usr/local/include, to install to different locations use:
```
$ cmake -DINSTALL_DIR=/path/to/install -DINCLUDE_DIR=/path/to/include ..
```
If you have previous versions of libbtbb, libubertooth or the Ubertooth tools
installed, you can use the cleanup script to remove them:
```
$ sudo cmake/cleanup.sh -d
```
To list the installed files without removing them, use:
```
$ cmake/cleanup.sh
```

View File

@ -0,0 +1,39 @@
#!/bin/bash
# A quick and dirty script to remove old installs of
# libbtbb, libubertooth and associated Ubertooth tools
# Copyright 2014 Dominic Spill
# License: GPL v2
FIND=`which find`
INSTALL_DIRS="/usr /usr/local"
LIBS="btbb ubertooth"
HEADERS="bluetooth_packet.h \
bluetooth_piconet.h \
bluetooth_le_packet.h \
ubertooth_interface.h \
ubertooth_control.h \
ubertooth.h \
"
if [ "$1" == "-d" ]
then
EXEC="-print -exec rm -f {} ;"
echo "Deleting previous installs:"
else
EXEC=-print
echo 'Installed files, use "sudo cleanup.sh -d" to delete these files'
fi
for dir in $INSTALL_DIRS; do
for lib in $LIBS; do
$FIND ${dir}/lib -maxdepth 1 -name "lib$lib.so*" $EXEC
done
for header in $HEADERS; do
$FIND ${dir}/include -maxdepth 1 -name "$header" $EXEC
done
$FIND ${dir}/bin -maxdepth 1 -name "ubertooth-*" $EXEC
done

View File

@ -0,0 +1,32 @@
# http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
IF(EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)

View File

@ -0,0 +1,138 @@
# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
#
# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for
# parsing the arguments given to that macro or function.
# It processes the arguments and defines a set of variables which hold the
# values of the respective options.
#
# The <options> argument contains all options for the respective macro,
# i.e. keywords which can be used when calling the macro without any value
# following, like e.g. the OPTIONAL keyword of the install() command.
#
# The <one_value_keywords> argument contains all keywords for this macro
# which are followed by one value, like e.g. DESTINATION keyword of the
# install() command.
#
# The <multi_value_keywords> argument contains all keywords for this macro
# which can be followed by more than one value, like e.g. the TARGETS or
# FILES keywords of the install() command.
#
# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
# keywords listed in <options>, <one_value_keywords> and
# <multi_value_keywords> a variable composed of the given <prefix>
# followed by "_" and the name of the respective keyword.
# These variables will then hold the respective value from the argument list.
# For the <options> keywords this will be TRUE or FALSE.
#
# All remaining arguments are collected in a variable
# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see whether
# your macro was called with unrecognized parameters.
#
# As an example here a my_install() macro, which takes similar arguments as the
# real install() command:
#
# function(MY_INSTALL)
# set(options OPTIONAL FAST)
# set(oneValueArgs DESTINATION RENAME)
# set(multiValueArgs TARGETS CONFIGURATIONS)
# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
# ...
#
# Assume my_install() has been called like this:
# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
#
# After the cmake_parse_arguments() call the macro will have set the following
# variables:
# MY_INSTALL_OPTIONAL = TRUE
# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
# MY_INSTALL_DESTINATION = "bin"
# MY_INSTALL_RENAME = "" (was not used)
# MY_INSTALL_TARGETS = "foo;bar"
# MY_INSTALL_CONFIGURATIONS = "" (was not used)
# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
#
# You can the continue and process these variables.
#
# Keywords terminate lists of values, e.g. if directly after a one_value_keyword
# another recognized keyword follows, this is interpreted as the beginning of
# the new option.
# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
#=============================================================================
# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
return()
endif()
set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
# first set all result variables to empty/FALSE
foreach(arg_name ${_singleArgNames} ${_multiArgNames})
set(${prefix}_${arg_name})
endforeach()
foreach(option ${_optionNames})
set(${prefix}_${option} FALSE)
endforeach()
set(${prefix}_UNPARSED_ARGUMENTS)
set(insideValues FALSE)
set(currentArgName)
# now iterate over all arguments and fill the result variables
foreach(currentArg ${ARGN})
list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
if(insideValues)
if("${insideValues}" STREQUAL "SINGLE")
set(${prefix}_${currentArgName} ${currentArg})
set(insideValues FALSE)
elseif("${insideValues}" STREQUAL "MULTI")
list(APPEND ${prefix}_${currentArgName} ${currentArg})
endif()
else()
list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
endif()
else()
if(NOT ${optionIndex} EQUAL -1)
set(${prefix}_${currentArg} TRUE)
set(insideValues FALSE)
elseif(NOT ${singleArgIndex} EQUAL -1)
set(currentArgName ${currentArg})
set(${prefix}_${currentArgName})
set(insideValues "SINGLE")
elseif(NOT ${multiArgIndex} EQUAL -1)
set(currentArgName ${currentArg})
set(${prefix}_${currentArgName})
set(insideValues "MULTI")
endif()
endif()
endforeach()
# propagate the result variables to the caller:
foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
endforeach()
set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
endfunction()

View File

@ -0,0 +1,55 @@
# Try to find the libbtbb library
#
# Once done this defines:
# LIBBTBB_FOUND - system has libbtbb
# LIBBTBB_INCLUDE_DIR - the libbtbb include directory
# LIBBTBB_LIBRARIES - Link these to use libbtbb
#
# Copyright (c) 2013 Dominic Spill
if (LIBBTBB_INCLUDE_DIR AND LIBBTBB_LIBRARIES)
# in cache already
set(LIBBTBB_FOUND TRUE)
else (LIBBTBB_INCLUDE_DIR AND LIBBTBB_LIBRARIES)
IF (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
pkg_check_modules(PC_LIBBTBB QUIET libbtbb)
ENDIF(NOT WIN32)
FIND_PATH(LIBBTBB_INCLUDE_DIR
NAMES btbb.h
HINTS $ENV{LIBBTBB_DIR}/include ${PC_LIBBTBB_INCLUDEDIR}
PATHS /usr/include /usr/local/include
/opt/local/include
${CMAKE_SOURCE_DIR}/../libbtbb/src
${LIBBTBB_INCLUDE_DIR}
)
set(libbtbb_library_names btbb)
FIND_LIBRARY(LIBBTBB_LIBRARIES
NAMES ${libbtbb_library_names}
HINTS $ENV{LIBBTBB_DIR}/lib ${PC_LIBBTBB_LIBDIR}
PATHS /usr/local/lib /usr/lib /opt/local/lib ${PC_LIBBTBB_LIBDIR}
${PC_LIBBTBB_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../libbtbb/src
)
if(LIBBTBB_INCLUDE_DIR)
set(CMAKE_REQUIRED_INCLUDES ${LIBBTBB_INCLUDE_DIR})
endif()
if(LIBBTBB_LIBRARIES)
set(CMAKE_REQUIRED_LIBRARIES ${LIBBTBB_LIBRARIES})
endif()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBBTBB DEFAULT_MSG LIBBTBB_LIBRARIES LIBBTBB_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBBTBB_INCLUDE_DIR LIBBTBB_LIBRARIES)
endif (LIBBTBB_INCLUDE_DIR AND LIBBTBB_LIBRARIES)

View File

@ -0,0 +1,146 @@
#
# $Id: FindPCAP.cmake 38372 2011-08-05 18:52:53Z gerald $
#
###################################################################
#
# Copyright (c) 2006 Frederic Heem, <frederic.heem@telsey.it>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the Telsey nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
###################################################################
# - Find pcap
# Find the PCAP includes and library
# http://www.tcpdump.org/
#
# The environment variable PCAPDIR allows to specficy where to find
# libpcap in non standard location.
#
# PCAP_INCLUDE_DIRS - where to find pcap.h, etc.
# PCAP_LIBRARIES - List of libraries when using pcap.
# PCAP_FOUND - True if pcap found.
IF(EXISTS $ENV{PCAPDIR})
FIND_PATH(PCAP_INCLUDE_DIR
NAMES
pcap/pcap.h
pcap.h
PATHS
$ENV{PCAPDIR}
NO_DEFAULT_PATH
)
FIND_LIBRARY(PCAP_LIBRARY
NAMES
pcap
PATHS
$ENV{PCAPDIR}
NO_DEFAULT_PATH
)
ELSE(EXISTS $ENV{PCAPDIR})
FIND_PATH(PCAP_INCLUDE_DIR
NAMES
pcap/pcap.h
pcap.h
HINTS
/usr/local/opt/libpcap/include
)
FIND_LIBRARY(PCAP_LIBRARY
NAMES
pcap
HINTS
/usr/local/opt/libpcap/lib
)
ENDIF(EXISTS $ENV{PCAPDIR})
SET(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR})
SET(PCAP_LIBRARIES ${PCAP_LIBRARY})
IF(PCAP_INCLUDE_DIRS)
MESSAGE(STATUS "Pcap include dirs set to ${PCAP_INCLUDE_DIRS}")
ELSE(PCAP_INCLUDE_DIRS)
MESSAGE(FATAL " Pcap include dirs cannot be found")
ENDIF(PCAP_INCLUDE_DIRS)
IF(PCAP_LIBRARIES)
MESSAGE(STATUS "Pcap library set to ${PCAP_LIBRARIES}")
ELSE(PCAP_LIBRARIES)
MESSAGE(FATAL "Pcap library cannot be found")
ENDIF(PCAP_LIBRARIES)
#Functions
INCLUDE(CheckFunctionExists)
INCLUDE(CheckVariableExists)
SET(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS})
SET(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES})
CHECK_VARIABLE_EXISTS("pcap_version" HAVE_PCAP_VERSION)
CHECK_FUNCTION_EXISTS("pcap_open_dead" HAVE_PCAP_OPEN_DEAD)
CHECK_FUNCTION_EXISTS("pcap_freecode" HAVE_PCAP_FREECODE)
#
# Note: for pcap_breakloop() and pcap_findalldevs(), the autoconf script
# checks for more than just whether the function exists, it also checks
# for whether pcap.h declares it; Mac OS X software/security updates can
# update libpcap without updating the headers.
#
CHECK_FUNCTION_EXISTS("pcap_breakloop" HAVE_PCAP_BREAKLOOP)
CHECK_FUNCTION_EXISTS("pcap_create" HAVE_PCAP_CREATE)
CHECK_FUNCTION_EXISTS("pcap_datalink_name_to_val" HAVE_PCAP_DATALINK_NAME_TO_VAL)
CHECK_FUNCTION_EXISTS("pcap_datalink_val_to_description" HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
CHECK_FUNCTION_EXISTS("pcap_datalink_val_to_name" HAVE_PCAP_DATALINK_VAL_TO_NAME)
CHECK_FUNCTION_EXISTS("pcap_findalldevs" HAVE_PCAP_FINDALLDEVS)
CHECK_FUNCTION_EXISTS("pcap_free_datalinks" HAVE_PCAP_FREE_DATALINKS)
CHECK_FUNCTION_EXISTS("pcap_get_selectable_fd" HAVE_PCAP_GET_SELECTABLE_FD)
CHECK_FUNCTION_EXISTS("pcap_lib_version" HAVE_PCAP_LIB_VERSION)
CHECK_FUNCTION_EXISTS("pcap_list_datalinks" HAVE_PCAP_LIST_DATALINKS)
CHECK_FUNCTION_EXISTS("pcap_set_datalink" HAVE_PCAP_SET_DATALINK)
# Remote pcap checks
CHECK_FUNCTION_EXISTS("pcap_open" H_PCAP_OPEN)
CHECK_FUNCTION_EXISTS("pcap_findalldevs_ex" H_FINDALLDEVS_EX)
CHECK_FUNCTION_EXISTS("pcap_createsrcstr" H_CREATESRCSTR)
if(H_PCAP_OPEN AND H_FINDALLDEVS_EX AND H_CREATESRCSTR)
SET(HAVE_PCAP_REMOTE 1)
SET(HAVE_REMOTE 1)
endif()
# reset vars
SET(CMAKE_REQUIRED_INCLUDES "")
SET(CMAKE_REQUIRED_LIBRARIES "")
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCAP DEFAULT_MSG PCAP_INCLUDE_DIRS PCAP_LIBRARIES)
MARK_AS_ADVANCED(
PCAP_LIBRARIES
PCAP_INCLUDE_DIRS
)

View File

@ -0,0 +1,299 @@
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ... )
#
# This function is intended to be used in FindXXX.cmake modules files.
# It handles the REQUIRED, QUIET and version-related arguments to find_package().
# It also sets the <UPPERCASED_NAME>_FOUND variable.
# The package is considered found if all variables <var1>... listed contain
# valid results, e.g. valid filepaths.
#
# There are two modes of this function. The first argument in both modes is
# the name of the Find-module where it is called (in original casing).
#
# The first simple mode looks like this:
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> (DEFAULT_MSG|"Custom failure message") <var1>...<varN> )
# If the variables <var1> to <varN> are all valid, then <UPPERCASED_NAME>_FOUND
# will be set to TRUE.
# If DEFAULT_MSG is given as second argument, then the function will generate
# itself useful success and error messages. You can also supply a custom error message
# for the failure case. This is not recommended.
#
# The second mode is more powerful and also supports version checking:
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS <var1>...<varN>]
# [VERSION_VAR <versionvar>]
# [HANDLE_COMPONENTS]
# [CONFIG_MODE]
# [FAIL_MESSAGE "Custom failure message"] )
#
# As above, if <var1> through <varN> are all valid, <UPPERCASED_NAME>_FOUND
# will be set to TRUE.
# After REQUIRED_VARS the variables which are required for this package are listed.
# Following VERSION_VAR the name of the variable can be specified which holds
# the version of the package which has been found. If this is done, this version
# will be checked against the (potentially) specified required version used
# in the find_package() call. The EXACT keyword is also handled. The default
# messages include information about the required version and the version
# which has been actually found, both if the version is ok or not.
# If the package supports components, use the HANDLE_COMPONENTS option to enable
# handling them. In this case, find_package_handle_standard_args() will report
# which components have been found and which are missing, and the <NAME>_FOUND
# variable will be set to FALSE if any of the required components (i.e. not the
# ones listed after OPTIONAL_COMPONENTS) are missing.
# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for
# a find_package(... NO_MODULE) call. In this case VERSION_VAR will be set
# to <NAME>_VERSION and the macro will automatically check whether the
# Config module was found.
# Via FAIL_MESSAGE a custom failure message can be specified, if this is not
# used, the default message will be displayed.
#
# Example for mode 1:
#
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
#
# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE.
# If it is not found and REQUIRED was used, it fails with FATAL_ERROR,
# independent whether QUIET was used or not.
# If it is found, success will be reported, including the content of <var1>.
# On repeated Cmake runs, the same message won't be printed again.
#
# Example for mode 2:
#
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE
# VERSION_VAR BISON_VERSION)
# In this case, BISON is considered to be found if the variable(s) listed
# after REQUIRED_VAR are all valid, i.e. BISON_EXECUTABLE in this case.
# Also the version of BISON will be checked by using the version contained
# in BISON_VERSION.
# Since no FAIL_MESSAGE is given, the default messages will be printed.
#
# Another example for mode 2:
#
# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(Automoc4 CONFIG_MODE)
# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4 NO_MODULE)
# and adds an additional search directory for automoc4.
# The following FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
# success/error message.
#=============================================================================
# Copyright 2007-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
include(FindPackageMessage)
include(CMakeParseArguments)
# internal helper macro
macro(_FPHSA_FAILURE_MESSAGE _msg)
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${_msg}")
else ()
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${_msg}")
endif ()
endif ()
endmacro()
# internal helper macro to generate the failure message when used in CONFIG_MODE:
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
# <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
if(${_NAME}_CONFIG)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
else()
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
# List them all in the error message:
if(${_NAME}_CONSIDERED_CONFIGS)
set(configsText "")
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
math(EXPR configsCount "${configsCount} - 1")
foreach(currentConfigIndex RANGE ${configsCount})
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
set(configsText "${configsText} ${filename} (version ${version})\n")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
else()
# Simple case: No Config-file was found at all:
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
endif()
endif()
endmacro()
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
# new extended or in the "old" mode:
set(options CONFIG_MODE HANDLE_COMPONENTS)
set(oneValueArgs FAIL_MESSAGE VERSION_VAR)
set(multiValueArgs REQUIRED_VARS)
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
if(${INDEX} EQUAL -1)
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
set(FPHSA_REQUIRED_VARS ${ARGN})
set(FPHSA_VERSION_VAR)
else()
CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
if(FPHSA_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT FPHSA_FAIL_MESSAGE)
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
endif()
# now that we collected all arguments, process them
if("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
endif()
# In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
# when it successfully found the config-file, including version checking:
if(FPHSA_CONFIG_MODE)
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
endif()
if(NOT FPHSA_REQUIRED_VARS)
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
endif()
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
string(TOUPPER ${_NAME} _NAME_UPPER)
string(TOLOWER ${_NAME} _NAME_LOWER)
# collect all variables which were not found, so they can be printed, so the
# user knows better what went wrong (#6375)
set(MISSING_VARS "")
set(DETAILS "")
set(${_NAME_UPPER}_FOUND TRUE)
# check if all passed variables are valid
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
if(NOT ${_CURRENT_VAR})
set(${_NAME_UPPER}_FOUND FALSE)
set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
else()
set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
endif()
endforeach()
# component handling
unset(FOUND_COMPONENTS_MSG)
unset(MISSING_COMPONENTS_MSG)
if(FPHSA_HANDLE_COMPONENTS)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(${_NAME}_${comp}_FOUND)
if(NOT DEFINED FOUND_COMPONENTS_MSG)
set(FOUND_COMPONENTS_MSG "found components: ")
endif()
set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
else()
if(NOT DEFINED MISSING_COMPONENTS_MSG)
set(MISSING_COMPONENTS_MSG "missing components: ")
endif()
set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME_UPPER}_FOUND FALSE)
set(MISSING_VARS "${MISSING_VARS} ${comp}")
endif()
endif()
endforeach()
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
endif()
# version handling:
set(VERSION_MSG "")
set(VERSION_OK TRUE)
set(VERSION ${${FPHSA_VERSION_VAR}} )
if (${_NAME}_FIND_VERSION)
if(VERSION)
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
endif ()
else() # minimum version specified:
if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
endif ()
endif()
else()
# if the package was not found, but a version was given, add that to the output:
if(${_NAME}_FIND_VERSION_EXACT)
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
else()
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
endif()
endif()
else ()
if(VERSION)
set(VERSION_MSG "(found version \"${VERSION}\")")
endif()
endif ()
if(VERSION_OK)
set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
else()
set(${_NAME_UPPER}_FOUND FALSE)
endif()
# print the result:
if (${_NAME_UPPER}_FOUND)
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
else ()
if(FPHSA_CONFIG_MODE)
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
else()
if(NOT VERSION_OK)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
else()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
endif()
endif()
endif ()
set(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE)
endfunction()

View File

@ -0,0 +1,141 @@
# - Find python interpreter
# This module finds if Python interpreter is installed and determines where the
# executables are. This code sets the following variables:
#
# PYTHONINTERP_FOUND - Was the Python executable found
# PYTHON_EXECUTABLE - path to the Python interpreter
#
# PYTHON_VERSION_STRING - Python version found e.g. 2.5.2
# PYTHON_VERSION_MAJOR - Python major version found e.g. 2
# PYTHON_VERSION_MINOR - Python minor version found e.g. 5
# PYTHON_VERSION_PATCH - Python patch version found e.g. 2
#
# The Python_ADDITIONAL_VERSIONS variable can be used to specify a list of
# version numbers that should be taken into account when searching for Python.
# You need to set this variable before calling find_package(PythonInterp).
#=============================================================================
# Copyright 2005-2010 Kitware, Inc.
# Copyright 2011 Bjoern Ricks <bjoern.ricks@gmail.com>
# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
unset(_Python_NAMES)
set(_PYTHON1_VERSIONS 1.6 1.5)
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
set(_PYTHON3_VERSIONS 3.3 3.2 3.1 3.0)
if(PythonInterp_FIND_VERSION)
if(PythonInterp_FIND_VERSION MATCHES "^[0-9]+\\.[0-9]+(\\.[0-9]+.*)?$")
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" _PYTHON_FIND_MAJ_MIN "${PythonInterp_FIND_VERSION}")
string(REGEX REPLACE "^([0-9]+).*" "\\1" _PYTHON_FIND_MAJ "${_PYTHON_FIND_MAJ_MIN}")
list(APPEND _Python_NAMES python${_PYTHON_FIND_MAJ_MIN} python${_PYTHON_FIND_MAJ})
unset(_PYTHON_FIND_OTHER_VERSIONS)
if(NOT PythonInterp_FIND_VERSION_EXACT)
foreach(_PYTHON_V ${_PYTHON${_PYTHON_FIND_MAJ}_VERSIONS})
if(NOT _PYTHON_V VERSION_LESS _PYTHON_FIND_MAJ_MIN)
list(APPEND _PYTHON_FIND_OTHER_VERSIONS ${_PYTHON_V})
endif()
endforeach()
endif()
unset(_PYTHON_FIND_MAJ_MIN)
unset(_PYTHON_FIND_MAJ)
else()
list(APPEND _Python_NAMES python${PythonInterp_FIND_VERSION})
set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON${PythonInterp_FIND_VERSION}_VERSIONS})
endif()
else()
set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON3_VERSIONS} ${_PYTHON2_VERSIONS} ${_PYTHON1_VERSIONS})
endif()
list(APPEND _Python_NAMES python)
# Search for the current active python version first
find_program(PYTHON_EXECUTABLE NAMES ${_Python_NAMES})
# Set up the versions we know about, in the order we will search. Always add
# the user supplied additional versions to the front.
set(_Python_VERSIONS
${Python_ADDITIONAL_VERSIONS}
${_PYTHON_FIND_OTHER_VERSIONS}
)
unset(_PYTHON_FIND_OTHER_VERSIONS)
unset(_PYTHON1_VERSIONS)
unset(_PYTHON2_VERSIONS)
unset(_PYTHON3_VERSIONS)
# Search for newest python version if python executable isn't found
if(NOT PYTHON_EXECUTABLE)
foreach(_CURRENT_VERSION ${_Python_VERSIONS})
set(_Python_NAMES python${_CURRENT_VERSION})
if(WIN32)
list(APPEND _Python_NAMES python)
endif()
find_program(PYTHON_EXECUTABLE
NAMES ${_Python_NAMES}
PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]
)
endforeach()
endif()
# determine python version string
if(PYTHON_EXECUTABLE)
execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c
"import sys; sys.stdout.write(';'.join([str(x) for x in sys.version_info[:3]]))"
OUTPUT_VARIABLE _VERSION
RESULT_VARIABLE _PYTHON_VERSION_RESULT
ERROR_QUIET)
if(NOT _PYTHON_VERSION_RESULT)
string(REPLACE ";" "." PYTHON_VERSION_STRING "${_VERSION}")
list(GET _VERSION 0 PYTHON_VERSION_MAJOR)
list(GET _VERSION 1 PYTHON_VERSION_MINOR)
list(GET _VERSION 2 PYTHON_VERSION_PATCH)
if(PYTHON_VERSION_PATCH EQUAL 0)
# it's called "Python 2.7", not "2.7.0"
string(REGEX REPLACE "\\.0$" "" PYTHON_VERSION_STRING "${PYTHON_VERSION_STRING}")
endif()
else()
# sys.version predates sys.version_info, so use that
execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.version)"
OUTPUT_VARIABLE _VERSION
RESULT_VARIABLE _PYTHON_VERSION_RESULT
ERROR_QUIET)
if(NOT _PYTHON_VERSION_RESULT)
string(REGEX REPLACE " .*" "" PYTHON_VERSION_STRING "${_VERSION}")
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+.*" "\\1" PYTHON_VERSION_MAJOR "${PYTHON_VERSION_STRING}")
string(REGEX REPLACE "^[0-9]+\\.([0-9])+.*" "\\1" PYTHON_VERSION_MINOR "${PYTHON_VERSION_STRING}")
if(PYTHON_VERSION_STRING MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+.*")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PYTHON_VERSION_PATCH "${PYTHON_VERSION_STRING}")
else()
set(PYTHON_VERSION_PATCH "0")
endif()
else()
# sys.version was first documented for Python 1.5, so assume
# this is older.
set(PYTHON_VERSION_STRING "1.4")
set(PYTHON_VERSION_MAJOR "1")
set(PYTHON_VERSION_MAJOR "4")
set(PYTHON_VERSION_MAJOR "0")
endif()
endif()
unset(_PYTHON_VERSION_RESULT)
unset(_VERSION)
endif()
# handle the QUIETLY and REQUIRED arguments and set PYTHONINTERP_FOUND to TRUE if
# all listed variables are TRUE
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonInterp REQUIRED_VARS PYTHON_EXECUTABLE VERSION_VAR PYTHON_VERSION_STRING)
mark_as_advanced(PYTHON_EXECUTABLE)

View File

@ -0,0 +1,130 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_head_revision _refspecvar _hashvar)
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
# We have reached the root directory, we are not in git
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
return()
endif()
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
endwhile()
# check if this is a submodule
if(NOT IS_DIRECTORY ${GIT_DIR})
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${GIT_DIR}/HEAD")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake"
@ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(COMMAND
"${GIT_EXECUTABLE}"
describe
${hash}
${ARGN}
WORKING_DIRECTORY
"${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var} "${out}" PARENT_SCOPE)
endfunction()

View File

@ -0,0 +1,39 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
set(HEAD_HASH "${HEAD_REF}")
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
string(SUBSTRING ${HEAD_HASH} 0 7 HEAD_HASH)
endif()

View File

@ -0,0 +1,39 @@
#
# Copyright 2013 Dominic Spill
#
# This file is part of Libbtbb.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
include(GNUInstallDirs)
# Based heavily upon the hackrf cmake setup.
project(libbtbb C)
set(PACKAGE libbtbb)
add_subdirectory(src)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/libbtbb.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libbtbb.pc
@ONLY)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/libbtbb.pc
DESTINATION lib${LIB_SUFFIX}/pkgconfig
)

View File

@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Bluetooth Baseband Library
Description: C Utility Library
Version: @VERSION@
Cflags: -I${includedir}/ @BTBB_PC_CFLAGS@
Libs: -L${libdir} -lbtbb
Libs.private: @BTBB_PC_LIBS@

View File

@ -0,0 +1,105 @@
#
# This file is part of Libbtbb.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
# Based slightly upon the hackrf cmake setup.
# FIXME Set static release version here to avoid pulling from git
set(RELEASE "")
set(DIRTY_FLAG "")
if ( "${RELEASE}" STREQUAL "" )
# automatic git version when working out of git
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC RELEASE)
execute_process(COMMAND git status -s --untracked-files=no OUTPUT_VARIABLE DIRTY)
if ( NOT "${DIRTY}" STREQUAL "" )
set(DIRTY_FLAG "*")
endif()
endif()
add_definitions( -DRELEASE="${RELEASE}${DIRTY_FLAG}" )
# Source
set(c_sources ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_packet.c
${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_piconet.c
${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_le_packet.c
${CMAKE_CURRENT_SOURCE_DIR}/pcap.c
${CMAKE_CURRENT_SOURCE_DIR}/pcapng.c
${CMAKE_CURRENT_SOURCE_DIR}/pcapng-bt.c
CACHE INTERNAL "List of C sources")
set(c_headers ${CMAKE_CURRENT_SOURCE_DIR}/btbb.h
CACHE INTERNAL "List of C headers")
# For cygwin just force UNIX OFF and WIN32 ON
if( ${CYGWIN} )
SET(UNIX OFF)
SET(WIN32 ON)
endif( ${CYGWIN} )
# FIXME: This may be a hack
# perhaps there should be separate libbtbb and libbtbb-static targets?
if( ${WIN32} )
# Static library
add_library(btbb STATIC ${c_sources})
set_target_properties(btbb PROPERTIES OUTPUT_NAME "btbb_static")
else()
# Dynamic library
add_library(btbb SHARED ${c_sources})
set_target_properties(btbb PROPERTIES VERSION ${MAJOR_VERSION}.${MINOR_VERSION} SOVERSION 0)
endif()
set_target_properties(btbb PROPERTIES CLEAN_DIRECT_OUTPUT 1)
# PCAP Support
if( (NOT DEFINED USE_PCAP) OR USE_PCAP )
find_package(PCAP)
if( USE_PCAP AND NOT ${PCAP_FOUND} )
message( FATAL_ERROR
"Cannot find libpcap, which is required for USE_PCAP")
endif()
if( ${PCAP_FOUND} )
include_directories(${PCAP_INCLUDE_DIRS})
target_link_libraries(btbb ${PCAP_LIBRARIES})
add_definitions( -DENABLE_PCAP )
endif( ${PCAP_FOUND} )
endif( (NOT DEFINED USE_PCAP) OR USE_PCAP )
if( ${UNIX} )
install(TARGETS btbb
LIBRARY DESTINATION lib${LIB_SUFFIX}
COMPONENT sharedlibs
)
install(FILES ${c_headers}
DESTINATION include
COMPONENT headers
)
endif( ${UNIX} )
if( ${WIN32} )
install(TARGETS btbb
DESTINATION bin
COMPONENT staticlibs
)
install(FILES ${c_headers}
DESTINATION include
COMPONENT headers
)
endif( ${WIN32} )

View File

@ -0,0 +1,607 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2012 Mike Ryan, Dominic Spill, Michael Ossmann
* Copyright 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "btbb.h"
#include "bluetooth_le_packet.h"
#include <ctype.h>
#include <string.h>
/* string representations of advertising packet type */
static const char *ADV_TYPE_NAMES[] = {
"ADV_IND", "ADV_DIRECT_IND", "ADV_NONCONN_IND", "SCAN_REQ",
"SCAN_RSP", "CONNECT_REQ", "ADV_SCAN_IND",
};
/* source clock accuracy in a connect packet */
static const char *CONNECT_SCA[] = {
"251 ppm to 500 ppm", "151 ppm to 250 ppm", "101 ppm to 150 ppm",
"76 ppm to 100 ppm", "51 ppm to 75 ppm", "31 ppm to 50 ppm",
"21 ppm to 30 ppm", "0 ppm to 20 ppm",
};
// count of objects in an array, shamelessly stolen from Chrome
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
static uint8_t count_bits(uint32_t n)
{
uint8_t i = 0;
for (i = 0; n != 0; i++)
n &= n - 1;
return i;
}
static int aa_access_channel_off_by_one(const uint32_t aa) {
int retval = 0;
if(count_bits(aa ^ LE_ADV_AA) == 1) {
retval = 1;
}
return retval;
}
/*
* A helper function for filtering bogus packets on data channels.
*
* If a candidate capture packet is random noise we would expect its
* Access Address to be a randomly distributed 32-bit number. An
* exhaustive software analysis reveals that of 4294967296 possible
* 32-bit Access Address values, 2900629660 (67.5%) are acceptable and
* 1394337636 (32.5%) are invalid. This function will identify which
* category a candidate Access Address falls into by returning the
* number of offenses contained.
*
* Refer to BT 4.x, Vol 6, Par B, Section 2.1.2.
*
* The Access Address in data channel packets meet the
* following requirements:
* - It shall have no more than six consecutive zeros or ones.
* - It shall not be the advertising channel packets Access Address.
* - It shall not be a sequence that differs from the advertising channel packets
* Access Address by only one bit.
* - It shall not have all four octets equal.
* - It shall have no more than 24 transitions.
* - It shall have a minimum of two transitions in the most significant six bits.
*/
static int aa_data_channel_offenses(const uint32_t aa) {
int retval = 0, transitions = 0;
unsigned shift, odd = (unsigned) (aa & 1);
uint8_t aab3, aab2, aab1, aab0 = (uint8_t) (aa & 0xff);
const uint8_t EIGHT_BIT_TRANSITIONS_EVEN[256] = {
0, 2, 2, 2, 2, 4, 2, 2, 2, 4, 4, 4, 2, 4, 2, 2,
2, 4, 4, 4, 4, 6, 4, 4, 2, 4, 4, 4, 2, 4, 2, 2,
2, 4, 4, 4, 4, 6, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4,
2, 4, 4, 4, 4, 6, 4, 4, 2, 4, 4, 4, 2, 4, 2, 2,
2, 4, 4, 4, 4, 6, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4,
4, 6, 6, 6, 6, 8, 6, 6, 4, 6, 6, 6, 4, 6, 4, 4,
2, 4, 4, 4, 4, 6, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4,
2, 4, 4, 4, 4, 6, 4, 4, 2, 4, 4, 4, 2, 4, 2, 2,
1, 3, 3, 3, 3, 5, 3, 3, 3, 5, 5, 5, 3, 5, 3, 3,
3, 5, 5, 5, 5, 7, 5, 5, 3, 5, 5, 5, 3, 5, 3, 3,
3, 5, 5, 5, 5, 7, 5, 5, 5, 7, 7, 7, 5, 7, 5, 5,
3, 5, 5, 5, 5, 7, 5, 5, 3, 5, 5, 5, 3, 5, 3, 3,
1, 3, 3, 3, 3, 5, 3, 3, 3, 5, 5, 5, 3, 5, 3, 3,
3, 5, 5, 5, 5, 7, 5, 5, 3, 5, 5, 5, 3, 5, 3, 3,
1, 3, 3, 3, 3, 5, 3, 3, 3, 5, 5, 5, 3, 5, 3, 3,
1, 3, 3, 3, 3, 5, 3, 3, 1, 3, 3, 3, 1, 3, 1, 1
};
const uint8_t EIGHT_BIT_TRANSITIONS_ODD[256] = {
1, 1, 3, 1, 3, 3, 3, 1, 3, 3, 5, 3, 3, 3, 3, 1,
3, 3, 5, 3, 5, 5, 5, 3, 3, 3, 5, 3, 3, 3, 3, 1,
3, 3, 5, 3, 5, 5, 5, 3, 5, 5, 7, 5, 5, 5, 5, 3,
3, 3, 5, 3, 5, 5, 5, 3, 3, 3, 5, 3, 3, 3, 3, 1,
3, 3, 5, 3, 5, 5, 5, 3, 5, 5, 7, 5, 5, 5, 5, 3,
5, 5, 7, 5, 7, 7, 7, 5, 5, 5, 7, 5, 5, 5, 5, 3,
3, 3, 5, 3, 5, 5, 5, 3, 5, 5, 7, 5, 5, 5, 5, 3,
3, 3, 5, 3, 5, 5, 5, 3, 3, 3, 5, 3, 3, 3, 3, 1,
2, 2, 4, 2, 4, 4, 4, 2, 4, 4, 6, 4, 4, 4, 4, 2,
4, 4, 6, 4, 6, 6, 6, 4, 4, 4, 6, 4, 4, 4, 4, 2,
4, 4, 6, 4, 6, 6, 6, 4, 6, 6, 8, 6, 6, 6, 6, 4,
4, 4, 6, 4, 6, 6, 6, 4, 4, 4, 6, 4, 4, 4, 4, 2,
2, 2, 4, 2, 4, 4, 4, 2, 4, 4, 6, 4, 4, 4, 4, 2,
4, 4, 6, 4, 6, 6, 6, 4, 4, 4, 6, 4, 4, 4, 4, 2,
2, 2, 4, 2, 4, 4, 4, 2, 4, 4, 6, 4, 4, 4, 4, 2,
2, 2, 4, 2, 4, 4, 4, 2, 2, 2, 4, 2, 2, 2, 2, 0
};
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab0] : EIGHT_BIT_TRANSITIONS_EVEN[aab0] );
odd = (unsigned) (aab0 & 0x80);
aab1 = (uint8_t) (aa >> 8);
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab1] : EIGHT_BIT_TRANSITIONS_EVEN[aab1] );
odd = (unsigned) (aab1 & 0x80);
aab2 = (uint8_t) (aa >> 16);
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab2] : EIGHT_BIT_TRANSITIONS_EVEN[aab2] );
odd = (unsigned) (aab2 & 0x80);
aab3 = (uint8_t) (aa >> 24);
transitions += (odd ? EIGHT_BIT_TRANSITIONS_ODD[aab3] : EIGHT_BIT_TRANSITIONS_EVEN[aab3] );
/* consider excessive transitions as offenses */
if (transitions > 24) {
retval += (transitions - 24);
}
const uint8_t AA_MSB6_ALLOWED[64] = {
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0
};
/* consider excessive transitions in the 6 MSBs as an offense */
retval += (1 - AA_MSB6_ALLOWED[aab3>>2]);
/* consider all bytes as being equal an offense */
retval += (((aab0 == aab1) && (aab0 == aab2) && (aab0 == aab3)) ? 1 : 0);
/* access-channel address and off-by-ones are illegal */
retval += ((aa == LE_ADV_AA) ? 1 : 0);
retval += aa_access_channel_off_by_one(aa);
/* inspect nibble triples for insufficient bit transitions */
for(shift=0; shift<=20; shift+=4) {
uint16_t twelvebits = (uint16_t) ((aa >> shift) & 0xfff);
switch( twelvebits ) {
/* seven consecutive zeroes */
case 0x080: case 0x180: case 0x280: case 0x380: case 0x480:
case 0x580: case 0x680: case 0x780: case 0x880: case 0x980:
case 0xa80: case 0xb80: case 0xc80: case 0xd80: case 0xe80:
case 0xf80: case 0x101: case 0x301: case 0x501: case 0x701:
case 0x901: case 0xb01: case 0xd01: case 0xf01: case 0x202:
case 0x602: case 0xa02: case 0xe02: case 0x203: case 0x603:
case 0xa03: case 0xe03: case 0x404: case 0xc04: case 0x405:
case 0xc05: case 0x406: case 0xc06: case 0x407: case 0xc07:
case 0x808: case 0x809: case 0x80a: case 0x80b: case 0x80c:
case 0x80d: case 0x80e: case 0x80f: case 0x010: case 0x011:
case 0x012: case 0x013: case 0x014: case 0x015: case 0x016:
case 0x017: case 0x018: case 0x019: case 0x01a: case 0x01b:
case 0x01c: case 0x01d: case 0x01e: case 0x01f:
/* eight consecutive zeroes */
case 0x100: case 0x300: case 0x500: case 0x700: case 0x900:
case 0xb00: case 0xd00: case 0xf00: case 0x201: case 0x601:
case 0xa01: case 0xe01: case 0x402: case 0xc02: case 0x403:
case 0xc03: case 0x804: case 0x805: case 0x806: case 0x807:
case 0x008: case 0x009: case 0x00a: case 0x00b: case 0x00c:
case 0x00d: case 0x00e: case 0x00f:
/* nine consecutive zeroes */
case 0xe00: case 0xc01: case 0x802: case 0x803: case 0x004:
case 0x005: case 0x006: case 0x007:
/* ten consecutive zeroes */
case 0x400: case 0xc00: case 0x801: case 0x002: case 0x003:
/* eleven consecutive zeroes */
case 0x800: case 0x001:
/* twelve consecutive zeroes */
case 0x000:
/* seven consecutive ones */
case 0x07f: case 0x0fe: case 0x2fe: case 0x4fe: case 0x6fe:
case 0x8fe: case 0xafe: case 0xcfe: case 0xefe: case 0x1fc:
case 0x5fc: case 0x9fc: case 0xdfc: case 0x1fd: case 0x5fd:
case 0x9fd: case 0xdfd: case 0x3f8: case 0xbf8: case 0x3f9:
case 0xbf9: case 0x3fa: case 0xbfa: case 0x3fb: case 0xbfb:
case 0x7f4: case 0x7f5: case 0x7f6: case 0x7f7: case 0xfe0:
/* eight consecutive ones */
case 0x0ff: case 0x2ff: case 0x4ff: case 0x6ff: case 0x8ff:
case 0xaff: case 0xcff: case 0xeff: case 0x1fe: case 0x5fe:
case 0x9fe: case 0xdfe: case 0x3fc: case 0xbfc: case 0x3fd:
case 0xbfd: case 0x7f8: case 0x7f9: case 0x7fa: case 0x7fb:
case 0xff0: case 0xff1: case 0xff2: case 0xff3: case 0xff4:
case 0xff5: case 0xff6: case 0xff7:
/* nine consecutive ones */
case 0x1ff: case 0x5ff: case 0x9ff: case 0xdff: case 0x3fe:
case 0xbfe: case 0x7fc: case 0x7fd: case 0xff8: case 0xff9:
case 0xffa: case 0xffb:
/* ten consecutive ones */
case 0x3ff: case 0xbff: case 0x7fe: case 0xffc: case 0xffd:
/* eleven consecutive ones */
case 0x7ff: case 0xffe:
/* all ones */
case 0xfff:
retval++;
break;
default:
break;
}
}
return retval;
}
lell_packet *
lell_packet_new(void)
{
lell_packet *pkt = (lell_packet *)calloc(1, sizeof(lell_packet));
pkt->refcount = 1;
return pkt;
}
void
lell_packet_ref(lell_packet *pkt)
{
pkt->refcount++;
}
void
lell_packet_unref(lell_packet *pkt)
{
pkt->refcount--;
if (pkt->refcount == 0)
free(pkt);
}
static uint8_t le_channel_index(uint16_t phys_channel) {
uint8_t ret;
if (phys_channel == 2402) {
ret = 37;
} else if (phys_channel < 2426) { // 0 - 10
ret = (phys_channel - 2404) / 2;
} else if (phys_channel == 2426) {
ret = 38;
} else if (phys_channel < 2480) { // 11 - 36
ret = 11 + (phys_channel - 2428) / 2;
} else {
ret = 39;
}
return ret;
}
void lell_allocate_and_decode(const uint8_t *stream, uint16_t phys_channel, uint32_t clk100ns, lell_packet **pkt)
{
*pkt = lell_packet_new( );
memcpy((*pkt)->symbols, stream, MAX_LE_SYMBOLS);
(*pkt)->channel_idx = le_channel_index(phys_channel);
(*pkt)->channel_k = (phys_channel-2402)/2;
(*pkt)->clk100ns = clk100ns;
(*pkt)->access_address = 0;
(*pkt)->access_address |= (*pkt)->symbols[0];
(*pkt)->access_address |= (*pkt)->symbols[1] << 8;
(*pkt)->access_address |= (*pkt)->symbols[2] << 16;
(*pkt)->access_address |= (*pkt)->symbols[3] << 24;
if (lell_packet_is_data(*pkt)) {
// data PDU
(*pkt)->length = (*pkt)->symbols[5] & 0x1f;
(*pkt)->access_address_offenses = aa_data_channel_offenses((*pkt)->access_address);
(*pkt)->flags.as_bits.access_address_ok = (*pkt)->access_address_offenses ? 0 : 1;
} else {
// advertising PDU
(*pkt)->length = (*pkt)->symbols[5] & 0x3f;
(*pkt)->adv_type = (*pkt)->symbols[4] & 0xf;
(*pkt)->adv_tx_add = (*pkt)->symbols[4] & 0x40 ? 1 : 0;
(*pkt)->adv_rx_add = (*pkt)->symbols[4] & 0x80 ? 1 : 0;
(*pkt)->flags.as_bits.access_address_ok = ((*pkt)->access_address == 0x8e89bed6);
(*pkt)->access_address_offenses = (*pkt)->flags.as_bits.access_address_ok ? 0 :
(aa_access_channel_off_by_one((*pkt)->access_address) ? 1 : 32);
}
}
unsigned lell_packet_is_data(const lell_packet *pkt)
{
return (unsigned) (pkt->channel_idx < 37);
}
uint32_t lell_get_access_address(const lell_packet *pkt)
{
return pkt->access_address;
}
unsigned lell_get_access_address_offenses(const lell_packet *pkt)
{
return pkt->access_address_offenses;
}
unsigned lell_get_channel_index(const lell_packet *pkt)
{
return pkt->channel_idx;
}
unsigned lell_get_channel_k(const lell_packet *pkt)
{
return pkt->channel_k;
}
const char * lell_get_adv_type_str(const lell_packet *pkt)
{
if (lell_packet_is_data(pkt))
return NULL;
if (pkt->adv_type < COUNT_OF(ADV_TYPE_NAMES))
return ADV_TYPE_NAMES[pkt->adv_type];
return "UNKNOWN";
}
static void _dump_addr(const char *name, const uint8_t *buf, int offset, int random) {
int i;
printf(" %s%02x", name, buf[offset+5]);
for (i = 4; i >= 0; --i)
printf(":%02x", buf[offset+i]);
printf(" (%s)\n", random ? "random" : "public");
}
static void _dump_8(const char *name, const uint8_t *buf, int offset) {
printf(" %s%02x (%d)\n", name, buf[offset], buf[offset]);
}
static void _dump_16(const char *name, const uint8_t *buf, int offset) {
uint16_t val = buf[offset+1] << 8 | buf[offset];
printf(" %s%04x (%d)\n", name, val, val);
}
static void _dump_24(char *name, const uint8_t *buf, int offset) {
uint32_t val = buf[offset+2] << 16 | buf[offset+1] << 8 | buf[offset];
printf(" %s%06x\n", name, val);
}
static void _dump_32(const char *name, const uint8_t *buf, int offset) {
uint32_t val = buf[offset+3] << 24 |
buf[offset+2] << 16 |
buf[offset+1] << 8 |
buf[offset+0];
printf(" %s%08x\n", name, val);
}
static void _dump_uuid(const uint8_t *uuid) {
int i;
for (i = 0; i < 4; ++i)
printf("%02x", uuid[i]);
printf("-");
for (i = 4; i < 6; ++i)
printf("%02x", uuid[i]);
printf("-");
for (i = 6; i < 8; ++i)
printf("%02x", uuid[i]);
printf("-");
for (i = 8; i < 10; ++i)
printf("%02x", uuid[i]);
printf("-");
for (i = 10; i < 16; ++i)
printf("%02x", uuid[i]);
}
// Refer to pg 1735 of Bluetooth Core Spec 4.0
static void _dump_scan_rsp_data(const uint8_t *buf, int len) {
int pos = 0;
int sublen, i;
uint8_t type;
uint16_t val;
char *cval;
while (pos < len) {
sublen = buf[pos];
++pos;
if (pos + sublen > len) {
printf("Error: attempt to read past end of buffer (%d + %d > %d)\n", pos, sublen, len);
return;
}
if (sublen == 0) {
printf("Early return due to 0 length\n");
return;
}
type = buf[pos];
printf(" Type %02x", type);
switch (type) {
case 0x01:
printf(" (Flags)\n");
printf(" ");
for (i = 0; i < 8; ++i)
printf("%d", buf[pos+1] & (1 << (7-i)) ? 1 : 0);
printf("\n");
break;
case 0x06:
printf(" (128-bit Service UUIDs, more available)\n");
goto print128;
case 0x07:
printf(" (128-bit Service UUIDs)\n");
print128:
if ((sublen - 1) % 16 == 0) {
uint8_t uuid[16];
for (i = 0; i < sublen - 1; ++i) {
uuid[15 - (i % 16)] = buf[pos+1+i];
if ((i & 15) == 15) {
printf(" ");
_dump_uuid(uuid);
printf("\n");
}
}
}
else {
printf("Wrong length (%d, must be divisible by 16)\n", sublen-1);
}
break;
case 0x09:
printf(" (Complete Local Name)\n");
printf(" ");
for (i = 1; i < sublen; ++i)
printf("%c", isprint(buf[pos+i]) ? buf[pos+i] : '.');
printf("\n");
break;
case 0x0a:
printf(" (Tx Power Level)\n");
printf(" ");
if (sublen-1 == 1) {
cval = (char *)&buf[pos+1];
printf("%d dBm\n", *cval);
} else {
printf("Wrong length (%d, should be 1)\n", sublen-1);
}
break;
case 0x12:
printf(" (Slave Connection Interval Range)\n");
printf(" ");
if (sublen-1 == 4) {
val = (buf[pos+2] << 8) | buf[pos+1];
printf("(%0.2f, ", val * 1.25);
val = (buf[pos+4] << 8) | buf[pos+3];
printf("%0.2f) ms\n", val * 1.25);
}
else {
printf("Wrong length (%d, should be 4)\n", sublen-1);
}
break;
case 0x16:
printf(" (Service Data)\n");
printf(" ");
if (sublen-1 >= 2) {
val = (buf[pos+2] << 8) | buf[pos+1];
printf("UUID: %02x", val);
if (sublen-1 > 2) {
printf(", Additional:");
for (i = 3; i < sublen; ++i)
printf(" %02x", buf[pos+i]);
}
printf("\n");
}
else {
printf("Wrong length (%d, should be >= 2)\n", sublen-1);
}
break;
default:
printf("\n");
printf(" ");
for (i = 1; i < sublen; ++i)
printf(" %02x", buf[pos+i]);
printf("\n");
}
pos += sublen;
}
}
void lell_print(const lell_packet *pkt)
{
int i, opcode;
if (lell_packet_is_data(pkt)) {
int llid = pkt->symbols[4] & 0x3;
static const char *llid_str[] = {
"Reserved",
"LL Data PDU / empty or L2CAP continuation",
"LL Data PDU / L2CAP start",
"LL Control PDU",
};
printf("Data / AA %08x (%s) / %2d bytes\n", pkt->access_address,
pkt->flags.as_bits.access_address_ok ? "valid" : "invalid",
pkt->length);
printf(" Channel Index: %d\n", pkt->channel_idx);
printf(" LLID: %d / %s\n", llid, llid_str[llid]);
printf(" NESN: %d SN: %d MD: %d\n", (pkt->symbols[4] >> 2) & 1,
(pkt->symbols[4] >> 3) & 1,
(pkt->symbols[4] >> 4) & 1);
switch (llid) {
case 3: // LL Control PDU
opcode = pkt->symbols[6];
static const char *opcode_str[] = {
"LL_CONNECTION_UPDATE_REQ",
"LL_CHANNEL_MAP_REQ",
"LL_TERMINATE_IND",
"LL_ENC_REQ",
"LL_ENC_RSP",
"LL_START_ENC_REQ",
"LL_START_ENC_RSP",
"LL_UNKNOWN_RSP",
"LL_FEATURE_REQ",
"LL_FEATURE_RSP",
"LL_PAUSE_ENC_REQ",
"LL_PAUSE_ENC_RSP",
"LL_VERSION_IND",
"LL_REJECT_IND",
"LL_SLAVE_FEATURE_REQ",
"LL_CONNECTION_PARAM_REQ",
"LL_CONNECTION_PARAM_RSP",
"LL_REJECT_IND_EXT",
"LL_PING_REQ",
"LL_PING_RSP",
"Reserved for Future Use",
};
printf(" Opcode: %d / %s\n", opcode, opcode_str[(opcode<0x14)?opcode:0x14]);
break;
default:
break;
}
} else {
printf("Advertising / AA %08x (%s)/ %2d bytes\n", pkt->access_address,
pkt->flags.as_bits.access_address_ok ? "valid" : "invalid",
pkt->length);
printf(" Channel Index: %d\n", pkt->channel_idx);
printf(" Type: %s\n", lell_get_adv_type_str(pkt));
switch(pkt->adv_type) {
case ADV_IND:
_dump_addr("AdvA: ", pkt->symbols, 6, pkt->adv_tx_add);
if (pkt->length-6 > 0) {
printf(" AdvData:");
for (i = 0; i < pkt->length - 6; ++i)
printf(" %02x", pkt->symbols[12+i]);
printf("\n");
_dump_scan_rsp_data(&pkt->symbols[12], pkt->length-6);
}
break;
case SCAN_REQ:
_dump_addr("ScanA: ", pkt->symbols, 6, pkt->adv_tx_add);
_dump_addr("AdvA: ", pkt->symbols, 12, pkt->adv_rx_add);
break;
case SCAN_RSP:
_dump_addr("AdvA: ", pkt->symbols, 6, pkt->adv_tx_add);
printf(" ScanRspData:");
for (i = 0; i < pkt->length - 6; ++i)
printf(" %02x", pkt->symbols[12+i]);
printf("\n");
_dump_scan_rsp_data(&pkt->symbols[12], pkt->length-6);
break;
case CONNECT_REQ:
_dump_addr("InitA: ", pkt->symbols, 6, pkt->adv_tx_add);
_dump_addr("AdvA: ", pkt->symbols, 12, pkt->adv_rx_add);
_dump_32("AA: ", pkt->symbols, 18);
_dump_24("CRCInit: ", pkt->symbols, 22);
_dump_8("WinSize: ", pkt->symbols, 25);
_dump_16("WinOffset: ", pkt->symbols, 26);
_dump_16("Interval: ", pkt->symbols, 28);
_dump_16("Latency: ", pkt->symbols, 30);
_dump_16("Timeout: ", pkt->symbols, 32);
printf(" ChM:");
for (i = 0; i < 5; ++i)
printf(" %02x", pkt->symbols[34+i]);
printf("\n");
printf(" Hop: %d\n", pkt->symbols[39] & 0x1f);
printf(" SCA: %d, %s\n",
pkt->symbols[39] >> 5,
CONNECT_SCA[pkt->symbols[39] >> 5]);
break;
}
}
printf("\n");
printf(" Data: ");
for (i = 6; i < 6 + pkt->length; ++i)
printf(" %02x", pkt->symbols[i]);
printf("\n");
printf(" CRC: ");
for (i = 0; i < 3; ++i)
printf(" %02x", pkt->symbols[6 + pkt->length + i]);
printf("\n");
}

View File

@ -0,0 +1,74 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2012 Mike Ryan, Dominic Spill, Michael Ossmann
* Copyright 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLUETOOTH_LE_PACKET_H
#define INCLUDED_BLUETOOTH_LE_PACKET_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_LE_SYMBOLS 64
#define LE_ADV_AA 0x8E89BED6
#define ADV_IND 0
#define ADV_DIRECT_IND 1
#define ADV_NONCONN_IND 2
#define SCAN_REQ 3
#define SCAN_RSP 4
#define CONNECT_REQ 5
#define ADV_SCAN_IND 6
struct lell_packet {
// raw unwhitened bytes of packet, including access address
uint8_t symbols[MAX_LE_SYMBOLS];
uint32_t access_address;
// channel index
uint8_t channel_idx;
uint8_t channel_k;
// number of symbols
int length;
uint32_t clk100ns;
// advertising packet header info
uint8_t adv_type;
int adv_tx_add;
int adv_rx_add;
unsigned access_address_offenses;
uint32_t refcount;
/* flags */
union {
struct {
uint32_t access_address_ok : 1;
} as_bits;
uint32_t as_word;
} flags;
};
#endif /* INCLUDED_BLUETOOTH_LE_PACKET_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,147 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLUETOOTH_PACKET_H
#define INCLUDED_BLUETOOTH_PACKET_H
#include "btbb.h"
/* maximum number of symbols */
#define MAX_SYMBOLS 3125
/* maximum number of payload bits */
#define MAX_PAYLOAD_LENGTH 2744
/* minimum header bit errors to indicate that this is an ID packet */
#define ID_THRESHOLD 5
#define PACKET_TYPE_NULL 0
#define PACKET_TYPE_POLL 1
#define PACKET_TYPE_FHS 2
#define PACKET_TYPE_DM1 3
#define PACKET_TYPE_DH1 4
#define PACKET_TYPE_HV1 5
#define PACKET_TYPE_HV2 6
#define PACKET_TYPE_HV3 7
#define PACKET_TYPE_DV 8
#define PACKET_TYPE_AUX1 9
#define PACKET_TYPE_DM3 10
#define PACKET_TYPE_DH3 11
#define PACKET_TYPE_EV4 12
#define PACKET_TYPE_EV5 13
#define PACKET_TYPE_DM5 14
#define PACKET_TYPE_DH5 15
struct btbb_packet {
uint32_t refcount;
uint32_t flags;
uint8_t channel; /* Bluetooth channel (0-79) */
uint8_t UAP; /* upper address part */
uint16_t NAP; /* non-significant address part */
uint32_t LAP; /* lower address part found in access code */
uint8_t modulation;
uint8_t transport;
uint8_t packet_type;
uint8_t packet_lt_addr; /* LLID field of payload header (2 bits) */
uint8_t packet_flags; /* Flags - FLOW/ARQN/SQEN */
uint8_t packet_hec; /* Flags - FLOW/ARQN/SQEN */
/* packet header, one bit per char */
char packet_header[18];
/* number of payload header bytes: 0, 1, 2, or -1 for
* unknown. payload is one bit per char. */
int payload_header_length;
char payload_header[16];
/* LLID field of payload header (2 bits) */
uint8_t payload_llid;
/* flow field of payload header (1 bit) */
uint8_t payload_flow;
/* payload length: the total length of the asynchronous data
* in bytes. This does not include the length of synchronous
* data, such as the voice field of a DV packet. If there is a
* payload header, this payload length is payload body length
* (the length indicated in the payload header's length field)
* plus payload_header_length plus 2 bytes CRC (if present).
*/
int payload_length;
/* The actual payload data in host format
* Ready for passing to wireshark
* 2744 is the maximum length, but most packets are shorter.
* Dynamic allocation would probably be better in the long run but is
* problematic in the short run.
*/
char payload[MAX_PAYLOAD_LENGTH];
uint16_t crc;
uint32_t clock; /* CLK1-27 of master */
uint32_t clkn; /* native (local) clock, CLK0-27 */
uint8_t ac_errors; /* Number of bit errors in the AC */
/* the raw symbol stream (less the preamble), one bit per char */
//FIXME maybe this should be a vector so we can grow it only
//to the size needed and later shrink it if we find we have
//more symbols than necessary
uint16_t length; /* number of symbols */
char symbols[MAX_SYMBOLS];
};
/* type-specific CRC checks and decoding */
int fhs(int clock, btbb_packet* p);
int DM(int clock, btbb_packet* p);
int DH(int clock, btbb_packet* p);
int EV3(int clock, btbb_packet* p);
int EV4(int clock, btbb_packet* p);
int EV5(int clock, btbb_packet* p);
int HV(int clock, btbb_packet* p);
/* check if the packet's CRC is correct for a given clock (CLK1-6) */
int crc_check(int clock, btbb_packet* p);
/* format payload for tun interface */
char *tun_format(btbb_packet* p);
/* try a clock value (CLK1-6) to unwhiten packet header,
* sets resultant d_packet_type and d_UAP, returns UAP.
*/
uint8_t try_clock(int clock, btbb_packet* p);
/* extract LAP from FHS payload */
uint32_t lap_from_fhs(btbb_packet* p);
/* extract UAP from FHS payload */
uint8_t uap_from_fhs(btbb_packet* p);
/* extract NAP from FHS payload */
uint16_t nap_from_fhs(btbb_packet* p);
/* extract clock from FHS payload */
uint32_t clock_from_fhs(btbb_packet* p);
#endif /* INCLUDED_BLUETOOTH_PACKET_H */

View File

@ -0,0 +1,953 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "bluetooth_packet.h"
#include "bluetooth_piconet.h"
#include "uthash.h"
#include <stdlib.h>
#include <stdio.h>
int perm_table_initialized = 0;
char perm_table[0x20][0x20][0x200];
/* count the number of 1 bits in a uint64_t */
int count_bits(uint8_t n)
{
int i = 0;
for (i = 0; n != 0; i++)
n &= n - 1;
return i;
}
btbb_piconet *
btbb_piconet_new(void)
{
btbb_piconet *pn = (btbb_piconet *)calloc(1, sizeof(btbb_piconet));
pn->refcount = 1;
return pn;
}
void
btbb_piconet_ref(btbb_piconet *pn)
{
pn->refcount++;
}
void
btbb_piconet_unref(btbb_piconet *pn)
{
pn->refcount--;
if (pn->refcount == 0)
free(pn);
}
/* A bit of a hack? to set survey mode */
static int survey_mode = 0;
int btbb_init_survey() {
survey_mode = 1;
return 0;
}
void btbb_init_piconet(btbb_piconet *pn, uint32_t lap)
{
pn->LAP = lap;
btbb_piconet_set_flag(pn, BTBB_LAP_VALID, 1);
}
void btbb_piconet_set_flag(btbb_piconet *pn, int flag, int val)
{
uint32_t mask = 1L << flag;
pn->flags &= ~mask;
if (val)
pn->flags |= mask;
}
int btbb_piconet_get_flag(const btbb_piconet *pn, const int flag)
{
uint32_t mask = 1L << flag;
return ((pn->flags & mask) != 0);
}
void btbb_piconet_set_uap(btbb_piconet *pn, uint8_t uap)
{
pn->UAP = uap;
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
}
uint8_t btbb_piconet_get_uap(const btbb_piconet *pn)
{
return pn->UAP;
}
uint32_t btbb_piconet_get_lap(const btbb_piconet *pn)
{
return pn->LAP;
}
uint16_t btbb_piconet_get_nap(const btbb_piconet *pn)
{
return pn->NAP;
}
uint64_t btbb_piconet_get_bdaddr(const btbb_piconet *pn)
{
return ((uint64_t) pn->NAP) << 32 | pn->UAP << 24 | pn->LAP;
}
int btbb_piconet_get_clk_offset(const btbb_piconet *pn)
{
return pn->clk_offset;
}
void btbb_piconet_set_clk_offset(btbb_piconet *pn, int clk_offset)
{
pn->clk_offset = clk_offset;
}
void btbb_piconet_set_afh_map(btbb_piconet *pn, uint8_t *afh_map) {
int i;
pn->used_channels = 0;
// DGS: Unroll this?
for(i=0; i<10; i++) {
pn->afh_map[i] = afh_map[i];
pn->used_channels += count_bits(pn->afh_map[i]);
}
if(btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
get_hop_pattern(pn);
}
uint8_t *btbb_piconet_get_afh_map(btbb_piconet *pn) {
return pn->afh_map;
}
void btbb_piconet_set_channel_seen(btbb_piconet *pn, uint8_t channel)
{
if(!(pn->afh_map[channel/8] & 0x1 << (channel % 8))) {
pn->afh_map[channel/8] |= 0x1 << (channel % 8);
pn->used_channels++;
if(btbb_piconet_get_flag(pn, BTBB_UAP_VALID) && !survey_mode)
get_hop_pattern(pn);
}
}
uint8_t btbb_piconet_get_channel_seen(btbb_piconet *pn, uint8_t channel)
{
if(channel < BT_NUM_CHANNELS)
return ( pn->afh_map[channel/8] & (1 << (channel % 8)) ) != 0;
else
return 1;
}
/* do all the precalculation that can be done before knowing the address */
void precalc(btbb_piconet *pn)
{
int i = 0;
int j = 0;
int chan;
/* populate frequency register bank*/
for (i = 0; i < BT_NUM_CHANNELS; i++) {
/* AFH is used, hopping sequence contains only used channels */
if(btbb_piconet_get_flag(pn, BTBB_IS_AFH)) {
chan = (i * 2) % BT_NUM_CHANNELS;
if(btbb_piconet_get_channel_seen(pn, chan))
pn->bank[j++] = chan;
}
/* all channels are used */
else {
pn->bank[i] = ((i * 2) % BT_NUM_CHANNELS);
}
}
/* actual frequency is 2402 + pn->bank[i] MHz */
}
/* do precalculation that requires the address */
void address_precalc(int address, btbb_piconet *pn)
{
/* precalculate some of single_hop()/gen_hop()'s variables */
pn->a1 = (address >> 23) & 0x1f;
pn->b = (address >> 19) & 0x0f;
pn->c1 = ((address >> 4) & 0x10) +
((address >> 3) & 0x08) +
((address >> 2) & 0x04) +
((address >> 1) & 0x02) +
(address & 0x01);
pn->d1 = (address >> 10) & 0x1ff;
pn->e = ((address >> 7) & 0x40) +
((address >> 6) & 0x20) +
((address >> 5) & 0x10) +
((address >> 4) & 0x08) +
((address >> 3) & 0x04) +
((address >> 2) & 0x02) +
((address >> 1) & 0x01);
}
#ifdef WC4
/* These are optimization experiments, which don't help much for
* x86. Hold on to them to see whether they're useful on ARM. */
#ifdef NEVER
#define BUTTERFLY(z,p,c,a,b) \
if ( ((p&(1<<c))!=0) & (((z&(1<<a))!=0) ^ ((z&(1<<b))!=0)) ) \
z ^= ((1<<a)|(1<<b))
#endif
#define BUTTERFLY(z,p,c,a,b) \
if ( (((z>>a)^(z>>b)) & (p>>c)) & 0x1 ) \
z ^= ((1<<a)|(1<<b))
int perm5(int z, int p_high, int p_low)
{
int p = (p_high << 5) | p_low;
BUTTERFLY(z,p,13,1,2);
BUTTERFLY(z,p,12,0,3);
BUTTERFLY(z,p,11,1,3);
BUTTERFLY(z,p,10,2,4);
BUTTERFLY(z,p, 9,0,3);
BUTTERFLY(z,p, 8,1,4);
BUTTERFLY(z,p, 7,3,4);
BUTTERFLY(z,p, 6,0,2);
BUTTERFLY(z,p, 5,1,3);
BUTTERFLY(z,p, 4,0,4);
BUTTERFLY(z,p, 3,3,4);
BUTTERFLY(z,p, 2,1,2);
BUTTERFLY(z,p, 1,2,3);
BUTTERFLY(z,p, 0,0,1);
return z;
}
#endif // WC4
/* 5 bit permutation */
/* assumes z is constrained to 5 bits, p_high to 5 bits, p_low to 9 bits */
int perm5(int z, int p_high, int p_low)
{
int i, tmp, output, z_bit[5], p[14];
int index1[] = {0, 2, 1, 3, 0, 1, 0, 3, 1, 0, 2, 1, 0, 1};
int index2[] = {1, 3, 2, 4, 4, 3, 2, 4, 4, 3, 4, 3, 3, 2};
/* bits of p_low and p_high are control signals */
for (i = 0; i < 9; i++)
p[i] = (p_low >> i) & 0x01;
for (i = 0; i < 5; i++)
p[i+9] = (p_high >> i) & 0x01;
/* bit swapping will be easier with an array of bits */
for (i = 0; i < 5; i++)
z_bit[i] = (z >> i) & 0x01;
/* butterfly operations */
for (i = 13; i >= 0; i--) {
/* swap bits according to index arrays if control signal tells us to */
if (p[i]) {
tmp = z_bit[index1[i]];
z_bit[index1[i]] = z_bit[index2[i]];
z_bit[index2[i]] = tmp;
}
}
/* reconstruct output from rearranged bits */
output = 0;
for (i = 0; i < 5; i++)
output += z_bit[i] << i;
return(output);
}
void perm_table_init(void)
{
/* populate perm_table for all possible inputs */
int z, p_high, p_low;
for (z = 0; z < 0x20; z++)
for (p_high = 0; p_high < 0x20; p_high++)
for (p_low = 0; p_low < 0x200; p_low++)
perm_table[z][p_high][p_low] = perm5(z, p_high, p_low);
}
/* drop-in replacement for perm5() using lookup table */
int fast_perm(int z, int p_high, int p_low)
{
if (!perm_table_initialized) {
perm_table_init();
perm_table_initialized = 1;
}
return(perm_table[z][p_high][p_low]);
}
/* generate the complete hopping sequence */
static void gen_hops(btbb_piconet *pn)
{
/* a, b, c, d, e, f, x, y1, y2 are variable names used in section 2.6 of the spec */
/* b is already defined */
/* e is already defined */
int a, c, d, x;
uint32_t base_f, f, f_dash;
int h, i, j, k, c_flipped, perm_in, perm_out;
/* sequence index = clock >> 1 */
/* (hops only happen at every other clock value) */
int index = 0;
base_f = 0;
f = 0;
f_dash = 0;
/* nested loops for optimization (not recalculating every variable with every clock tick) */
for (h = 0; h < 0x04; h++) { /* clock bits 26-27 */
for (i = 0; i < 0x20; i++) { /* clock bits 21-25 */
a = pn->a1 ^ i;
for (j = 0; j < 0x20; j++) { /* clock bits 16-20 */
c = pn->c1 ^ j;
c_flipped = c ^ 0x1f;
for (k = 0; k < 0x200; k++) { /* clock bits 7-15 */
d = pn->d1 ^ k;
for (x = 0; x < 0x20; x++) { /* clock bits 2-6 */
perm_in = ((x + a) % 32) ^ pn->b;
/* y1 (clock bit 1) = 0, y2 = 0 */
perm_out = fast_perm(perm_in, c, d);
if (btbb_piconet_get_flag(pn, BTBB_IS_AFH))
pn->sequence[index] = pn->bank[(perm_out + pn->e + f_dash) % pn->used_channels];
else
pn->sequence[index] = pn->bank[(perm_out + pn->e + f) % BT_NUM_CHANNELS];
/* y1 (clock bit 1) = 1, y2 = 32 */
perm_out = fast_perm(perm_in, c_flipped, d);
if (btbb_piconet_get_flag(pn, BTBB_IS_AFH))
pn->sequence[index + 1] = pn->bank[(perm_out + pn->e + f_dash + 32) % pn->used_channels];
else
pn->sequence[index + 1] = pn->bank[(perm_out + pn->e + f + 32) % BT_NUM_CHANNELS];
index += 2;
}
base_f += 16;
f = base_f % BT_NUM_CHANNELS;
f_dash = f % pn->used_channels;
}
}
}
}
}
/* Function to calculate piconet hopping patterns and add to hash map */
void gen_hop_pattern(btbb_piconet *pn)
{
printf("\nCalculating complete hopping sequence.\n");
/* this holds the entire hopping sequence */
pn->sequence = (char*) malloc(SEQUENCE_LENGTH);
precalc(pn);
address_precalc(((pn->UAP<<24) | pn->LAP) & 0xfffffff, pn);
gen_hops(pn);
printf("Hopping sequence calculated.\n");
}
/* Container for hopping pattern */
typedef struct {
uint64_t key; /* afh flag + address */
char *sequence;
UT_hash_handle hh;
} hopping_struct;
static hopping_struct *hopping_map = NULL;
/* Function to fetch piconet hopping patterns */
void get_hop_pattern(btbb_piconet *pn)
{
hopping_struct *s;
uint64_t key;
/* Two stages to avoid "left shift count >= width of type" warning */
key = btbb_piconet_get_flag(pn, BTBB_IS_AFH);
key = (key<<39) | ((uint64_t)pn->used_channels<<32) | (pn->UAP<<24) | pn->LAP;
HASH_FIND(hh, hopping_map, &key, 4, s);
if (s == NULL) {
gen_hop_pattern(pn);
s = malloc(sizeof(hopping_struct));
s->key = key;
s->sequence = pn->sequence;
HASH_ADD(hh, hopping_map, key, 4, s);
} else {
printf("\nFound hopping sequence in cache.\n");
pn->sequence = s->sequence;
}
}
/* determine channel for a particular hop */
/* borrowed from ubertooth firmware to support AFH */
char single_hop(int clock, btbb_piconet *pn)
{
int a, c, d, x, y1, y2, perm, next_channel;
uint32_t base_f, f, f_dash;
/* following variable names used in section 2.6 of the spec */
x = (clock >> 2) & 0x1f;
y1 = (clock >> 1) & 0x01;
y2 = y1 << 5;
a = (pn->a1 ^ (clock >> 21)) & 0x1f;
/* b is already defined */
c = (pn->c1 ^ (clock >> 16)) & 0x1f;
d = (pn->d1 ^ (clock >> 7)) & 0x1ff;
/* e is already defined */
base_f = (clock >> 3) & 0x1fffff0;
f = base_f % BT_NUM_CHANNELS;
perm = fast_perm(
((x + a) % 32) ^ pn->b,
(y1 * 0x1f) ^ c,
d);
/* hop selection */
if(btbb_piconet_get_flag(pn, BTBB_IS_AFH)) {
f_dash = base_f % pn->used_channels;
next_channel = pn->bank[(perm + pn->e + f_dash + y2) % pn->used_channels];
} else {
next_channel = pn->bank[(perm + pn->e + f + y2) % BT_NUM_CHANNELS];
}
return next_channel;
}
/* look up channel for a particular hop */
char hop(int clock, btbb_piconet *pn)
{
return pn->sequence[clock];
}
static char aliased_channel(char channel)
{
return ((channel + 24) % ALIASED_CHANNELS) + 26;
}
/* create list of initial candidate clock values (hops with same channel as first observed hop) */
static int init_candidates(char channel, int known_clock_bits, btbb_piconet *pn)
{
int i;
int count = 0; /* total number of candidates */
char observable_channel; /* accounts for aliasing if necessary */
/* only try clock values that match our known bits */
for (i = known_clock_bits; i < SEQUENCE_LENGTH; i += 0x40) {
if (pn->aliased)
observable_channel = aliased_channel(pn->sequence[i]);
else
observable_channel = pn->sequence[i];
if (observable_channel == channel)
pn->clock_candidates[count++] = i;
//FIXME ought to throw exception if count gets too big
}
return count;
}
/* initialize the hop reversal process */
int btbb_init_hop_reversal(int aliased, btbb_piconet *pn)
{
int max_candidates;
uint32_t clock;
get_hop_pattern(pn);
if(aliased)
max_candidates = (SEQUENCE_LENGTH / ALIASED_CHANNELS) / 32;
else
max_candidates = (SEQUENCE_LENGTH / BT_NUM_CHANNELS) / 32;
/* this can hold twice the approximate number of initial candidates */
pn->clock_candidates = (uint32_t*) malloc(sizeof(uint32_t) * max_candidates);
clock = (pn->clk_offset + pn->first_pkt_time) & 0x3f;
pn->num_candidates = init_candidates(pn->pattern_channels[0], clock, pn);
pn->winnowed = 0;
btbb_piconet_set_flag(pn, BTBB_HOP_REVERSAL_INIT, 1);
btbb_piconet_set_flag(pn, BTBB_CLK27_VALID, 0);
btbb_piconet_set_flag(pn, BTBB_IS_ALIASED, aliased);
printf("%d initial CLK1-27 candidates\n", pn->num_candidates);
return pn->num_candidates;
}
void try_hop(btbb_packet *pkt, btbb_piconet *pn)
{
uint8_t filter_uap = pn->UAP;
/* Decode packet - fixing clock drift in the process */
btbb_decode(pkt, pn);
if (btbb_piconet_get_flag(pn, BTBB_HOP_REVERSAL_INIT)) {
//pn->winnowed = 0;
pn->pattern_indices[pn->packets_observed] =
pkt->clkn - pn->first_pkt_time;
pn->pattern_channels[pn->packets_observed] = pkt->channel;
pn->packets_observed++;
pn->total_packets_observed++;
btbb_winnow(pn);
if (btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
printf("got CLK1-27\n");
printf("clock offset = %d.\n", pn->clk_offset);
}
} else {
if (btbb_piconet_get_flag(pn, BTBB_CLK6_VALID)) {
btbb_uap_from_header(pkt, pn);
if (btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
printf("got CLK1-27\n");
printf("clock offset = %d.\n", pn->clk_offset);
}
} else {
if (btbb_uap_from_header(pkt, pn)) {
if (filter_uap == pn->UAP) {
btbb_init_hop_reversal(0, pn);
btbb_winnow(pn);
} else {
printf("failed to confirm UAP\n");
}
}
}
}
if(!btbb_piconet_get_flag(pn, BTBB_UAP_VALID)) {
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
pn->UAP = filter_uap;
}
}
/* return the observable channel (26-50) for a given channel (0-78) */
/* reset UAP/clock discovery */
static void reset(btbb_piconet *pn)
{
//printf("no candidates remaining! starting over . . .\n");
if(btbb_piconet_get_flag(pn, BTBB_HOP_REVERSAL_INIT)) {
free(pn->clock_candidates);
pn->sequence = NULL;
}
btbb_piconet_set_flag(pn, BTBB_GOT_FIRST_PACKET, 0);
btbb_piconet_set_flag(pn, BTBB_HOP_REVERSAL_INIT, 0);
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 0);
btbb_piconet_set_flag(pn, BTBB_CLK6_VALID, 0);
btbb_piconet_set_flag(pn, BTBB_CLK27_VALID, 0);
pn->packets_observed = 0;
/*
* If we have recently observed two packets in a row on the same
* channel, try AFH next time. If not, don't.
*/
btbb_piconet_set_flag(pn, BTBB_IS_AFH,
btbb_piconet_get_flag(pn, BTBB_LOOKS_LIKE_AFH));
// btbb_piconet_set_flag(pn, BTBB_LOOKS_LIKE_AFH, 0);
//int i;
//for(i=0; i<10; i++)
// pn->afh_map[i] = 0;
}
/* narrow a list of candidate clock values based on a single observed hop */
static int channel_winnow(int offset, char channel, btbb_piconet *pn)
{
int i;
int new_count = 0; /* number of candidates after winnowing */
char observable_channel; /* accounts for aliasing if necessary */
/* check every candidate */
for (i = 0; i < pn->num_candidates; i++) {
if (pn->aliased)
observable_channel = aliased_channel(pn->sequence[(pn->clock_candidates[i] + offset) % SEQUENCE_LENGTH]);
else
observable_channel = pn->sequence[(pn->clock_candidates[i] + offset) % SEQUENCE_LENGTH];
if (observable_channel == channel) {
/* this candidate matches the latest hop */
/* blow away old list of candidates with new one */
/* safe because new_count can never be greater than i */
pn->clock_candidates[new_count++] = pn->clock_candidates[i];
}
}
pn->num_candidates = new_count;
if (new_count == 1) {
// Calculate clock offset for CLKN, not CLK1-27
pn->clk_offset = ((pn->clock_candidates[0]<<1) - (pn->first_pkt_time<<1));
printf("\nAcquired CLK1-27 = 0x%07x\n", pn->clock_candidates[0]);
btbb_piconet_set_flag(pn, BTBB_CLK27_VALID, 1);
}
else if (new_count == 0) {
reset(pn);
}
//else {
//printf("%d CLK1-27 candidates remaining (channel=%d)\n", new_count, channel);
//}
return new_count;
}
/* narrow a list of candidate clock values based on all observed hops */
int btbb_winnow(btbb_piconet *pn)
{
int new_count = pn->num_candidates;
int index, last_index;
uint8_t channel, last_channel;
for (; pn->winnowed < pn->packets_observed; pn->winnowed++) {
index = pn->pattern_indices[pn->winnowed];
channel = pn->pattern_channels[pn->winnowed];
new_count = channel_winnow(index, channel, pn);
if (new_count <= 1)
break;
if (pn->packets_observed > 0) {
last_index = pn->pattern_indices[pn->winnowed - 1];
last_channel = pn->pattern_channels[pn->winnowed - 1];
/*
* Two packets in a row on the same channel should only
* happen if adaptive frequency hopping is in use.
* There can be false positives, though, especially if
* there is aliasing.
*/
if (!btbb_piconet_get_flag(pn, BTBB_LOOKS_LIKE_AFH)
&& (index == last_index + 1)
&& (channel == last_channel)) {
btbb_piconet_set_flag(pn, BTBB_LOOKS_LIKE_AFH, 1);
printf("Hopping pattern appears to be AFH\n");
}
}
}
return new_count;
}
/* use packet headers to determine UAP */
int btbb_uap_from_header(btbb_packet *pkt, btbb_piconet *pn)
{
uint8_t UAP;
int count, crc_chk, first_clock = 0;
int starting = 0;
int remaining = 0;
uint32_t clkn = pkt->clkn;
if (!btbb_piconet_get_flag(pn, BTBB_GOT_FIRST_PACKET))
pn->first_pkt_time = clkn;
// Set afh channel map
btbb_piconet_set_channel_seen(pn, pkt->channel);
if (pn->packets_observed < MAX_PATTERN_LENGTH) {
pn->pattern_indices[pn->packets_observed] = clkn - pn->first_pkt_time;
pn->pattern_channels[pn->packets_observed] = pkt->channel;
} else {
printf("Oops. More hops than we can remember.\n");
reset(pn);
return 0; //FIXME ought to throw exception
}
pn->packets_observed++;
pn->total_packets_observed++;
/* try every possible first packet clock value */
for (count = 0; count < 64; count++) {
/* skip eliminated candidates unless this is our first time through */
if (pn->clock6_candidates[count] > -1
|| !btbb_piconet_get_flag(pn, BTBB_GOT_FIRST_PACKET)) {
/* clock value for the current packet assuming count was the clock of the first packet */
int clock = (count + clkn - pn->first_pkt_time) % 64;
starting++;
UAP = try_clock(clock, pkt);
crc_chk = -1;
/* if this is the first packet: populate the candidate list */
/* if not: check CRCs if UAPs match */
if (!btbb_piconet_get_flag(pn, BTBB_GOT_FIRST_PACKET)
|| UAP == pn->clock6_candidates[count])
crc_chk = crc_check(clock, pkt);
if (btbb_piconet_get_flag(pn, BTBB_UAP_VALID) &&
(UAP != pn->UAP))
crc_chk = -1;
switch(crc_chk) {
case -1: /* UAP mismatch */
case 0: /* CRC failure */
pn->clock6_candidates[count] = -1;
break;
case 1: /* inconclusive result */
case 2: /* Inconclusive, but looks better */
pn->clock6_candidates[count] = UAP;
/* remember this count because it may be the correct clock of the first packet */
first_clock = count;
remaining++;
break;
default: /* CRC success */
pn->clk_offset = (count - (pn->first_pkt_time & 0x3f)) & 0x3f;
if (!btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
printf("Correct CRC! UAP = 0x%x found after %d total packets.\n",
UAP, pn->total_packets_observed);
else
printf("Correct CRC! CLK6 = 0x%x found after %d total packets.\n",
pn->clk_offset, pn->total_packets_observed);
pn->UAP = UAP;
btbb_piconet_set_flag(pn, BTBB_CLK6_VALID, 1);
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
pn->total_packets_observed = 0;
return 1;
}
}
}
btbb_piconet_set_flag(pn, BTBB_GOT_FIRST_PACKET, 1);
//printf("reduced from %d to %d CLK1-6 candidates\n", starting, remaining);
if (remaining == 1) {
pn->clk_offset = (first_clock - (pn->first_pkt_time & 0x3f)) & 0x3f;
if (!btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
printf("UAP = 0x%x found after %d total packets.\n",
pn->clock6_candidates[first_clock], pn->total_packets_observed);
else
printf("CLK6 = 0x%x found after %d total packets.\n",
pn->clk_offset, pn->total_packets_observed);
pn->UAP = pn->clock6_candidates[first_clock];
btbb_piconet_set_flag(pn, BTBB_CLK6_VALID, 1);
btbb_piconet_set_flag(pn, BTBB_UAP_VALID, 1);
pn->total_packets_observed = 0;
return 1;
}
if (remaining == 0) {
reset(pn);
}
return 0;
}
/* FIXME: comment out enqueue and dequeue because they are
* never used. Try to find out what tey were meant to be
* used for before the next release.
*/
///* add a packet to the queue */
//static void enqueue(btbb_packet *pkt, btbb_piconet *pn)
//{
// pkt_queue *head;
// //pkt_queue item;
//
// btbb_packet_ref(pkt);
// pkt_queue item = {pkt, NULL};
// head = pn->queue;
//
// if (head == NULL) {
// pn->queue = &item;
// } else {
// for(; head->next != NULL; head = head->next)
// ;
// head->next = &item;
// }
//}
//
///* pull the first packet from the queue (FIFO) */
//static btbb_packet *dequeue(btbb_piconet *pn)
//{
// btbb_packet *pkt;
//
// if (pn->queue == NULL) {
// pkt = NULL;
// } else {
// pkt = pn->queue->pkt;
// pn->queue = pn->queue->next;
// btbb_packet_unref(pkt);
// }
//
// return pkt;
//}
/* decode the whole packet */
int btbb_decode(btbb_packet* pkt, btbb_piconet *pn)
{
btbb_packet_set_flag(pkt, BTBB_HAS_PAYLOAD, 0);
uint8_t clk6, i, best_clk;
int rv = 0, max_rv = 0;
if (btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
/* Removing this section until we can more reliably handle AFH */
//if(pn->sequence == NULL)
// get_hop_pattern(pn);
//clk6 = pkt->clock & 0x3f;
//for(i=0; i<64; i++) {
// pkt->clock = (pkt->clock & 0xffffffc0) | ((clk6 + i) & 0x3f);
// if ((pn->sequence[pkt->clock] == pkt->channel) && (btbb_decode_header(pkt))) {
// rv = btbb_decode_payload(pkt);
// if(rv > max_rv) {
// max_rv = rv;
// best_clk = (clk6 + i) & 0x3f;
// }
// }
//}
// If we found nothing, try again, ignoring channel
if(max_rv <= 1) {
clk6 = pkt->clock & 0x3f;
for(i=0; i<64; i++) {
pkt->clock = (pkt->clock & 0xffffffc0) | ((clk6 + i) & 0x3f);
if (btbb_decode_header(pkt)) {
rv = btbb_decode_payload(pkt);
if(rv > max_rv) {
//printf("Packet decoded with clock 0x%07x (rv=%d)\n", pkt->clock, rv);
//btbb_print_packet(pkt);
max_rv = rv;
best_clk = (clk6 + i) & 0x3f;
}
}
}
}
} else
if (btbb_decode_header(pkt)) {
for(i=0; i<64; i++) {
pkt->clock = (pkt->clock & 0xffffffc0) | (i & 0x3f);
if (btbb_decode_header(pkt)) {
rv = btbb_decode_payload(pkt);
if(rv > max_rv) {
//printf("Packet decoded with clock 0x%02x (rv=%d)\n", i, rv);
//btbb_print_packet(pkt);
max_rv = rv;
best_clk = i & 0x3f;
}
}
}
}
/* If we were successful, print the packet */
if(max_rv > 0) {
pkt->clock = (pkt->clock & 0xffffffc0) | (best_clk & 0x3f);
btbb_decode_payload(pkt);
printf("Packet decoded with clock 0x%02x (rv=%d)\n", i, rv);
btbb_print_packet(pkt);
}
return max_rv;
}
/* Print AFH map from observed packets */
void btbb_print_afh_map(btbb_piconet *pn) {
uint8_t *afh_map;
afh_map = pn->afh_map;
/* Print like hcitool does */
printf("AFH map: 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
afh_map[0], afh_map[1], afh_map[2], afh_map[3], afh_map[4],
afh_map[5], afh_map[6], afh_map[7], afh_map[8], afh_map[9]);
// /* Printed ch78 -> ch0 */
// printf("\tAFH Map=0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
// afh_map[9], afh_map[8], afh_map[7], afh_map[6], afh_map[5],
// afh_map[4], afh_map[3], afh_map[2], afh_map[1], afh_map[0]);
}
/* Container for survey piconets */
typedef struct {
uint32_t key; /* LAP */
btbb_piconet *pn;
UT_hash_handle hh;
} survey_hash;
static survey_hash *piconet_survey = NULL;
/* Check for existing piconets in survey results */
btbb_piconet *get_piconet(uint32_t lap)
{
survey_hash *s;
btbb_piconet *pn;
HASH_FIND(hh, piconet_survey, &lap, 4, s);
if (s == NULL) {
pn = btbb_piconet_new();
btbb_init_piconet(pn, lap);
s = malloc(sizeof(survey_hash));
s->key = lap;
s->pn = pn;
HASH_ADD(hh, piconet_survey, key, 4, s);
} else {
pn = s->pn;
}
return pn;
}
/* Destructively iterate over survey results */
btbb_piconet *btbb_next_survey_result() {
btbb_piconet *pn = NULL;
survey_hash *tmp;
if (piconet_survey != NULL) {
pn = piconet_survey->pn;
tmp = piconet_survey;
piconet_survey = piconet_survey->hh.next;
free(tmp);
}
return pn;
}
int btbb_process_packet(btbb_packet *pkt, btbb_piconet *pn) {
if (survey_mode) {
pn = get_piconet(btbb_packet_get_lap(pkt));
btbb_piconet_set_channel_seen(pn, pkt->channel);
if(btbb_header_present(pkt) && !btbb_piconet_get_flag(pn, BTBB_UAP_VALID))
btbb_uap_from_header(pkt, pn);
return 0;
}
if(pn)
btbb_piconet_set_channel_seen(pn, pkt->channel);
/* If piconet structure is given, a LAP is given, and packet
* header is readable, do further analysis. If UAP has not yet
* been determined, attempt to calculate it from headers. Once
* UAP is known, try to determine clk6 and clk27. Once clocks
* are known, follow the piconet. */
if (pn && btbb_piconet_get_flag(pn, BTBB_LAP_VALID) &&
btbb_header_present(pkt)) {
/* Have LAP/UAP/clocks, now hopping along with the piconet. */
if (btbb_piconet_get_flag(pn, BTBB_FOLLOWING)) {
btbb_packet_set_uap(pkt, btbb_piconet_get_uap(pn));
btbb_packet_set_flag(pkt, BTBB_CLK6_VALID, 1);
btbb_packet_set_flag(pkt, BTBB_CLK27_VALID, 1);
if(btbb_decode(pkt, pn))
btbb_print_packet(pkt);
else
printf("Failed to decode packet\n");
}
/* Have LAP/UAP, need clocks. */
else if (btbb_piconet_get_uap(pn)) {
try_hop(pkt, pn);
if (btbb_piconet_get_flag(pn, BTBB_CLK6_VALID) &&
btbb_piconet_get_flag(pn, BTBB_CLK27_VALID)) {
btbb_piconet_set_flag(pn, BTBB_FOLLOWING, 1);
return -1;
}
}
/* Have LAP, need UAP. */
else {
btbb_uap_from_header(pkt, pn);
}
}
return 0;
}

View File

@ -0,0 +1,131 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BLUETOOTH_PICONET_H
#define INCLUDED_BLUETOOTH_PICONET_H
#include "btbb.h"
/* maximum number of hops to remember */
#define MAX_PATTERN_LENGTH 1000
/* number of channels in use */
#define BT_NUM_CHANNELS 79
struct btbb_piconet {
uint32_t refcount;
uint32_t flags;
/* true if using a particular aliased receiver implementation */
int aliased;
/* AFH channel map - either read or derived from observed packets */
uint8_t afh_map[10];
/* Number of used channel derived from AFH channel map */
uint8_t used_channels;
/* lower address part (of master's BD_ADDR) */
uint32_t LAP;
/* upper address part (of master's BD_ADDR) */
uint8_t UAP;
/* non-significant address part (of master's BD_ADDR) */
uint16_t NAP;
/* CLK1-27 candidates */
uint32_t *clock_candidates;
/* these values for hop() can be precalculated */
int b, e;
/* these values for hop() can be precalculated in part (e.g. a1 is the
* precalculated part of a) */
int a1, c1, d1;
/* frequency register bank */
int bank[BT_NUM_CHANNELS];
/* this holds the entire hopping sequence */
char *sequence;
/* number of candidates for CLK1-27 */
int num_candidates;
/* number of packets observed during one attempt at UAP/clock discovery */
int packets_observed;
/* total number of packets observed */
int total_packets_observed;
/* number of observed packets that have been used to winnow the candidates */
int winnowed;
/* CLK1-6 candidates */
int clock6_candidates[64];
/* remember patterns of observed hops */
int pattern_indices[MAX_PATTERN_LENGTH];
uint8_t pattern_channels[MAX_PATTERN_LENGTH];
/* offset between CLKN (local) and CLK of piconet */
int clk_offset;
/* local clock (clkn) at time of first packet */
uint32_t first_pkt_time;
/* queue of packets to be decoded */
pkt_queue *queue;
};
/* number of hops in the hopping sequence (i.e. number of possible values of CLK1-27) */
#define SEQUENCE_LENGTH 134217728
/* number of aliased channels received */
#define ALIASED_CHANNELS 25
/* do all the precalculation that can be done before knowing the address */
void precalc(btbb_piconet *pnet);
/* do precalculation that requires the address */
void address_precalc(int address, btbb_piconet *pnet);
/* drop-in replacement for perm5() using lookup table */
int fast_perm(int z, int p_high, int p_low);
/* 5 bit permutation */
/* assumes z is constrained to 5 bits, p_high to 5 bits, p_low to 9 bits */
int perm5(int z, int p_high, int p_low);
/* determine channel for a particular hop */
/* replaced with gen_hops() for a complete sequence but could still come in handy */
char single_hop(int clock, btbb_piconet *pnet);
/* look up channel for a particular hop */
char hop(int clock, btbb_piconet *pnet);
void try_hop(btbb_packet *pkt, btbb_piconet *pn);
void get_hop_pattern(btbb_piconet *pn);
#endif /* INCLUDED_BLUETOOTH_PICONET_H */

View File

@ -0,0 +1,288 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2013 Dominic Spill, Michael Ossmann, Will Code
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_BTBB_H
#define INCLUDED_BTBB_H
#include <stdint.h>
#define BTBB_WHITENED 0
#define BTBB_NAP_VALID 1
#define BTBB_UAP_VALID 2
#define BTBB_LAP_VALID 3
#define BTBB_CLK6_VALID 4
#define BTBB_CLK27_VALID 5
#define BTBB_CRC_CORRECT 6
#define BTBB_HAS_PAYLOAD 7
#define BTBB_IS_EDR 8
#define BTBB_HOP_REVERSAL_INIT 9
#define BTBB_GOT_FIRST_PACKET 10
#define BTBB_IS_AFH 11
#define BTBB_LOOKS_LIKE_AFH 12
#define BTBB_IS_ALIASED 13
#define BTBB_FOLLOWING 14
/* Payload modulation */
#define BTBB_MOD_UNKNOWN 0x00
#define BTBB_MOD_GFSK 0x01
#define BTBB_MOD_PI_OVER_2_DQPSK 0x02
#define BTBB_MOD_8DPSK 0x03
/* Transport types */
#define BTBB_TRANSPORT_ANY 0x00
#define BTBB_TRANSPORT_SCO 0x01
#define BTBB_TRANSPORT_ESCO 0x02
#define BTBB_TRANSPORT_ACL 0x03
#define BTBB_TRANSPORT_CSB 0x04
#ifdef __cplusplus
extern "C"
{
#endif
/* BT BR/EDR support */
typedef struct btbb_packet btbb_packet;
/* Initialize the library. Compute the syndrome. Return 0 on success,
* negative on error.
*
* The library limits max_ac_errors to 5. Using a larger value will
* take up a lot of memory (several GB), without decoding many useful
* packets. Even a limit of 5 results in a syndrome table of several
* hundred MB and lots of noise. For embedded targets, a value of 2 is
* reasonable. */
int btbb_init(int max_ac_errors);
char *btbb_get_release(void);
char *btbb_get_version(void);
btbb_packet *btbb_packet_new(void);
void btbb_packet_ref(btbb_packet *pkt);
void btbb_packet_unref(btbb_packet *pkt);
/* Search for a packet with specified LAP (or LAP_ANY). The stream
* must be at least of length serch_length + 72. Limit to
* 'max_ac_errors' bit errors.
*
* Returns offset into 'stream' at which packet was found. If no
* packet was found, returns a negative number. If LAP_ANY was
* specified, fills lap. 'ac_errors' must be set as an input, replaced
* by actual number of errors on output. */
int btbb_find_ac(char *stream,
int search_length,
uint32_t lap,
int max_ac_errors,
btbb_packet **pkt);
#define LAP_ANY 0xffffffffUL
#define UAP_ANY 0xff
void btbb_packet_set_flag(btbb_packet *pkt, int flag, int val);
int btbb_packet_get_flag(const btbb_packet *pkt, int flag);
uint32_t btbb_packet_get_lap(const btbb_packet *pkt);
void btbb_packet_set_uap(btbb_packet *pkt, uint8_t uap);
uint8_t btbb_packet_get_uap(const btbb_packet *pkt);
uint16_t btbb_packet_get_nap(const btbb_packet *pkt);
void btbb_packet_set_modulation(btbb_packet *pkt, uint8_t modulation);
void btbb_packet_set_transport(btbb_packet *pkt, uint8_t transport);
uint8_t btbb_packet_get_modulation(const btbb_packet *pkt);
uint8_t btbb_packet_get_transport(const btbb_packet *pkt);
uint8_t btbb_packet_get_channel(const btbb_packet *pkt);
uint8_t btbb_packet_get_ac_errors(const btbb_packet *pkt);
uint32_t btbb_packet_get_clkn(const btbb_packet *pkt);
uint32_t btbb_packet_get_header_packed(const btbb_packet* pkt);
void btbb_packet_set_data(btbb_packet *pkt,
char *syms, // Symbol data
int length, // Number of symbols
uint8_t channel, // Bluetooth channel 0-79
uint32_t clkn); // 312.5us clock (CLK27-0)
/* Get a pointer to packet symbols. */
const char *btbb_get_symbols(const btbb_packet* pkt);
int btbb_packet_get_payload_length(const btbb_packet* pkt);
/* Get a pointer to payload. */
const char *btbb_get_payload(const btbb_packet* pkt);
/* Pack the payload in to bytes */
int btbb_get_payload_packed(const btbb_packet* pkt, char *dst);
uint8_t btbb_packet_get_type(const btbb_packet* pkt);
uint8_t btbb_packet_get_lt_addr(const btbb_packet* pkt);
uint8_t btbb_packet_get_header_flags(const btbb_packet* pkt);
uint8_t btbb_packet_get_hec(const btbb_packet *pkt);
/* Generate Sync Word from an LAP */
uint64_t btbb_gen_syncword(const int LAP);
/* decode the packet header */
int btbb_decode_header(btbb_packet* pkt);
/* decode the packet header */
int btbb_decode_payload(btbb_packet* pkt);
/* print packet information */
void btbb_print_packet(const btbb_packet* pkt);
/* check to see if the packet has a header */
int btbb_header_present(const btbb_packet* pkt);
/* Packet queue (linked list) */
typedef struct pkt_queue {
btbb_packet *pkt;
struct pkt_queue *next;
} pkt_queue;
typedef struct btbb_piconet btbb_piconet;
btbb_piconet *btbb_piconet_new(void);
void btbb_piconet_ref(btbb_piconet *pn);
void btbb_piconet_unref(btbb_piconet *pn);
/* initialize the piconet struct */
void btbb_init_piconet(btbb_piconet *pn, uint32_t lap);
void btbb_piconet_set_uap(btbb_piconet *pn, uint8_t uap);
uint8_t btbb_piconet_get_uap(const btbb_piconet *pn);
uint32_t btbb_piconet_get_lap(const btbb_piconet *pn);
uint16_t btbb_piconet_get_nap(const btbb_piconet *pn);
uint64_t btbb_piconet_get_bdaddr(const btbb_piconet *pn);
int btbb_piconet_get_clk_offset(const btbb_piconet *pn);
void btbb_piconet_set_clk_offset(btbb_piconet *pn, int clk_offset);
void btbb_piconet_set_flag(btbb_piconet *pn, int flag, int val);
int btbb_piconet_get_flag(const btbb_piconet *pn, int flag);
void btbb_piconet_set_channel_seen(btbb_piconet *pn, uint8_t channel);
void btbb_piconet_set_afh_map(btbb_piconet *pn, uint8_t *afh_map);
uint8_t *btbb_piconet_get_afh_map(btbb_piconet *pn);
/* Extract as much information (LAP/UAP/CLK) as possible from received packet */
int btbb_process_packet(btbb_packet *pkt, btbb_piconet *pn);
/* use packet headers to determine UAP */
int btbb_uap_from_header(btbb_packet *pkt, btbb_piconet *pn);
/* Print hexadecimal representation of the derived AFH map */
void btbb_print_afh_map(btbb_piconet *pn);
/* decode a whole packet from the given piconet */
int btbb_decode(btbb_packet* pkt, btbb_piconet *pn);
/* initialize the hop reversal process */
/* returns number of initial candidates for CLK1-27 */
int btbb_init_hop_reversal(int aliased, btbb_piconet *pn);
/* narrow a list of candidate clock values based on all observed hops */
int btbb_winnow(btbb_piconet *pn);
int btbb_init_survey(void);
/* Destructively iterate over survey results - optionally remove elements */
btbb_piconet *btbb_next_survey_result(void);
typedef struct btbb_pcapng_handle btbb_pcapng_handle;
/* create a PCAPNG file for BREDR captures */
int btbb_pcapng_create_file(const char *filename, const char *interface_desc, btbb_pcapng_handle ** ph);
/* save a BREDR packet to PCAPNG capture file */
int btbb_pcapng_append_packet(btbb_pcapng_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t reflap, const uint8_t refuap,
const btbb_packet *pkt);
/* record a BDADDR to PCAPNG capture file */
int btbb_pcapng_record_bdaddr(btbb_pcapng_handle * h, const uint64_t bdaddr,
const uint8_t uapmask, const uint8_t napvalid);
/* record BT CLOCK to PCAPNG capture file */
int btbb_pcapng_record_btclock(btbb_pcapng_handle * h, const uint64_t bdaddr,
const uint64_t ns, const uint32_t clk, const uint32_t clkmask);
int btbb_pcapng_close(btbb_pcapng_handle * h);
/* BLE support */
typedef struct lell_packet lell_packet;
/* decode and allocate LE packet */
void lell_allocate_and_decode(const uint8_t *stream, uint16_t phys_channel, uint32_t clk100ns, lell_packet **pkt);
lell_packet *lell_packet_new(void);
void lell_packet_ref(lell_packet *pkt);
void lell_packet_unref(lell_packet *pkt);
uint32_t lell_get_access_address(const lell_packet *pkt);
unsigned lell_get_access_address_offenses(const lell_packet *pkt);
unsigned lell_packet_is_data(const lell_packet *pkt);
unsigned lell_get_channel_index(const lell_packet *pkt);
unsigned lell_get_channel_k(const lell_packet *pkt);
const char * lell_get_adv_type_str(const lell_packet *pkt);
void lell_print(const lell_packet *pkt);
typedef struct lell_pcapng_handle lell_pcapng_handle;
/* create a PCAPNG file for LE captures */
int lell_pcapng_create_file(const char *filename, const char *interface_desc, lell_pcapng_handle ** ph);
/* save an LE packet to PCAPNG capture file */
int lell_pcapng_append_packet(lell_pcapng_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t refAA, const lell_packet *pkt);
/* record LE CONNECT_REQ parameters to PCAPNG capture file */
int lell_pcapng_record_connect_req(lell_pcapng_handle * h, const uint64_t ns, const uint8_t * pdu);
int lell_pcapng_close(lell_pcapng_handle *h);
/* PCAP Support */
#if defined(ENABLE_PCAP)
typedef struct btbb_pcap_handle btbb_pcap_handle;
/* create a PCAP file for BREDR captures with LINKTYPE_BLUETOOTH_BREDR_BB */
int btbb_pcap_create_file(const char *filename, btbb_pcap_handle ** ph);
/* write a BREDR packet to PCAP file */
int btbb_pcap_append_packet(btbb_pcap_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t reflap, const uint8_t refuap,
const btbb_packet *pkt);
int btbb_pcap_close(btbb_pcap_handle * h);
typedef struct lell_pcap_handle lell_pcap_handle;
/* create a PCAP file for LE captures using LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR */
int lell_pcap_create_file(const char *filename, lell_pcap_handle ** ph);
/* create a PCAP file for LE captures using LINKTYPE_PPI */
int lell_pcap_ppi_create_file(const char *filename, int btle_ppi_version, lell_pcap_handle ** ph);
/* save an LE packet to PCAP capture file */
int lell_pcap_append_packet(lell_pcap_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t refAA, const lell_packet *pkt);
int lell_pcap_append_ppi_packet(lell_pcap_handle * h, const uint64_t ns,
const uint8_t clkn_high,
const int8_t rssi_min, const int8_t rssi_max,
const int8_t rssi_avg, const uint8_t rssi_count,
const lell_packet *pkt);
int lell_pcap_close(lell_pcap_handle *h);
#endif // ENABLE_PCAP
#ifdef __cplusplus
} // __cplusplus defined.
#endif
#endif /* INCLUDED_BTBB_H */

View File

@ -0,0 +1,129 @@
/* -*- c -*- */
/*
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef PCAP_COMMON_DOT_H
#define PCAP_COMMON_DOT_H
/* pull definitions for BT DLTs and pseudoheaders from libpcap, if possible */
#if defined(ENABLE_PCAP)
#include <pcap/pcap.h>
#include <pcap/bluetooth.h>
#endif /* ENABLE_PCAP */
#if defined( __APPLE__ )
#include <CoreServices/CoreServices.h>
#define htobe32 EndianU32_NtoB
#define be32toh EndianU32_BtoN
#define le32toh EndianU32_LtoN
#define htobe64 EndianU64_NtoB
#define be64toh EndianU64_BtoN
#define htole16 EndianU16_NtoL
#define htole32 EndianU32_NtoL
#else
#include <endian.h>
#endif
#if !defined( htole16 ) /* will be defined under Linux when endian.h already included */
#if defined( __GNUC__ )
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
inline uint16_t htole16(uint16_t host_16bits) { return host_16bits; }
inline uint16_t le16toh(uint16_t little_endian_16bits) { return little_endian_16bits; }
inline uint32_t htole32(uint32_t host_32bits) { return host_32bits; }
inline uint32_t le32toh(uint32_t little_endian_32bits) { return little_endian_32bits; }
inline uint64_t htole64(uint64_t host_64bits) { return host_64bits; }
inline uint64_t le64toh(uint64_t little_endian_64bits) { return little_endian_64bits; }
#else
#error "FIXME: need to support big-endian under GNU"
#endif /* __BYTE_ORDER__ */
#else /* not GNU C */
#error "FIXME: need to support non-GNU compiler"
#endif /* __GNUC__ */
#endif /* htole16 */
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
/* --------------------------------- BR/EDR ----------------------------- */
#if !defined( DLT_BLUETOOTH_BREDR_BB )
#define DLT_BLUETOOTH_BREDR_BB 255
#endif
typedef struct __attribute__((packed)) _pcap_bluetooth_bredr_bb_header {
uint8_t rf_channel;
int8_t signal_power;
int8_t noise_power;
uint8_t access_code_offenses;
uint8_t payload_transport_rate;
uint8_t corrected_header_bits;
int16_t corrected_payload_bits;
uint32_t lap;
uint32_t ref_lap_uap;
uint32_t bt_header;
uint16_t flags;
uint8_t br_edr_payload[0];
} pcap_bluetooth_bredr_bb_header;
#define BREDR_DEWHITENED 0x0001
#define BREDR_SIGPOWER_VALID 0x0002
#define BREDR_NOISEPOWER_VALID 0x0004
#define BREDR_PAYLOAD_DECRYPTED 0x0008
#define BREDR_REFLAP_VALID 0x0010
#define BREDR_PAYLOAD_PRESENT 0x0020
#define BREDR_CHANNEL_ALIASED 0x0040
#define BREDR_REFUAP_VALID 0x0080
#define BREDR_HEC_CHECKED 0x0100
#define BREDR_HEC_VALID 0x0200
#define BREDR_CRC_CHECKED 0x0400
#define BREDR_CRC_VALID 0x0800
#define BREDR_MIC_CHECKED 0x1000
#define BREDR_MIC_VALID 0x2000
#define BREDR_MAX_PAYLOAD 400
/* --------------------------------- Low Energy ---------------------------- */
#if !defined( DLT_BLUETOOTH_LE_LL_WITH_PHDR )
#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
#endif
typedef struct __attribute__((packed)) _pcap_bluetooth_le_ll_header {
uint8_t rf_channel;
int8_t signal_power;
int8_t noise_power;
uint8_t access_address_offenses;
uint32_t ref_access_address;
uint16_t flags;
uint8_t le_packet[0];
} pcap_bluetooth_le_ll_header;
#define LE_DEWHITENED 0x0001
#define LE_SIGPOWER_VALID 0x0002
#define LE_NOISEPOWER_VALID 0x0004
#define LE_PACKET_DECRYPTED 0x0008
#define LE_REF_AA_VALID 0x0010
#define LE_AA_OFFENSES_VALID 0x0020
#define LE_CHANNEL_ALIASED 0x0040
#define LE_CRC_CHECKED 0x0400
#define LE_CRC_VALID 0x0800
#define LE_MIC_CHECKED 0x1000
#define LE_MIC_VALID 0x2000
#define LE_MAX_PAYLOAD 48
#endif /* PCAP_COMMON_DOT_H */

View File

@ -0,0 +1,422 @@
/* -*- c -*- */
/*
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "bluetooth_le_packet.h"
#include "bluetooth_packet.h"
#include "btbb.h"
#include "pcap-common.h"
#include <stdlib.h>
#include <string.h>
typedef enum {
PCAP_OK = 0,
PCAP_INVALID_HANDLE,
PCAP_FILE_NOT_ALLOWED,
PCAP_NO_MEMORY,
} PCAP_RESULT;
#if defined(ENABLE_PCAP)
/* BT BR/EDR support */
struct btbb_pcap_handle {
pcap_t * pcap;
pcap_dumper_t * dumper;
};
int
btbb_pcap_create_file(const char *filename, btbb_pcap_handle ** ph)
{
int retval = 0;
btbb_pcap_handle * handle = malloc( sizeof(btbb_pcap_handle) );
if (handle) {
memset(handle, 0, sizeof(*handle));
#ifdef PCAP_TSTAMP_PRECISION_NANO
handle->pcap = pcap_open_dead_with_tstamp_precision(DLT_BLUETOOTH_BREDR_BB,
BREDR_MAX_PAYLOAD,
PCAP_TSTAMP_PRECISION_NANO);
#else
handle->pcap = pcap_open_dead(DLT_BLUETOOTH_BREDR_BB, BREDR_MAX_PAYLOAD);
#endif
if (handle->pcap) {
handle->dumper = pcap_dump_open(handle->pcap, filename);
if (handle->dumper) {
*ph = handle;
}
else {
pcap_perror(handle->pcap, "PCAP error:");
retval = -PCAP_FILE_NOT_ALLOWED;
goto fail;
}
}
else {
retval = -PCAP_INVALID_HANDLE;
goto fail;
}
}
else {
retval = -PCAP_NO_MEMORY;
goto fail;
}
return retval;
fail:
(void) btbb_pcap_close( handle );
return retval;
}
typedef struct {
struct pcap_pkthdr pcap_header;
pcap_bluetooth_bredr_bb_header bredr_bb_header;
uint8_t bredr_payload[BREDR_MAX_PAYLOAD];
} pcap_bredr_packet;
static void
assemble_pcapng_bredr_packet( pcap_bredr_packet * pkt,
const uint32_t interface_id __attribute__((unused)),
const uint64_t ns,
const uint32_t caplen,
const uint8_t rf_channel,
const int8_t signal_power,
const int8_t noise_power,
const uint8_t access_code_offenses,
const uint8_t payload_transport,
const uint8_t payload_rate,
const uint8_t corrected_header_bits,
const int16_t corrected_payload_bits,
const uint32_t lap,
const uint32_t ref_lap,
const uint8_t ref_uap,
const uint32_t bt_header,
const uint16_t flags,
const uint8_t * payload )
{
uint32_t pcap_caplen = sizeof(pcap_bluetooth_bredr_bb_header)+caplen;
uint32_t reflapuap = (ref_lap&0xffffff) | (ref_uap<<24);
pkt->pcap_header.ts.tv_sec = ns / 1000000000ull;
pkt->pcap_header.ts.tv_usec = ns % 1000000000ull;
pkt->pcap_header.caplen = pcap_caplen;
pkt->pcap_header.len = pcap_caplen;
pkt->bredr_bb_header.rf_channel = rf_channel;
pkt->bredr_bb_header.signal_power = signal_power;
pkt->bredr_bb_header.noise_power = noise_power;
pkt->bredr_bb_header.access_code_offenses = access_code_offenses;
pkt->bredr_bb_header.payload_transport_rate =
(payload_transport << 4) | payload_rate;
pkt->bredr_bb_header.corrected_header_bits = corrected_header_bits;
pkt->bredr_bb_header.corrected_payload_bits = htole16( corrected_payload_bits );
pkt->bredr_bb_header.lap = htole32( lap );
pkt->bredr_bb_header.ref_lap_uap = htole32( reflapuap );
pkt->bredr_bb_header.bt_header = htole16( bt_header );
pkt->bredr_bb_header.flags = htole16( flags );
if (caplen) {
(void) memcpy( &pkt->bredr_payload[0], payload, caplen );
}
else {
pkt->bredr_bb_header.flags &= htole16( ~BREDR_PAYLOAD_PRESENT );
}
}
int
btbb_pcap_append_packet(btbb_pcap_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t reflap, const uint8_t refuap,
const btbb_packet *pkt)
{
if (h && h->dumper) {
uint16_t flags = BREDR_DEWHITENED | BREDR_SIGPOWER_VALID |
((noisedbm < sigdbm) ? BREDR_NOISEPOWER_VALID : 0) |
((reflap != LAP_ANY) ? BREDR_REFLAP_VALID : 0) |
((refuap != UAP_ANY) ? BREDR_REFUAP_VALID : 0);
uint32_t caplen = (uint32_t) btbb_packet_get_payload_length(pkt);
uint8_t payload_bytes[caplen];
btbb_get_payload_packed( pkt, (char *) &payload_bytes[0] );
caplen = MIN(BREDR_MAX_PAYLOAD, caplen);
pcap_bredr_packet pcap_pkt;
assemble_pcapng_bredr_packet( &pcap_pkt,
0,
ns,
caplen,
btbb_packet_get_channel(pkt),
sigdbm,
noisedbm,
btbb_packet_get_ac_errors(pkt),
btbb_packet_get_transport(pkt),
btbb_packet_get_modulation(pkt),
0, /* TODO: corrected header bits */
0, /* TODO: corrected payload bits */
btbb_packet_get_lap(pkt),
reflap,
refuap,
btbb_packet_get_header_packed(pkt),
flags,
payload_bytes );
pcap_dump((u_char *)h->dumper, &pcap_pkt.pcap_header, (u_char *)&pcap_pkt.bredr_bb_header);
return 0;
}
return -PCAP_INVALID_HANDLE;
}
int
btbb_pcap_close(btbb_pcap_handle * h)
{
if (h && h->dumper) {
pcap_dump_close(h->dumper);
}
if (h && h->pcap) {
pcap_close(h->pcap);
}
if (h) {
free(h);
return 0;
}
return -PCAP_INVALID_HANDLE;
}
/* BTLE support */
struct lell_pcap_handle {
pcap_t * pcap;
pcap_dumper_t * dumper;
int dlt;
uint8_t btle_ppi_version;
};
static int
lell_pcap_create_file_dlt(const char *filename, int dlt, lell_pcap_handle ** ph)
{
int retval = 0;
lell_pcap_handle * handle = malloc( sizeof(lell_pcap_handle) );
if (handle) {
memset(handle, 0, sizeof(*handle));
#ifdef PCAP_TSTAMP_PRECISION_NANO
handle->pcap = pcap_open_dead_with_tstamp_precision(dlt,
BREDR_MAX_PAYLOAD,
PCAP_TSTAMP_PRECISION_NANO);
#else
handle->pcap = pcap_open_dead(dlt, BREDR_MAX_PAYLOAD);
#endif
if (handle->pcap) {
handle->dumper = pcap_dump_open(handle->pcap, filename);
if (handle->dumper) {
handle->dlt = dlt;
*ph = handle;
}
else {
retval = -PCAP_FILE_NOT_ALLOWED;
goto fail;
}
}
else {
retval = -PCAP_INVALID_HANDLE;
goto fail;
}
}
else {
retval = -PCAP_NO_MEMORY;
goto fail;
}
return retval;
fail:
(void) lell_pcap_close( handle );
return retval;
}
int
lell_pcap_create_file(const char *filename, lell_pcap_handle ** ph)
{
return lell_pcap_create_file_dlt(filename, DLT_BLUETOOTH_LE_LL_WITH_PHDR, ph);
}
int
lell_pcap_ppi_create_file(const char *filename, int btle_ppi_version,
lell_pcap_handle ** ph)
{
int retval = lell_pcap_create_file_dlt(filename, DLT_PPI, ph);
if (!retval) {
(*ph)->btle_ppi_version = btle_ppi_version;
}
return retval;
}
typedef struct {
struct pcap_pkthdr pcap_header;
pcap_bluetooth_le_ll_header le_ll_header;
uint8_t le_packet[LE_MAX_PAYLOAD];
} pcap_le_packet;
static void
assemble_pcapng_le_packet( pcap_le_packet * pkt,
const uint32_t interface_id __attribute__((unused)),
const uint64_t ns,
const uint32_t caplen,
const uint8_t rf_channel,
const int8_t signal_power,
const int8_t noise_power,
const uint8_t access_address_offenses,
const uint32_t ref_access_address,
const uint16_t flags,
const uint8_t * lepkt )
{
uint32_t pcap_caplen = sizeof(pcap_bluetooth_le_ll_header)+caplen;
pkt->pcap_header.ts.tv_sec = ns / 1000000000ull;
pkt->pcap_header.ts.tv_usec = ns % 1000000000ull;
pkt->pcap_header.caplen = pcap_caplen;
pkt->pcap_header.len = pcap_caplen;
pkt->le_ll_header.rf_channel = rf_channel;
pkt->le_ll_header.signal_power = signal_power;
pkt->le_ll_header.noise_power = noise_power;
pkt->le_ll_header.access_address_offenses = access_address_offenses;
pkt->le_ll_header.ref_access_address = htole32( ref_access_address );
pkt->le_ll_header.flags = htole16( flags );
(void) memcpy( &pkt->le_packet[0], lepkt, caplen );
}
int
lell_pcap_append_packet(lell_pcap_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t refAA, const lell_packet *pkt)
{
if (h && h->dumper &&
(h->dlt == DLT_BLUETOOTH_LE_LL_WITH_PHDR)) {
uint16_t flags = LE_DEWHITENED | LE_AA_OFFENSES_VALID |
LE_SIGPOWER_VALID |
((noisedbm < sigdbm) ? LE_NOISEPOWER_VALID : 0) |
(lell_packet_is_data(pkt) ? 0 : LE_REF_AA_VALID);
pcap_le_packet pcap_pkt;
assemble_pcapng_le_packet( &pcap_pkt,
0,
ns,
9+pkt->length,
pkt->channel_k,
sigdbm,
noisedbm,
pkt->access_address_offenses,
refAA,
flags,
&pkt->symbols[0] );
pcap_dump((u_char *)h->dumper, &pcap_pkt.pcap_header, (u_char *)&pcap_pkt.le_ll_header);
return 0;
}
return -PCAP_INVALID_HANDLE;
}
#define PPI_BTLE 30006
typedef struct __attribute__((packed)) {
uint8_t pph_version;
uint8_t pph_flags;
uint16_t pph_len;
uint32_t pph_dlt;
} ppi_packet_header_t;
typedef struct __attribute__((packed)) {
uint16_t pfh_type;
uint16_t pfh_datalen;
} ppi_fieldheader_t;
typedef struct __attribute__((packed)) {
uint8_t btle_version;
uint16_t btle_channel;
uint8_t btle_clkn_high;
uint32_t btle_clk100ns;
int8_t rssi_max;
int8_t rssi_min;
int8_t rssi_avg;
uint8_t rssi_count;
} ppi_btle_t;
typedef struct __attribute__((packed)) {
struct pcap_pkthdr pcap_header;
ppi_packet_header_t ppi_packet_header;
ppi_fieldheader_t ppi_fieldheader;
ppi_btle_t le_ll_ppi_header;
uint8_t le_packet[LE_MAX_PAYLOAD];
} pcap_ppi_le_packet;
int
lell_pcap_append_ppi_packet(lell_pcap_handle * h, const uint64_t ns,
const uint8_t clkn_high,
const int8_t rssi_min, const int8_t rssi_max,
const int8_t rssi_avg, const uint8_t rssi_count,
const lell_packet *pkt)
{
const uint16_t ppi_packet_header_sz = sizeof(ppi_packet_header_t);
const uint16_t ppi_fieldheader_sz = sizeof(ppi_fieldheader_t);
const uint16_t le_ll_ppi_header_sz = sizeof(ppi_btle_t);
if (h && h->dumper &&
(h->dlt == DLT_PPI)) {
pcap_ppi_le_packet pcap_pkt;
uint32_t pcap_caplen =
ppi_packet_header_sz+ppi_fieldheader_sz+le_ll_ppi_header_sz+pkt->length+9;
uint16_t MHz = 2402 + 2*lell_get_channel_k(pkt);
pcap_pkt.pcap_header.ts.tv_sec = ns / 1000000000ull;
pcap_pkt.pcap_header.ts.tv_usec = ns % 1000000000ull;
pcap_pkt.pcap_header.caplen = pcap_caplen;
pcap_pkt.pcap_header.len = pcap_caplen;
pcap_pkt.ppi_packet_header.pph_version = 0;
pcap_pkt.ppi_packet_header.pph_flags = 0;
pcap_pkt.ppi_packet_header.pph_len = htole16(ppi_packet_header_sz+ppi_fieldheader_sz+le_ll_ppi_header_sz);
pcap_pkt.ppi_packet_header.pph_dlt = htole32(DLT_USER0);
pcap_pkt.ppi_fieldheader.pfh_type = htole16(PPI_BTLE);
pcap_pkt.ppi_fieldheader.pfh_datalen = htole16(le_ll_ppi_header_sz);
pcap_pkt.le_ll_ppi_header.btle_version = h->btle_ppi_version;
pcap_pkt.le_ll_ppi_header.btle_channel = htole16(MHz);
pcap_pkt.le_ll_ppi_header.btle_clkn_high = clkn_high;
pcap_pkt.le_ll_ppi_header.btle_clk100ns = htole32(pkt->clk100ns);
pcap_pkt.le_ll_ppi_header.rssi_max = rssi_max;
pcap_pkt.le_ll_ppi_header.rssi_min = rssi_min;
pcap_pkt.le_ll_ppi_header.rssi_avg = rssi_avg;
pcap_pkt.le_ll_ppi_header.rssi_count = rssi_count;
(void) memcpy( &pcap_pkt.le_packet[0], &pkt->symbols[0], pkt->length + 9 ); // FIXME where does the 9 come from?
pcap_dump((u_char *)h->dumper, &pcap_pkt.pcap_header, (u_char *)&pcap_pkt.ppi_packet_header);
pcap_dump_flush(h->dumper);
return 0;
}
return -PCAP_INVALID_HANDLE;
}
int
lell_pcap_close(lell_pcap_handle *h)
{
if (h && h->dumper) {
pcap_dump_close(h->dumper);
}
if (h && h->pcap) {
pcap_close(h->pcap);
}
if (h) {
free(h);
return 0;
}
return -PCAP_INVALID_HANDLE;
}
#endif /* ENABLE_PCAP */

View File

@ -0,0 +1,522 @@
/* -*- c -*- */
/*
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "btbb.h"
#include "bluetooth_le_packet.h"
#include "bluetooth_packet.h"
#include "pcapng-bt.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
/* generic section options indicating libbtbb */
const struct {
struct {
option_header hdr;
char libname[8];
} libopt;
struct {
option_header hdr;
} termopt;
} libbtbb_section_options = {
.libopt = {
.hdr = {
.option_code = SHB_USERAPPL,
.option_length = 7 },
.libname = "libbtbb"
},
.termopt = {
.hdr = {
.option_code = OPT_ENDOFOPT,
.option_length = 0
}
}
};
static PCAPNG_RESULT
check_and_fix_tsresol( PCAPNG_HANDLE * handle,
const option_header * interface_options )
{
PCAPNG_RESULT retval = PCAPNG_OK;
int got_tsresol = 0;
while( !got_tsresol &&
interface_options &&
interface_options->option_code &&
interface_options->option_length) {
if (interface_options->option_code == IF_TSRESOL) {
got_tsresol = 1;
}
else {
size_t step = 4+4*((interface_options->option_length+3)/4);
uint8_t * next = &((uint8_t *)interface_options)[step];
interface_options = (const option_header *) next;
}
}
if (!got_tsresol) {
const struct {
option_header hdr;
uint8_t resol;
} tsresol = {
.hdr = {
.option_code = IF_TSRESOL,
.option_length = 1,
},
.resol = 9 /* 10^-9 is nanoseconds */
};
retval = pcapng_append_interface_option( handle,
(const option_header *) &tsresol );
}
return retval;
}
/* --------------------------------- BR/EDR ----------------------------- */
static PCAPNG_RESULT
create_bredr_capture_file_single_interface( PCAPNG_HANDLE * handle,
const char * filename,
const option_header * interface_options )
{
PCAPNG_RESULT retval = PCAPNG_OK;
retval = pcapng_create( handle,
filename,
(const option_header *) &libbtbb_section_options,
(size_t) getpagesize( ),
DLT_BLUETOOTH_BREDR_BB,
BREDR_MAX_PAYLOAD,
interface_options,
(size_t) getpagesize( ) );
if (retval == PCAPNG_OK) {
/* if there is no timestamp resolution alread in the
interface options, record nanosecond resolution */
retval = check_and_fix_tsresol( handle, interface_options );
if (retval != PCAPNG_OK) {
(void) pcapng_close( handle );
}
}
return retval;
}
int btbb_pcapng_create_file( const char *filename,
const char *interface_desc,
btbb_pcapng_handle ** ph )
{
int retval = PCAPNG_OK;
PCAPNG_HANDLE * handle = malloc( sizeof(PCAPNG_HANDLE) );
if (handle) {
const option_header * popt = NULL;
struct {
option_header header;
char desc[256];
} ifopt = {
.header = {
.option_code = IF_DESCRIPTION,
}
};
if (interface_desc) {
(void) strncpy( &ifopt.desc[0], interface_desc, 256 );
ifopt.desc[255] = '\0';
ifopt.header.option_length = strlen( ifopt.desc );
popt = (const option_header *) &ifopt;
}
retval = -create_bredr_capture_file_single_interface( handle,
filename,
popt );
if (retval == PCAPNG_OK) {
*ph = (btbb_pcapng_handle *) handle;
}
else {
free( handle );
}
}
else {
retval = -PCAPNG_NO_MEMORY;
}
return retval;
}
static PCAPNG_RESULT
append_bredr_packet( PCAPNG_HANDLE * handle,
pcapng_bredr_packet * pkt )
{
return pcapng_append_packet( handle, ( const enhanced_packet_block *) pkt );
}
static void
assemble_pcapng_bredr_packet( pcapng_bredr_packet * pkt,
const uint32_t interface_id,
const uint64_t ns,
const uint32_t caplen,
const uint8_t rf_channel,
const int8_t signal_power,
const int8_t noise_power,
const uint8_t access_code_offenses,
const uint8_t payload_transport,
const uint8_t payload_rate,
const uint8_t corrected_header_bits,
const int16_t corrected_payload_bits,
const uint32_t lap,
const uint32_t ref_lap,
const uint8_t ref_uap,
const uint32_t bt_header,
const uint16_t flags,
const char * payload )
{
uint32_t pcapng_caplen = sizeof(pcap_bluetooth_bredr_bb_header)+caplen;
uint32_t block_length = 4*((36+pcapng_caplen+3)/4);
uint32_t reflapuap = (ref_lap&0xffffff) | (ref_uap<<24);
pkt->blk_header.block_type = BLOCK_TYPE_ENHANCED_PACKET;
pkt->blk_header.block_total_length = block_length;
pkt->blk_header.interface_id = interface_id;
pkt->blk_header.timestamp_high = (uint32_t) (ns >> 32);
pkt->blk_header.timestamp_low = (uint32_t) (ns & 0x0ffffffffull);
pkt->blk_header.captured_len = pcapng_caplen;
pkt->blk_header.packet_len = pcapng_caplen;
pkt->bredr_bb_header.rf_channel = rf_channel;
pkt->bredr_bb_header.signal_power = signal_power;
pkt->bredr_bb_header.noise_power = noise_power;
pkt->bredr_bb_header.access_code_offenses = access_code_offenses;
pkt->bredr_bb_header.payload_transport_rate =
(payload_transport << 4) | payload_rate;
pkt->bredr_bb_header.corrected_header_bits = corrected_header_bits;
pkt->bredr_bb_header.corrected_payload_bits = htole16( corrected_payload_bits );
pkt->bredr_bb_header.lap = htole32( lap );
pkt->bredr_bb_header.ref_lap_uap = htole32( reflapuap );
pkt->bredr_bb_header.bt_header = htole16( bt_header );
pkt->bredr_bb_header.flags = htole16( flags );
if (caplen) {
(void) memcpy( &pkt->bredr_payload[0], payload, caplen );
}
else {
pkt->bredr_bb_header.flags &= htole16( ~BREDR_PAYLOAD_PRESENT );
}
((uint32_t *)pkt)[block_length/4-2] = 0x00000000; /* no-options */
((uint32_t *)pkt)[block_length/4-1] = block_length;
}
int btbb_pcapng_append_packet(btbb_pcapng_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t reflap, const uint8_t refuap,
const btbb_packet *pkt)
{
uint16_t flags = BREDR_DEWHITENED | BREDR_SIGPOWER_VALID |
((noisedbm < sigdbm) ? BREDR_NOISEPOWER_VALID : 0) |
((reflap != LAP_ANY) ? BREDR_REFLAP_VALID : 0) |
((refuap != UAP_ANY) ? BREDR_REFUAP_VALID : 0);
int caplen = btbb_packet_get_payload_length(pkt);
char payload_bytes[caplen];
btbb_get_payload_packed( pkt, &payload_bytes[0] );
caplen = MIN(BREDR_MAX_PAYLOAD, caplen);
pcapng_bredr_packet pcapng_pkt;
assemble_pcapng_bredr_packet( &pcapng_pkt,
0,
ns,
caplen,
btbb_packet_get_channel(pkt),
sigdbm,
noisedbm,
btbb_packet_get_ac_errors(pkt),
btbb_packet_get_transport(pkt),
btbb_packet_get_modulation(pkt),
0, /* TODO: corrected header bits */
0, /* TODO: corrected payload bits */
btbb_packet_get_lap(pkt),
reflap,
refuap,
btbb_packet_get_header_packed(pkt),
flags,
payload_bytes );
return -append_bredr_packet( (PCAPNG_HANDLE *)h, &pcapng_pkt );
}
static PCAPNG_RESULT
record_bd_addr_info( PCAPNG_HANDLE * handle,
const uint64_t bd_addr,
const uint8_t uap_mask,
const uint8_t nap_valid )
{
const bredr_br_addr_option bdopt = {
.header = {
.option_code = PCAPNG_BREDR_OPTION_BD_ADDR,
.option_length = sizeof(bredr_br_addr_option),
},
.bd_addr_info = {
.bd_addr = {
((bd_addr>>0) & 0xff),
((bd_addr>>8) & 0xff),
((bd_addr>>16) & 0xff),
((bd_addr>>24) & 0xff),
((bd_addr>>32) & 0xff),
((bd_addr>>40) & 0xff)
},
.uap_mask = uap_mask,
.nap_valid = nap_valid,
}
};
return pcapng_append_interface_option( handle,
(const option_header *) &bdopt );
}
int btbb_pcapng_record_bdaddr(btbb_pcapng_handle * h, const uint64_t bdaddr,
const uint8_t uapmask, const uint8_t napvalid)
{
return -record_bd_addr_info( (PCAPNG_HANDLE *) h,
bdaddr, uapmask, napvalid );
}
static PCAPNG_RESULT
record_bredr_master_clock_info( PCAPNG_HANDLE * handle,
const uint64_t bd_addr,
const uint64_t ns,
const uint32_t clk,
const uint32_t clk_mask)
{
const bredr_clk_option mcopt = {
.header = {
.option_code = PCAPNG_BREDR_OPTION_MASTER_CLOCK_INFO,
.option_length = sizeof(bredr_clk_option)
},
.clock_info = {
.ts = ns,
.lap_uap = htole32(bd_addr & 0xffffffff),
.clk = clk,
.clk_mask = clk_mask
}
};
return pcapng_append_interface_option( handle,
(const option_header *) &mcopt );
}
int btbb_pcapng_record_btclock(btbb_pcapng_handle * h, const uint64_t bdaddr,
const uint64_t ns, const uint32_t clk,
const uint32_t clkmask)
{
return -record_bredr_master_clock_info( (PCAPNG_HANDLE *) h,
bdaddr, ns, clk, clkmask );
}
int btbb_pcapng_close(btbb_pcapng_handle * h)
{
pcapng_close( (PCAPNG_HANDLE *) h );
if (h) {
free( h );
}
return -PCAPNG_INVALID_HANDLE;
}
/* --------------------------------- Low Energy ---------------------------- */
static PCAPNG_RESULT
create_le_capture_file_single_interface( PCAPNG_HANDLE * handle,
const char * filename,
const option_header * interface_options )
{
PCAPNG_RESULT retval = PCAPNG_OK;
retval = pcapng_create( handle,
filename,
(const option_header *) &libbtbb_section_options,
(size_t) getpagesize( ),
DLT_BLUETOOTH_LE_LL_WITH_PHDR,
64,
interface_options,
(size_t) getpagesize( ) );
if (retval == PCAPNG_OK) {
/* if there is no timestamp resolution alread in the
interface options, record nanosecond resolution */
retval = check_and_fix_tsresol( handle, interface_options );
if (retval != PCAPNG_OK) {
(void) pcapng_close( handle );
}
}
return retval;
}
int
lell_pcapng_create_file(const char *filename, const char *interface_desc,
lell_pcapng_handle ** ph)
{
int retval = PCAPNG_OK;
PCAPNG_HANDLE * handle = malloc( sizeof(PCAPNG_HANDLE) );
if (handle) {
const option_header * popt = NULL;
struct {
option_header header;
char desc[256];
} ifopt = {
.header = {
.option_code = IF_DESCRIPTION,
}
};
if (interface_desc) {
(void) strncpy( &ifopt.desc[0], interface_desc, 256 );
ifopt.desc[255] = '\0';
ifopt.header.option_length = strlen( ifopt.desc );
popt = (const option_header *) &ifopt;
}
retval = -create_le_capture_file_single_interface( handle,
filename,
popt );
if (retval == PCAPNG_OK) {
*ph = (lell_pcapng_handle *) handle;
}
else {
free( handle );
}
}
else {
retval = -PCAPNG_NO_MEMORY;
}
return retval;
}
static PCAPNG_RESULT
append_le_packet( PCAPNG_HANDLE * handle,
pcapng_le_packet * pkt )
{
return pcapng_append_packet( handle, ( const enhanced_packet_block *) pkt );
}
/* Size of a PCAPNG enhanced packet block with no packet data.
NOTE: The pcap_bluetooth_le_ll_header is part of the packet data of
the enhanced block. */
#define PCAPNG_ENHANCED_BLK_SZ 36
static void
assemble_pcapng_le_packet( pcapng_le_packet * pkt,
const uint32_t interface_id,
const uint64_t ns,
const uint32_t caplen,
const uint8_t rf_channel,
const int8_t signal_power,
const int8_t noise_power,
const uint8_t access_address_offenses,
const uint32_t ref_access_address,
const uint16_t flags,
const uint8_t * lepkt )
{
uint32_t pcapng_caplen = sizeof(pcap_bluetooth_le_ll_header)+caplen;
uint32_t block_length = 4*((PCAPNG_ENHANCED_BLK_SZ+pcapng_caplen+3)/4);
assert(caplen <= LE_MAX_PAYLOAD);
pkt->blk_header.block_type = BLOCK_TYPE_ENHANCED_PACKET;
pkt->blk_header.block_total_length = block_length;
pkt->blk_header.interface_id = interface_id;
pkt->blk_header.timestamp_high = (uint32_t) (ns >> 32);
pkt->blk_header.timestamp_low = (uint32_t) (ns & 0x0ffffffffull);
pkt->blk_header.captured_len = pcapng_caplen;
pkt->blk_header.packet_len = pcapng_caplen;
pkt->le_ll_header.rf_channel = rf_channel;
pkt->le_ll_header.signal_power = signal_power;
pkt->le_ll_header.noise_power = noise_power;
pkt->le_ll_header.access_address_offenses = access_address_offenses;
pkt->le_ll_header.ref_access_address = htole32( ref_access_address );
pkt->le_ll_header.flags = htole16( flags );
(void) memcpy( &pkt->le_packet[0], lepkt, caplen );
((uint32_t *)pkt)[block_length/4-2] = 0x00000000; /* no-options */
((uint32_t *)pkt)[block_length/4-1] = block_length;
}
int
lell_pcapng_append_packet(lell_pcapng_handle * h, const uint64_t ns,
const int8_t sigdbm, const int8_t noisedbm,
const uint32_t refAA, const lell_packet *pkt)
{
uint16_t flags = LE_DEWHITENED | LE_AA_OFFENSES_VALID |
LE_SIGPOWER_VALID |
((noisedbm < sigdbm) ? LE_NOISEPOWER_VALID : 0) |
(lell_packet_is_data(pkt) ? 0 : LE_REF_AA_VALID);
pcapng_le_packet pcapng_pkt;
/* The extra 9 bytes added to the packet length are for:
4 bytes for Access Address
2 bytes for PDU header
3 bytes for CRC */
assemble_pcapng_le_packet( &pcapng_pkt,
0,
ns,
9+pkt->length,
pkt->channel_k,
sigdbm,
noisedbm,
pkt->access_address_offenses,
refAA,
flags,
&pkt->symbols[0] );
int retval = -append_le_packet( (PCAPNG_HANDLE *) h, &pcapng_pkt );
if ((retval == 0) && !lell_packet_is_data(pkt) && (pkt->adv_type == CONNECT_REQ)) {
(void) lell_pcapng_record_connect_req(h, ns, &pkt->symbols[0]);
}
return retval;
}
static PCAPNG_RESULT
record_le_connect_req_info( PCAPNG_HANDLE * handle,
const uint64_t ns,
const uint8_t * pdu )
{
le_ll_connection_info_option cropt = {
.header = {
.option_code = PCAPNG_LE_LL_CONNECTION_INFO,
.option_length = sizeof(le_ll_connection_info_option)
},
.connection_info = {
.ns = ns
}
};
(void) memcpy( &cropt.connection_info.pdu.bytes[0], pdu, 34 );
return pcapng_append_interface_option( handle,
(const option_header *) &cropt );
}
int
lell_pcapng_record_connect_req(lell_pcapng_handle * h, const uint64_t ns,
const uint8_t * pdu)
{
return -record_le_connect_req_info( (PCAPNG_HANDLE *) h, ns, pdu );
}
int lell_pcapng_close(lell_pcapng_handle *h)
{
pcapng_close( (PCAPNG_HANDLE *) h );
if (h) {
free( h );
}
return -PCAPNG_INVALID_HANDLE;
}

View File

@ -0,0 +1,120 @@
/* -*- c -*- */
/*
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef PCAPNG_BT_DOT_H
#define PCAPNG_BT_DOT_H
#include "pcap-common.h"
#include "pcapng.h"
typedef struct __attribute__((packed)) {
uint32_t centre_freq;
uint32_t analog_bandwidth;
int32_t intermediate_freq;
uint32_t sampling_bandwidth;
} bt_wideband_rf_info;
typedef struct __attribute__((packed)) {
option_header header;
bt_wideband_rf_info wideband_rf_info;
} bt_wideband_rf_option;
#define PCAPNG_BT_WIDEBAND_RF_INFO 0xd300
/* --------------------------------- BR/EDR ----------------------------- */
typedef struct __attribute__((packed)) {
enhanced_packet_block blk_header;
pcap_bluetooth_bredr_bb_header bredr_bb_header;
uint8_t bredr_payload[BREDR_MAX_PAYLOAD];
} pcapng_bredr_packet;
typedef struct __attribute__((packed)) {
uint8_t bd_addr[6];
uint8_t uap_mask;
uint8_t nap_valid;
} bredr_bd_addr_info;
typedef struct __attribute__((packed)) {
option_header header;
bredr_bd_addr_info bd_addr_info;
} bredr_br_addr_option;
typedef struct __attribute__((packed)) {
uint64_t ts;
uint32_t lap_uap;
uint32_t clk;
uint32_t clk_mask;
} bredr_clk_info;
typedef struct __attribute__((packed)) {
option_header header;
bredr_clk_info clock_info;
} bredr_clk_option;
#define PCAPNG_BREDR_OPTION_BD_ADDR 0xd340
#define PCAPNG_BREDR_OPTION_MASTER_CLOCK_INFO 0xd341
/* --------------------------------- Low Energy ---------------------------- */
typedef struct __attribute__((packed)) {
enhanced_packet_block blk_header;
pcap_bluetooth_le_ll_header le_ll_header;
uint8_t le_packet[LE_MAX_PAYLOAD];
/* Force 32 bit alignment for options and blk_tot_length. */
uint8_t pad[2];
/* Add space for OPTIONS and BLOCK_TOTAL_LENGTH at end of
block. These won't be at this position in the structure unless
the LE PDU is the full 39 bytes. */
uint32_t options;
uint32_t blk_tot_length;
} pcapng_le_packet;
typedef struct __attribute__((packed)) {
uint64_t ns;
union {
struct {
uint8_t InitA[6];
uint8_t AdvA[6];
uint8_t AA[4];
uint8_t CRCInit[3];
uint8_t WinSize;
uint8_t WinOffset[2];
uint8_t Interval[2];
uint8_t Latency[2];
uint8_t Timeout[2];
uint8_t ChM[5];
uint8_t HopSCA;
} fields;
uint8_t bytes[0];
} pdu;
} le_ll_connection_info;
typedef struct __attribute__((packed)) {
option_header header;
le_ll_connection_info connection_info;
} le_ll_connection_info_option;
#define PCAPNG_LE_LL_CONNECTION_INFO 0xd380
#endif /* PCAPNG_BT_DOT_H */

View File

@ -0,0 +1,323 @@
/* -*- c -*- */
/*
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "pcapng.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static option_header padopt = {
.option_code = 0xffff,
};
PCAPNG_RESULT pcapng_create( PCAPNG_HANDLE * handle,
const char * filename,
const option_header * section_options,
const size_t section_options_space,
const uint16_t link_type,
const uint32_t snaplen,
const option_header * interface_options,
const size_t interface_options_space )
{
PCAPNG_RESULT retval = PCAPNG_OK;
int PGSZ = getpagesize( );
size_t zeroes = 0;
ssize_t result = -1;
handle->section_header = NULL;
handle->interface_description = NULL;
handle->section_header_size = handle->next_section_option_offset =
handle->interface_description_size =
handle->next_interface_option_offset = 0;
handle->fd = open( filename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP );
if (handle->fd == -1) {
switch( errno ) {
case EEXIST:
retval = PCAPNG_FILE_EXISTS;
break;
case EMFILE:
case ENFILE:
retval = PCAPNG_TOO_MANY_FILES_OPEN;
break;
case ENOMEM:
case ENOSPC:
retval = PCAPNG_NO_MEMORY;
break;
default:
retval = PCAPNG_FILE_NOT_ALLOWED;
}
}
if (retval == PCAPNG_OK) {
/* section header */
const section_header_block shb = {
.block_type = BLOCK_TYPE_SECTION_HEADER,
.block_total_length = 28,
.byte_order_magic = SECTION_HEADER_BYTE_ORDER_MAGIC,
.major_version = 1,
.minor_version = 0,
.section_length = (uint64_t) -1,
};
handle->section_header_size = sizeof( shb );
result = write( handle->fd, &shb, sizeof( shb ) );
/* write initial section options */
while ((result != -1) &&
section_options &&
section_options->option_code &&
section_options->option_length) {
size_t paddedsz = 4*((section_options->option_length+3)/4);
zeroes = paddedsz - section_options->option_length;
result = write( handle->fd, section_options, 4+section_options->option_length );
while ((zeroes > 0) && (result != -1)) {
result = write( handle->fd, "\0", 1 );
zeroes--;
}
section_options = (const option_header *) &((uint8_t *)section_options)[4+paddedsz];
handle->section_header_size += (4+paddedsz);
}
handle->next_section_option_offset = handle->section_header_size;
}
if (result == -1) {
retval = PCAPNG_FILE_WRITE_ERROR;
}
else {
/* determine the size of section header with desired space */
zeroes = (size_t) PGSZ*((handle->section_header_size + 4 +
section_options_space + PGSZ - 1)/PGSZ) -
handle->section_header_size;
handle->section_header_size += zeroes;
while ((zeroes > 0) && (result != -1)) {
result = write( handle->fd, "\0", 1 );
zeroes--;
}
/* mmap the section header */
handle->section_header = mmap( NULL, handle->section_header_size,
PROT_READ|PROT_WRITE,
MAP_SHARED,
handle->fd, 0 );
}
if (retval == PCAPNG_OK) {
if (result == -1) {
retval = PCAPNG_FILE_WRITE_ERROR;
}
else if (handle->section_header == MAP_FAILED) {
retval = PCAPNG_MMAP_FAILED;
}
else {
/* write the interface header */
const interface_description_block idb = {
.block_type = BLOCK_TYPE_INTERFACE,
.block_total_length = 0,
.link_type = link_type,
.snaplen = snaplen
};
handle->interface_description_size = sizeof( idb );
result = write( handle->fd, &idb, sizeof( idb ) );
/* write interface options */
while ((result != -1) &&
interface_options &&
interface_options->option_code &&
interface_options->option_length) {
size_t paddedsz = 4*((interface_options->option_length+3)/4);
zeroes = paddedsz - interface_options->option_length;
result = write( handle->fd, interface_options, 4+interface_options->option_length );
while ((zeroes > 0) && (result != -1)) {
result = write( handle->fd, "\0", 1 );
zeroes--;
}
interface_options = (const option_header *) &((uint8_t *)interface_options)[4+paddedsz];
handle->interface_description_size += (4+paddedsz);
}
handle->next_interface_option_offset = handle->interface_description_size;
}
}
if (retval == PCAPNG_OK) {
if (result == -1) {
retval = PCAPNG_FILE_WRITE_ERROR;
}
else {
/* determine the size of interface description with desired space */
zeroes = (size_t) PGSZ*((handle->interface_description_size + 4 +
interface_options_space + PGSZ - 1)/PGSZ) -
handle->interface_description_size;
handle->interface_description_size += zeroes;
while ((zeroes > 0) && (result != -1)) {
result = write( handle->fd, "\0", 1 );
zeroes--;
}
/* mmap the interface description */
handle->interface_description = mmap( NULL, handle->interface_description_size,
PROT_READ|PROT_WRITE,
MAP_SHARED,
handle->fd,
handle->section_header_size );
}
}
if (retval == PCAPNG_OK) {
if (result == -1) {
retval = PCAPNG_FILE_WRITE_ERROR;
}
else if (handle->interface_description == MAP_FAILED) {
retval = PCAPNG_MMAP_FAILED;
}
else {
uint8_t * dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
padopt.option_length = handle->section_header_size -
handle->next_section_option_offset - 12;
/* Add padding options, update the header sizes. */
(void) memcpy( dest, &padopt, sizeof( padopt ) );
handle->section_header->block_total_length =
(uint32_t) handle->section_header_size;
((uint32_t*)handle->section_header)[handle->section_header_size/4-1] =
(uint32_t) handle->section_header_size;
padopt.option_length = handle->interface_description_size -
handle->next_interface_option_offset - 12;
dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
(void) memcpy( dest, &padopt, sizeof( padopt ) );
handle->interface_description->block_total_length =
(uint32_t) handle->interface_description_size;
((uint32_t*)handle->interface_description)[handle->interface_description_size/4-1] =
(uint32_t) handle->interface_description_size;
handle->section_header->section_length = (uint64_t) handle->interface_description_size;
}
}
if (retval != PCAPNG_OK) {
(void) pcapng_close( handle );
}
return retval;
}
PCAPNG_RESULT pcapng_append_section_option( PCAPNG_HANDLE * handle,
const option_header * section_option )
{
PCAPNG_RESULT retval = PCAPNG_OK;
if (handle && (handle->fd != -1)) {
if (handle->section_header &&
(handle->section_header != MAP_FAILED) &&
handle->next_section_option_offset &&
section_option) {
size_t copysz = 4+section_option->option_length;
uint8_t * dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
(void) memcpy( dest, section_option, copysz );
handle->next_section_option_offset += 4*((copysz+3)/4);
/* update padding option */
dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
padopt.option_length = handle->section_header_size -
handle->next_section_option_offset - 12;
(void) memcpy( dest, &padopt, sizeof( padopt ) );
}
else {
retval = PCAPNG_NO_MEMORY;
}
}
else {
retval = PCAPNG_INVALID_HANDLE;
}
return retval;
}
PCAPNG_RESULT pcapng_append_interface_option( PCAPNG_HANDLE * handle,
const option_header * interface_option )
{
PCAPNG_RESULT retval = PCAPNG_OK;
if (handle && (handle->fd != -1)) {
if (handle->interface_description &&
(handle->interface_description != MAP_FAILED) &&
handle->next_interface_option_offset &&
interface_option) {
size_t copysz = 4+interface_option->option_length;
uint8_t * dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
(void) memcpy( dest, interface_option, copysz );
handle->next_interface_option_offset += 4*((copysz+3)/4);
/* update padding option */
dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
padopt.option_length = handle->interface_description_size -
handle->next_interface_option_offset - 12;
(void) memcpy( dest, &padopt, sizeof( padopt ) );
}
else {
retval = PCAPNG_NO_MEMORY;
}
}
else {
retval = PCAPNG_INVALID_HANDLE;
}
return retval;
}
PCAPNG_RESULT pcapng_append_packet( PCAPNG_HANDLE * handle,
const enhanced_packet_block * packet )
{
PCAPNG_RESULT retval = PCAPNG_OK;
if (handle && (handle->fd != -1)) {
size_t writesz = packet->block_total_length;
ssize_t result = write( handle->fd, packet, writesz );
if (result == -1) {
result = PCAPNG_FILE_WRITE_ERROR;
}
else {
handle->section_header->section_length += writesz;
}
}
else {
retval = PCAPNG_INVALID_HANDLE;
}
return retval;
}
PCAPNG_RESULT pcapng_close( PCAPNG_HANDLE * handle )
{
if (handle->interface_description &&
(handle->interface_description != MAP_FAILED)) {
(void) munmap( handle->interface_description,
handle->interface_description_size );
}
if (handle->section_header &&
(handle->section_header != MAP_FAILED)) {
(void) munmap( handle->section_header,
handle->section_header_size );
}
if (handle->fd != -1) {
(void) close( handle->fd );
}
return PCAPNG_OK;
}

View File

@ -0,0 +1,198 @@
/* -*- c -*- */
/*
* Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef PCAPNG_DOT_H
#define PCAPNG_DOT_H
#include <stdint.h>
#include <stdio.h>
typedef struct __attribute__((packed)) {
uint16_t option_code;
uint16_t option_length;
uint32_t option_value[0];
} option_header;
#define OPT_ENDOFOPT 0
#define OPT_COMMENT 1
typedef struct __attribute__((packed)) {
uint32_t block_type;
uint32_t block_total_length;
uint32_t byte_order_magic;
uint16_t major_version;
uint16_t minor_version;
uint64_t section_length;
option_header options[0];
} section_header_block;
#define SECTION_HEADER_BYTE_ORDER_MAGIC 0x1a2b3c4d
#define SHB_HARDWARE 2
#define SHB_OS 3
#define SHB_USERAPPL 4
typedef struct __attribute__((packed)) {
uint32_t block_type;
uint32_t block_total_length;
uint16_t link_type;
uint16_t reserved;
uint32_t snaplen;
option_header options[0];
} interface_description_block;
#define IF_NAME 2
#define IF_DESCRIPTION 3
#define IF_IPV4ADDR 4
#define IF_IPV6ADDR 5
#define IF_MACADDR 6
#define IF_EUIADDR 7
#define IF_SPEED 8
#define IF_TSRESOL 9
#define IF_TZONE 10
#define IF_FILTER 11
#define IF_OS 12
#define IF_FCSLEN 13
#define IF_TSOFFSET 14
typedef struct __attribute__((packed)) {
uint32_t block_type;
uint32_t block_total_length;
uint32_t interface_id;
uint32_t timestamp_high;
uint32_t timestamp_low;
uint32_t captured_len;
uint32_t packet_len;
uint32_t packet_data[0];
} enhanced_packet_block;
#define EPB_FLAGS 2
#define EPB_HASH 3
#define EPB_DROPCOUNT 4
typedef struct __attribute__((packed)) {
uint32_t block_type;
uint32_t block_total_length;
uint32_t packet_len;
uint32_t packet_data[0];
} simple_packet_block;
typedef struct __attribute__((packed)) {
uint32_t block_type;
uint32_t block_total_length;
uint16_t record_type;
uint16_t record_length;
uint32_t record_value[0];
} name_resolution_block;
#define NRES_ENDOFRECORD 0
#define NRES_IP4RECORD 1
#define NRES_IP6RECORD 2
#define NS_DNSNAME 2
#define NS_DNSIP4ADDR 3
#define NS_DNSIP6ADDR 4
typedef struct __attribute__((packed)) {
uint32_t block_type;
uint32_t block_total_length;
uint32_t interface_id;
uint32_t timestamp_high;
uint32_t timestamp_low;
option_header options[0];
} interface_statistics_block;
#define ISB_STARTTIME 2
#define ISB_ENDTIME 3
#define ISB_IFRECV 4
#define ISB_IFDROP 5
#define ISB_FILTERACCEPT 6
#define ISB_OSDROP 7
#define ISB_USRDELIV 8
#define BLOCK_TYPE_INTERFACE 0x00000001
#define BLOCK_TYPE_SIMPLE_PACKET 0x00000003
#define BLOCK_TYPE_NAME_RESOLUTION 0x00000004
#define BLOCK_TYPE_INTERFACE_STATISTICS 0x00000005
#define BLOCK_TYPE_ENHANCED_PACKET 0x00000006
#define BLOCK_TYPE_SECTION_HEADER 0x0a0d0d0a
typedef struct {
int fd;
section_header_block * section_header;
size_t section_header_size;
size_t next_section_option_offset;
interface_description_block * interface_description;
size_t interface_description_size;
size_t next_interface_option_offset;
} PCAPNG_HANDLE;
typedef enum {
PCAPNG_OK = 0,
PCAPNG_INVALID_HANDLE,
PCAPNG_FILE_NOT_ALLOWED,
PCAPNG_FILE_EXISTS,
PCAPNG_TOO_MANY_FILES_OPEN,
PCAPNG_NO_MEMORY,
PCAPNG_FILE_WRITE_ERROR,
PCAPNG_MMAP_FAILED,
} PCAPNG_RESULT;
/**
* Create a new PCAP-NG file and set aside space in the section and
* interface headers for options to be recorded/added while packets
* are captured.
*
* @param handle pointer to a handle that is populated by this call
* @param filename file to create
* @param section_options list of initial section options, can be NULL
* @param section_options_space size in bytes dedicated to storing extra section
* options; will be rounded up so section header
* is an integer number of memory pages
* @param link_type
* @param snaplen
* @param interface_options list of initial interface options, can be NULL
* @param interface_options_space size in bytes dedicated to storing extra interface
* options; will be rounded up so interface header
* is an integer number of memory pages
* @returns 0 on success, non zero result code otherwisex
*/
PCAPNG_RESULT pcapng_create( PCAPNG_HANDLE * handle,
const char * filename,
const option_header * section_options,
const size_t section_options_space,
const uint16_t link_type,
const uint32_t snaplen,
const option_header * interface_options,
const size_t interface_options_space );
PCAPNG_RESULT pcapng_append_section_option( PCAPNG_HANDLE * handle,
const option_header * section_option );
PCAPNG_RESULT pcapng_append_interface_option( PCAPNG_HANDLE * handle,
const option_header * interface_option );
PCAPNG_RESULT pcapng_append_packet( PCAPNG_HANDLE * handle,
const enhanced_packet_block * packet );
PCAPNG_RESULT pcapng_close( PCAPNG_HANDLE * handle );
#endif /* PCAPNG_DOT_H */

View File

@ -0,0 +1,4 @@
static const uint64_t sw_check_table4[] = {0x000000000ULL, 0x100000000ULL, 0x200000000ULL, 0x300000000ULL, 0x185713da9ULL, 0x085713da9ULL, 0x385713da9ULL, 0x285713da9ULL, 0x30ae27b52ULL, 0x20ae27b52ULL, 0x10ae27b52ULL, 0x00ae27b52ULL, 0x28f9346fbULL, 0x38f9346fbULL, 0x08f9346fbULL, 0x18f9346fbULL, 0x390b5cb0dULL, 0x290b5cb0dULL, 0x190b5cb0dULL, 0x090b5cb0dULL, 0x215c4f6a4ULL, 0x315c4f6a4ULL, 0x015c4f6a4ULL, 0x115c4f6a4ULL, 0x09a57b05fULL, 0x19a57b05fULL, 0x29a57b05fULL, 0x39a57b05fULL, 0x11f268df6ULL, 0x01f268df6ULL, 0x31f268df6ULL, 0x21f268df6ULL, 0x2a41aabb3ULL, 0x3a41aabb3ULL, 0x0a41aabb3ULL, 0x1a41aabb3ULL, 0x3216b961aULL, 0x2216b961aULL, 0x1216b961aULL, 0x0216b961aULL, 0x1aef8d0e1ULL, 0x0aef8d0e1ULL, 0x3aef8d0e1ULL, 0x2aef8d0e1ULL, 0x02b89ed48ULL, 0x12b89ed48ULL, 0x22b89ed48ULL, 0x32b89ed48ULL, 0x134af60beULL, 0x034af60beULL, 0x334af60beULL, 0x234af60beULL, 0x0b1de5d17ULL, 0x1b1de5d17ULL, 0x2b1de5d17ULL, 0x3b1de5d17ULL, 0x23e4d1becULL, 0x33e4d1becULL, 0x03e4d1becULL, 0x13e4d1becULL, 0x3bb3c2645ULL, 0x2bb3c2645ULL, 0x1bb3c2645ULL, 0x0bb3c2645ULL, 0x0cd446acfULL, 0x1cd446acfULL, 0x2cd446acfULL, 0x3cd446acfULL, 0x148355766ULL, 0x048355766ULL, 0x348355766ULL, 0x248355766ULL, 0x3c7a6119dULL, 0x2c7a6119dULL, 0x1c7a6119dULL, 0x0c7a6119dULL, 0x242d72c34ULL, 0x342d72c34ULL, 0x042d72c34ULL, 0x142d72c34ULL, 0x35df1a1c2ULL, 0x25df1a1c2ULL, 0x15df1a1c2ULL, 0x05df1a1c2ULL, 0x2d8809c6bULL, 0x3d8809c6bULL, 0x0d8809c6bULL, 0x1d8809c6bULL, 0x05713da90ULL, 0x15713da90ULL, 0x25713da90ULL, 0x35713da90ULL, 0x1d262e739ULL, 0x0d262e739ULL, 0x3d262e739ULL, 0x2d262e739ULL, 0x2695ec17cULL, 0x3695ec17cULL, 0x0695ec17cULL, 0x1695ec17cULL, 0x3ec2ffcd5ULL, 0x2ec2ffcd5ULL, 0x1ec2ffcd5ULL, 0x0ec2ffcd5ULL, 0x163bcba2eULL, 0x063bcba2eULL, 0x363bcba2eULL, 0x263bcba2eULL, 0x0e6cd8787ULL, 0x1e6cd8787ULL, 0x2e6cd8787ULL, 0x3e6cd8787ULL, 0x1f9eb0a71ULL, 0x0f9eb0a71ULL, 0x3f9eb0a71ULL, 0x2f9eb0a71ULL, 0x07c9a37d8ULL, 0x17c9a37d8ULL, 0x27c9a37d8ULL, 0x37c9a37d8ULL, 0x2f3097123ULL, 0x3f3097123ULL, 0x0f3097123ULL, 0x1f3097123ULL, 0x376784c8aULL, 0x276784c8aULL, 0x176784c8aULL, 0x076784c8aULL, 0x19a88d59eULL, 0x09a88d59eULL, 0x39a88d59eULL, 0x29a88d59eULL, 0x01ff9e837ULL, 0x11ff9e837ULL, 0x21ff9e837ULL, 0x31ff9e837ULL, 0x2906aaeccULL, 0x3906aaeccULL, 0x0906aaeccULL, 0x1906aaeccULL, 0x3151b9365ULL, 0x2151b9365ULL, 0x1151b9365ULL, 0x0151b9365ULL, 0x20a3d1e93ULL, 0x30a3d1e93ULL, 0x00a3d1e93ULL, 0x10a3d1e93ULL, 0x38f4c233aULL, 0x28f4c233aULL, 0x18f4c233aULL, 0x08f4c233aULL, 0x100df65c1ULL, 0x000df65c1ULL, 0x300df65c1ULL, 0x200df65c1ULL, 0x085ae5868ULL, 0x185ae5868ULL, 0x285ae5868ULL, 0x385ae5868ULL, 0x33e927e2dULL, 0x23e927e2dULL, 0x13e927e2dULL, 0x03e927e2dULL, 0x2bbe34384ULL, 0x3bbe34384ULL, 0x0bbe34384ULL, 0x1bbe34384ULL, 0x03470057fULL, 0x13470057fULL, 0x23470057fULL, 0x33470057fULL, 0x1b10138d6ULL, 0x0b10138d6ULL, 0x3b10138d6ULL, 0x2b10138d6ULL, 0x0ae27b520ULL, 0x1ae27b520ULL, 0x2ae27b520ULL, 0x3ae27b520ULL, 0x12b568889ULL, 0x02b568889ULL, 0x32b568889ULL, 0x22b568889ULL, 0x3a4c5ce72ULL, 0x2a4c5ce72ULL, 0x1a4c5ce72ULL, 0x0a4c5ce72ULL, 0x221b4f3dbULL, 0x321b4f3dbULL, 0x021b4f3dbULL, 0x121b4f3dbULL, 0x157ccbf51ULL, 0x057ccbf51ULL, 0x357ccbf51ULL, 0x257ccbf51ULL, 0x0d2bd82f8ULL, 0x1d2bd82f8ULL, 0x2d2bd82f8ULL, 0x3d2bd82f8ULL, 0x25d2ec403ULL, 0x35d2ec403ULL, 0x05d2ec403ULL, 0x15d2ec403ULL, 0x3d85ff9aaULL, 0x2d85ff9aaULL, 0x1d85ff9aaULL, 0x0d85ff9aaULL, 0x2c779745cULL, 0x3c779745cULL, 0x0c779745cULL, 0x1c779745cULL, 0x3420849f5ULL, 0x2420849f5ULL, 0x1420849f5ULL, 0x0420849f5ULL, 0x1cd9b0f0eULL, 0x0cd9b0f0eULL, 0x3cd9b0f0eULL, 0x2cd9b0f0eULL, 0x048ea32a7ULL, 0x148ea32a7ULL, 0x248ea32a7ULL, 0x348ea32a7ULL, 0x3f3d614e2ULL, 0x2f3d614e2ULL, 0x1f3d614e2ULL, 0x0f3d614e2ULL, 0x276a7294bULL, 0x376a7294bULL, 0x076a7294bULL, 0x176a7294bULL, 0x0f9346fb0ULL, 0x1f9346fb0ULL, 0x2f9346fb0ULL, 0x3f9346fb0ULL, 0x17c455219ULL, 0x07c455219ULL, 0x37c455219ULL, 0x27c455219ULL, 0x06363dfefULL, 0x16363dfefULL, 0x26363dfefULL, 0x36363dfefULL, 0x1e612e246ULL, 0x0e612e246ULL, 0x3e612e246ULL, 0x2e612e246ULL, 0x36981a4bdULL, 0x26981a4bdULL, 0x16981a4bdULL, 0x06981a4bdULL, 0x2ecf09914ULL, 0x3ecf09914ULL, 0x0ecf09914ULL, 0x1ecf09914ULL};
static const uint64_t sw_check_table5[] = {0x000000000ULL, 0x33511ab3cULL, 0x3ef526bd1ULL, 0x0da43c0edULL, 0x25bd5ea0bULL, 0x16ec44137ULL, 0x1b48781daULL, 0x281962ae6ULL, 0x132dae9bfULL, 0x207cb4283ULL, 0x2dd88826eULL, 0x1e8992952ULL, 0x3690f03b4ULL, 0x05c1ea888ULL, 0x0865d6865ULL, 0x3b34cc359ULL, 0x265b5d37eULL, 0x150a47842ULL, 0x18ae7b8afULL, 0x2bff61393ULL, 0x03e603975ULL, 0x30b719249ULL, 0x3d13252a4ULL, 0x0e423f998ULL, 0x3576f3ac1ULL, 0x0627e91fdULL, 0x0b83d5110ULL, 0x38d2cfa2cULL, 0x10cbad0caULL, 0x239ab7bf6ULL, 0x2e3e8bb1bULL, 0x1d6f91027ULL, 0x14e1a9b55ULL, 0x27b0b3069ULL, 0x2a148f084ULL, 0x194595bb8ULL, 0x315cf715eULL, 0x020deda62ULL, 0x0fa9d1a8fULL, 0x3cf8cb1b3ULL, 0x07cc072eaULL, 0x349d1d9d6ULL, 0x39392193bULL, 0x0a683b207ULL, 0x2271598e1ULL, 0x1120433ddULL, 0x1c847f330ULL, 0x2fd56580cULL, 0x32baf482bULL, 0x01ebee317ULL, 0x0c4fd23faULL, 0x3f1ec88c6ULL, 0x1707aa220ULL, 0x2456b091cULL, 0x29f28c9f1ULL, 0x1aa3962cdULL, 0x21975a194ULL, 0x12c640aa8ULL, 0x1f627ca45ULL, 0x2c3366179ULL, 0x042a04b9fULL, 0x377b1e0a3ULL, 0x3adf2204eULL, 0x098e38b72ULL, 0x29c3536aaULL, 0x1a9249d96ULL, 0x173675d7bULL, 0x24676f647ULL, 0x0c7e0dca1ULL, 0x3f2f1779dULL, 0x328b2b770ULL, 0x01da31c4cULL, 0x3aeefdf15ULL, 0x09bfe7429ULL, 0x041bdb4c4ULL, 0x374ac1ff8ULL, 0x1f53a351eULL, 0x2c02b9e22ULL, 0x21a685ecfULL, 0x12f79f5f3ULL, 0x0f980e5d4ULL, 0x3cc914ee8ULL, 0x316d28e05ULL, 0x023c32539ULL, 0x2a2550fdfULL, 0x19744a4e3ULL, 0x14d07640eULL, 0x27816cf32ULL, 0x1cb5a0c6bULL, 0x2fe4ba757ULL, 0x2240867baULL, 0x11119cc86ULL, 0x3908fe660ULL, 0x0a59e4d5cULL, 0x07fdd8db1ULL, 0x34acc268dULL, 0x3d22fadffULL, 0x0e73e06c3ULL, 0x03d7dc62eULL, 0x3086c6d12ULL, 0x189fa47f4ULL, 0x2bcebecc8ULL, 0x266a82c25ULL, 0x153b98719ULL, 0x2e0f54440ULL, 0x1d5e4ef7cULL, 0x10fa72f91ULL, 0x23ab684adULL, 0x0bb20ae4bULL, 0x38e310577ULL, 0x35472c59aULL, 0x061636ea6ULL, 0x1b79a7e81ULL, 0x2828bd5bdULL, 0x258c81550ULL, 0x16dd9be6cULL, 0x3ec4f948aULL, 0x0d95e3fb6ULL, 0x0031dff5bULL, 0x3360c5467ULL, 0x08540973eULL, 0x3b0513c02ULL, 0x36a12fcefULL, 0x05f0357d3ULL, 0x2de957d35ULL, 0x1eb84d609ULL, 0x131c716e4ULL, 0x204d6bdd8ULL, 0x0bd1b50fdULL, 0x3880afbc1ULL, 0x352493b2cULL, 0x067589010ULL, 0x2e6cebaf6ULL, 0x1d3df11caULL, 0x1099cd127ULL, 0x23c8d7a1bULL, 0x18fc1b942ULL, 0x2bad0127eULL, 0x26093d293ULL, 0x1558279afULL, 0x3d4145349ULL, 0x0e105f875ULL, 0x03b463898ULL, 0x30e5793a4ULL, 0x2d8ae8383ULL, 0x1edbf28bfULL, 0x137fce852ULL, 0x202ed436eULL, 0x0837b6988ULL, 0x3b66ac2b4ULL, 0x36c290259ULL, 0x05938a965ULL, 0x3ea746a3cULL, 0x0df65c100ULL, 0x0052601edULL, 0x33037aad1ULL, 0x1b1a18037ULL, 0x284b02b0bULL, 0x25ef3ebe6ULL, 0x16be240daULL, 0x1f301cba8ULL, 0x2c6106094ULL, 0x21c53a079ULL, 0x129420b45ULL, 0x3a8d421a3ULL, 0x09dc58a9fULL, 0x047864a72ULL, 0x37297e14eULL, 0x0c1db2217ULL, 0x3f4ca892bULL, 0x32e8949c6ULL, 0x01b98e2faULL, 0x29a0ec81cULL, 0x1af1f6320ULL, 0x1755ca3cdULL, 0x2404d08f1ULL, 0x396b418d6ULL, 0x0a3a5b3eaULL, 0x079e67307ULL, 0x34cf7d83bULL, 0x1cd61f2ddULL, 0x2f87059e1ULL, 0x22233990cULL, 0x117223230ULL, 0x2a46ef169ULL, 0x1917f5a55ULL, 0x14b3c9ab8ULL, 0x27e2d3184ULL, 0x0ffbb1b62ULL, 0x3caaab05eULL, 0x310e970b3ULL, 0x025f8db8fULL, 0x2212e6657ULL, 0x1143fcd6bULL, 0x1ce7c0d86ULL, 0x2fb6da6baULL, 0x07afb8c5cULL, 0x34fea2760ULL, 0x395a9e78dULL, 0x0a0b84cb1ULL, 0x313f48fe8ULL, 0x026e524d4ULL, 0x0fca6e439ULL, 0x3c9b74f05ULL, 0x1482165e3ULL, 0x27d30cedfULL, 0x2a7730e32ULL, 0x19262a50eULL, 0x0449bb529ULL, 0x3718a1e15ULL, 0x3abc9def8ULL, 0x09ed875c4ULL, 0x21f4e5f22ULL, 0x12a5ff41eULL, 0x1f01c34f3ULL, 0x2c50d9fcfULL, 0x176415c96ULL, 0x24350f7aaULL, 0x299133747ULL, 0x1ac029c7bULL, 0x32d94b69dULL, 0x018851da1ULL, 0x0c2c6dd4cULL, 0x3f7d77670ULL, 0x36f34fd02ULL, 0x05a25563eULL, 0x0806696d3ULL, 0x3b5773defULL, 0x134e11709ULL, 0x201f0bc35ULL, 0x2dbb37cd8ULL, 0x1eea2d7e4ULL, 0x25dee14bdULL, 0x168ffbf81ULL, 0x1b2bc7f6cULL, 0x287add450ULL, 0x0063bfeb6ULL, 0x3332a558aULL, 0x3e9699567ULL, 0x0dc783e5bULL, 0x10a812e7cULL, 0x23f908540ULL, 0x2e5d345adULL, 0x1d0c2ee91ULL, 0x35154c477ULL, 0x064456f4bULL, 0x0be06afa6ULL, 0x38b17049aULL, 0x0385bc7c3ULL, 0x30d4a6cffULL, 0x3d709ac12ULL, 0x0e218072eULL, 0x2638e2dc8ULL, 0x1569f86f4ULL, 0x18cdc4619ULL, 0x2b9cded25ULL};
static const uint64_t sw_check_table6[] = {0x000000000ULL, 0x17a36a1faULL, 0x2f46d43f4ULL, 0x38e5be20eULL, 0x06dabba41ULL, 0x1179d1bbbULL, 0x299c6f9b5ULL, 0x3e3f0584fULL, 0x0db577482ULL, 0x1a161d578ULL, 0x22f3a3776ULL, 0x3550c968cULL, 0x0b6fccec3ULL, 0x1ccca6f39ULL, 0x242918d37ULL, 0x338a72ccdULL, 0x1b6aee904ULL, 0x0cc9848feULL, 0x342c3aaf0ULL, 0x238f50b0aULL, 0x1db055345ULL, 0x0a133f2bfULL, 0x32f6810b1ULL, 0x2555eb14bULL, 0x16df99d86ULL, 0x017cf3c7cULL, 0x39994de72ULL, 0x2e3a27f88ULL, 0x1005227c7ULL, 0x07a64863dULL, 0x3f43f6433ULL, 0x28e09c5c9ULL, 0x36d5dd208ULL, 0x2176b73f2ULL, 0x1993091fcULL, 0x0e3063006ULL, 0x300f66849ULL, 0x27ac0c9b3ULL, 0x1f49b2bbdULL, 0x08ead8a47ULL, 0x3b60aa68aULL, 0x2cc3c0770ULL, 0x14267e57eULL, 0x038514484ULL, 0x3dba11ccbULL, 0x2a197bd31ULL, 0x12fcc5f3fULL, 0x055fafec5ULL, 0x2dbf33b0cULL, 0x3a1c59af6ULL, 0x02f9e78f8ULL, 0x155a8d902ULL, 0x2b658814dULL, 0x3cc6e20b7ULL, 0x04235c2b9ULL, 0x138036343ULL, 0x200a44f8eULL, 0x37a92ee74ULL, 0x0f4c90c7aULL, 0x18effad80ULL, 0x26d0ff5cfULL, 0x317395435ULL, 0x09962b63bULL, 0x1e35417c1ULL, 0x35fca99b9ULL, 0x225fc3843ULL, 0x1aba7da4dULL, 0x0d1917bb7ULL, 0x3326123f8ULL, 0x248578202ULL, 0x1c60c600cULL, 0x0bc3ac1f6ULL, 0x3849ded3bULL, 0x2feab4cc1ULL, 0x170f0aecfULL, 0x00ac60f35ULL, 0x3e936577aULL, 0x29300f680ULL, 0x11d5b148eULL, 0x0676db574ULL, 0x2e96470bdULL, 0x39352d147ULL, 0x01d093349ULL, 0x1673f92b3ULL, 0x284cfcafcULL, 0x3fef96b06ULL, 0x070a28908ULL, 0x10a9428f2ULL, 0x23233043fULL, 0x34805a5c5ULL, 0x0c65e47cbULL, 0x1bc68e631ULL, 0x25f98be7eULL, 0x325ae1f84ULL, 0x0abf5fd8aULL, 0x1d1c35c70ULL, 0x032974bb1ULL, 0x148a1ea4bULL, 0x2c6fa0845ULL, 0x3bccca9bfULL, 0x05f3cf1f0ULL, 0x1250a500aULL, 0x2ab51b204ULL, 0x3d16713feULL, 0x0e9c03f33ULL, 0x193f69ec9ULL, 0x21dad7cc7ULL, 0x3679bdd3dULL, 0x0846b8572ULL, 0x1fe5d2488ULL, 0x27006c686ULL, 0x30a30677cULL, 0x18439a2b5ULL, 0x0fe0f034fULL, 0x37054e141ULL, 0x20a6240bbULL, 0x1e99218f4ULL, 0x093a4b90eULL, 0x31dff5b00ULL, 0x267c9fafaULL, 0x15f6ed637ULL, 0x0255877cdULL, 0x3ab0395c3ULL, 0x2d1353439ULL, 0x132c56c76ULL, 0x048f3cd8cULL, 0x3c6a82f82ULL, 0x2bc9e8e78ULL, 0x33ae40edbULL, 0x240d2af21ULL, 0x1ce894d2fULL, 0x0b4bfecd5ULL, 0x3574fb49aULL, 0x22d791560ULL, 0x1a322f76eULL, 0x0d9145694ULL, 0x3e1b37a59ULL, 0x29b85dba3ULL, 0x115de39adULL, 0x06fe89857ULL, 0x38c18c018ULL, 0x2f62e61e2ULL, 0x1787583ecULL, 0x002432216ULL, 0x28c4ae7dfULL, 0x3f67c4625ULL, 0x07827a42bULL, 0x1021105d1ULL, 0x2e1e15d9eULL, 0x39bd7fc64ULL, 0x0158c1e6aULL, 0x16fbabf90ULL, 0x2571d935dULL, 0x32d2b32a7ULL, 0x0a370d0a9ULL, 0x1d9467153ULL, 0x23ab6291cULL, 0x3408088e6ULL, 0x0cedb6ae8ULL, 0x1b4edcb12ULL, 0x057b9dcd3ULL, 0x12d8f7d29ULL, 0x2a3d49f27ULL, 0x3d9e23eddULL, 0x03a126692ULL, 0x14024c768ULL, 0x2ce7f2566ULL, 0x3b449849cULL, 0x08ceea851ULL, 0x1f6d809abULL, 0x27883eba5ULL, 0x302b54a5fULL, 0x0e1451210ULL, 0x19b73b3eaULL, 0x2152851e4ULL, 0x36f1ef01eULL, 0x1e11735d7ULL, 0x09b21942dULL, 0x3157a7623ULL, 0x26f4cd7d9ULL, 0x18cbc8f96ULL, 0x0f68a2e6cULL, 0x378d1cc62ULL, 0x202e76d98ULL, 0x13a404155ULL, 0x04076e0afULL, 0x3ce2d02a1ULL, 0x2b41ba35bULL, 0x157ebfb14ULL, 0x02ddd5aeeULL, 0x3a386b8e0ULL, 0x2d9b0191aULL, 0x0652e9762ULL, 0x11f183698ULL, 0x29143d496ULL, 0x3eb75756cULL, 0x008852d23ULL, 0x172b38cd9ULL, 0x2fce86ed7ULL, 0x386decf2dULL, 0x0be79e3e0ULL, 0x1c44f421aULL, 0x24a14a014ULL, 0x3302201eeULL, 0x0d3d259a1ULL, 0x1a9e4f85bULL, 0x227bf1a55ULL, 0x35d89bbafULL, 0x1d3807e66ULL, 0x0a9b6df9cULL, 0x327ed3d92ULL, 0x25ddb9c68ULL, 0x1be2bc427ULL, 0x0c41d65ddULL, 0x34a4687d3ULL, 0x230702629ULL, 0x108d70ae4ULL, 0x072e1ab1eULL, 0x3fcba4910ULL, 0x2868ce8eaULL, 0x1657cb0a5ULL, 0x01f4a115fULL, 0x39111f351ULL, 0x2eb2752abULL, 0x30873456aULL, 0x27245e490ULL, 0x1fc1e069eULL, 0x08628a764ULL, 0x365d8ff2bULL, 0x21fee5ed1ULL, 0x191b5bcdfULL, 0x0eb831d25ULL, 0x3d32431e8ULL, 0x2a9129012ULL, 0x12749721cULL, 0x05d7fd3e6ULL, 0x3be8f8ba9ULL, 0x2c4b92a53ULL, 0x14ae2c85dULL, 0x030d469a7ULL, 0x2beddac6eULL, 0x3c4eb0d94ULL, 0x04ab0ef9aULL, 0x130864e60ULL, 0x2d376162fULL, 0x3a940b7d5ULL, 0x0271b55dbULL, 0x15d2df421ULL, 0x2658ad8ecULL, 0x31fbc7916ULL, 0x091e79b18ULL, 0x1ebd13ae2ULL, 0x2082162adULL, 0x37217c357ULL, 0x0fc4c2159ULL, 0x1867a80a3ULL};
static const uint64_t sw_check_table7[] = {0x000000000ULL, 0x3f0b9201fULL, 0x264037d97ULL, 0x194ba5d88ULL, 0x14d77c687ULL, 0x2bdcee698ULL, 0x32974bb10ULL, 0x0d9cd9b0fULL, 0x29aef8d0eULL, 0x16a56ad11ULL, 0x0feecf099ULL, 0x30e55d086ULL, 0x3d7984b89ULL, 0x027216b96ULL, 0x1b39b361eULL, 0x243221601ULL, 0x0b0ae27b5ULL, 0x3401707aaULL, 0x2d4ad5a22ULL, 0x124147a3dULL, 0x1fdd9e132ULL, 0x20d60c12dULL, 0x399da9ca5ULL, 0x06963bcbaULL, 0x22a41aabbULL, 0x1daf88aa4ULL, 0x04e42d72cULL, 0x3befbf733ULL, 0x367366c3cULL, 0x0978f4c23ULL, 0x1033511abULL, 0x2f38c31b4ULL, 0x1615c4f6aULL, 0x291e56f75ULL, 0x3055f32fdULL, 0x0f5e612e2ULL, 0x02c2b89edULL, 0x3dc92a9f2ULL, 0x24828f47aULL, 0x1b891d465ULL, 0x3fbb3c264ULL, 0x00b0ae27bULL, 0x19fb0bff3ULL, 0x26f099fecULL, 0x2b6c404e3ULL, 0x1467d24fcULL, 0x0d2c77974ULL, 0x3227e596bULL, 0x1d1f268dfULL, 0x2214b48c0ULL, 0x3b5f11548ULL, 0x045483557ULL, 0x09c85ae58ULL, 0x36c3c8e47ULL, 0x2f886d3cfULL, 0x1083ff3d0ULL, 0x34b1de5d1ULL, 0x0bba4c5ceULL, 0x12f1e9846ULL, 0x2dfa7b859ULL, 0x2066a2356ULL, 0x1f6d30349ULL, 0x062695ec1ULL, 0x392d07edeULL, 0x2c2b89ed4ULL, 0x13201becbULL, 0x0a6bbe343ULL, 0x35602c35cULL, 0x38fcf5853ULL, 0x07f76784cULL, 0x1ebcc25c4ULL, 0x21b7505dbULL, 0x0585713daULL, 0x3a8ee33c5ULL, 0x23c546e4dULL, 0x1cced4e52ULL, 0x11520d55dULL, 0x2e599f542ULL, 0x37123a8caULL, 0x0819a88d5ULL, 0x27216b961ULL, 0x182af997eULL, 0x01615c4f6ULL, 0x3e6ace4e9ULL, 0x33f617fe6ULL, 0x0cfd85ff9ULL, 0x15b620271ULL, 0x2abdb226eULL, 0x0e8f9346fULL, 0x318401470ULL, 0x28cfa49f8ULL, 0x17c4369e7ULL, 0x1a58ef2e8ULL, 0x25537d2f7ULL, 0x3c18d8f7fULL, 0x03134af60ULL, 0x3a3e4d1beULL, 0x0535df1a1ULL, 0x1c7e7ac29ULL, 0x2375e8c36ULL, 0x2ee931739ULL, 0x11e2a3726ULL, 0x08a906aaeULL, 0x37a294ab1ULL, 0x1390b5cb0ULL, 0x2c9b27cafULL, 0x35d082127ULL, 0x0adb10138ULL, 0x0747c9a37ULL, 0x384c5ba28ULL, 0x2107fe7a0ULL, 0x1e0c6c7bfULL, 0x3134af60bULL, 0x0e3f3d614ULL, 0x177498b9cULL, 0x287f0ab83ULL, 0x25e3d308cULL, 0x1ae841093ULL, 0x03a3e4d1bULL, 0x3ca876d04ULL, 0x189a57b05ULL, 0x2791c5b1aULL, 0x3eda60692ULL, 0x01d1f268dULL, 0x0c4d2bd82ULL, 0x3346b9d9dULL, 0x2a0d1c015ULL, 0x15068e00aULL, 0x000000001ULL, 0x3f0b9201eULL, 0x264037d96ULL, 0x194ba5d89ULL, 0x14d77c686ULL, 0x2bdcee699ULL, 0x32974bb11ULL, 0x0d9cd9b0eULL, 0x29aef8d0fULL, 0x16a56ad10ULL, 0x0feecf098ULL, 0x30e55d087ULL, 0x3d7984b88ULL, 0x027216b97ULL, 0x1b39b361fULL, 0x243221600ULL, 0x0b0ae27b4ULL, 0x3401707abULL, 0x2d4ad5a23ULL, 0x124147a3cULL, 0x1fdd9e133ULL, 0x20d60c12cULL, 0x399da9ca4ULL, 0x06963bcbbULL, 0x22a41aabaULL, 0x1daf88aa5ULL, 0x04e42d72dULL, 0x3befbf732ULL, 0x367366c3dULL, 0x0978f4c22ULL, 0x1033511aaULL, 0x2f38c31b5ULL, 0x1615c4f6bULL, 0x291e56f74ULL, 0x3055f32fcULL, 0x0f5e612e3ULL, 0x02c2b89ecULL, 0x3dc92a9f3ULL, 0x24828f47bULL, 0x1b891d464ULL, 0x3fbb3c265ULL, 0x00b0ae27aULL, 0x19fb0bff2ULL, 0x26f099fedULL, 0x2b6c404e2ULL, 0x1467d24fdULL, 0x0d2c77975ULL, 0x3227e596aULL, 0x1d1f268deULL, 0x2214b48c1ULL, 0x3b5f11549ULL, 0x045483556ULL, 0x09c85ae59ULL, 0x36c3c8e46ULL, 0x2f886d3ceULL, 0x1083ff3d1ULL, 0x34b1de5d0ULL, 0x0bba4c5cfULL, 0x12f1e9847ULL, 0x2dfa7b858ULL, 0x2066a2357ULL, 0x1f6d30348ULL, 0x062695ec0ULL, 0x392d07edfULL, 0x2c2b89ed5ULL, 0x13201becaULL, 0x0a6bbe342ULL, 0x35602c35dULL, 0x38fcf5852ULL, 0x07f76784dULL, 0x1ebcc25c5ULL, 0x21b7505daULL, 0x0585713dbULL, 0x3a8ee33c4ULL, 0x23c546e4cULL, 0x1cced4e53ULL, 0x11520d55cULL, 0x2e599f543ULL, 0x37123a8cbULL, 0x0819a88d4ULL, 0x27216b960ULL, 0x182af997fULL, 0x01615c4f7ULL, 0x3e6ace4e8ULL, 0x33f617fe7ULL, 0x0cfd85ff8ULL, 0x15b620270ULL, 0x2abdb226fULL, 0x0e8f9346eULL, 0x318401471ULL, 0x28cfa49f9ULL, 0x17c4369e6ULL, 0x1a58ef2e9ULL, 0x25537d2f6ULL, 0x3c18d8f7eULL, 0x03134af61ULL, 0x3a3e4d1bfULL, 0x0535df1a0ULL, 0x1c7e7ac28ULL, 0x2375e8c37ULL, 0x2ee931738ULL, 0x11e2a3727ULL, 0x08a906aafULL, 0x37a294ab0ULL, 0x1390b5cb1ULL, 0x2c9b27caeULL, 0x35d082126ULL, 0x0adb10139ULL, 0x0747c9a36ULL, 0x384c5ba29ULL, 0x2107fe7a1ULL, 0x1e0c6c7beULL, 0x3134af60aULL, 0x0e3f3d615ULL, 0x177498b9dULL, 0x287f0ab82ULL, 0x25e3d308dULL, 0x1ae841092ULL, 0x03a3e4d1aULL, 0x3ca876d05ULL, 0x189a57b04ULL, 0x2791c5b1bULL, 0x3eda60693ULL, 0x01d1f268cULL, 0x0c4d2bd83ULL, 0x3346b9d9cULL, 0x2a0d1c014ULL, 0x15068e00bULL};

View File

@ -0,0 +1,960 @@
/*
Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTHASH_H
#define UTHASH_H
#include <string.h> /* memcmp,strlen */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit() */
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#if defined(_MSC_VER) /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
#define DECLTYPE(x) (decltype(x))
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define DECLTYPE(x)
#endif
#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
#define NO_DECLTYPE
#define DECLTYPE(x)
#else /* GNU, Sun and other compilers */
#define DECLTYPE(x) (__typeof(x))
#endif
#ifdef NO_DECLTYPE
#define DECLTYPE_ASSIGN(dst,src) \
do { \
char **_da_dst = (char**)(&(dst)); \
*_da_dst = (char*)(src); \
} while(0)
#else
#define DECLTYPE_ASSIGN(dst,src) \
do { \
(dst) = DECLTYPE(dst)(src); \
} while(0)
#endif
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
#if defined (_WIN32)
#if defined(_MSC_VER) && _MSC_VER >= 1600
#include <stdint.h>
#elif defined(__WATCOMC__)
#include <stdint.h>
#else
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#endif
#else
#include <stdint.h>
#endif
#define UTHASH_VERSION 1.9.9
#ifndef uthash_fatal
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
#endif
#ifndef uthash_malloc
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#endif
#ifndef uthash_free
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
#endif
#ifndef uthash_noexpand_fyi
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
#endif
#ifndef uthash_expand_fyi
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
#endif
/* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
/* calculate the element whose hash handle address is hhe */
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
#define HASH_FIND(hh,head,keyptr,keylen,out) \
do { \
out=NULL; \
if (head) { \
unsigned _hf_bkt,_hf_hashv; \
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
keyptr,keylen,out); \
} \
} \
} while (0)
#ifdef HASH_BLOOM
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
#define HASH_BLOOM_MAKE(tbl) \
do { \
(tbl)->bloom_nbits = HASH_BLOOM; \
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
} while (0)
#define HASH_BLOOM_FREE(tbl) \
do { \
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
} while (0)
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
#define HASH_BLOOM_ADD(tbl,hashv) \
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#define HASH_BLOOM_TEST(tbl,hashv) \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
#define HASH_BLOOM_MAKE(tbl)
#define HASH_BLOOM_FREE(tbl)
#define HASH_BLOOM_ADD(tbl,hashv)
#define HASH_BLOOM_TEST(tbl,hashv) (1)
#define HASH_BLOOM_BYTELEN 0
#endif
#define HASH_MAKE_TABLE(hh,head) \
do { \
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
sizeof(UT_hash_table)); \
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
(head)->hh.tbl->tail = &((head)->hh); \
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl->buckets, 0, \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_MAKE((head)->hh.tbl); \
(head)->hh.tbl->signature = HASH_SIGNATURE; \
} while(0)
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
do { \
replaced=NULL; \
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
if (replaced!=NULL) { \
HASH_DELETE(hh,head,replaced); \
} \
HASH_ADD(hh,head,fieldname,keylen_in,add); \
} while(0)
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
do { \
unsigned _ha_bkt; \
(add)->hh.next = NULL; \
(add)->hh.key = (char*)(keyptr); \
(add)->hh.keylen = (unsigned)(keylen_in); \
if (!(head)) { \
head = (add); \
(head)->hh.prev = NULL; \
HASH_MAKE_TABLE(hh,head); \
} else { \
(head)->hh.tbl->tail->next = (add); \
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
(head)->hh.tbl->tail = &((add)->hh); \
} \
(head)->hh.tbl->num_items++; \
(add)->hh.tbl = (head)->hh.tbl; \
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
(add)->hh.hashv, _ha_bkt); \
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
HASH_FSCK(hh,head); \
} while(0)
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
do { \
bkt = ((hashv) & ((num_bkts) - 1)); \
} while(0)
/* delete "delptr" from the hash table.
* "the usual" patch-up process for the app-order doubly-linked-list.
* The use of _hd_hh_del below deserves special explanation.
* These used to be expressed using (delptr) but that led to a bug
* if someone used the same symbol for the head and deletee, like
* HASH_DELETE(hh,users,users);
* We want that to work, but by changing the head (users) below
* we were forfeiting our ability to further refer to the deletee (users)
* in the patch-up process. Solution: use scratch space to
* copy the deletee pointer, then the latter references are via that
* scratch pointer rather than through the repointed (users) symbol.
*/
#define HASH_DELETE(hh,head,delptr) \
do { \
struct UT_hash_handle *_hd_hh_del; \
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
head = NULL; \
} else { \
unsigned _hd_bkt; \
_hd_hh_del = &((delptr)->hh); \
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
(head)->hh.tbl->tail = \
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
(head)->hh.tbl->hho); \
} \
if ((delptr)->hh.prev) { \
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
} else { \
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
} \
if (_hd_hh_del->next) { \
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
(head)->hh.tbl->hho))->prev = \
_hd_hh_del->prev; \
} \
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
(head)->hh.tbl->num_items--; \
} \
HASH_FSCK(hh,head); \
} while (0)
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
#define HASH_FIND_STR(head,findstr,out) \
HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out)
#define HASH_ADD_STR(head,strfield,add) \
HASH_ADD(hh,head,strfield[0],strlen(add->strfield),add)
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced)
#define HASH_FIND_INT(head,findint,out) \
HASH_FIND(hh,head,findint,sizeof(int),out)
#define HASH_ADD_INT(head,intfield,add) \
HASH_ADD(hh,head,intfield,sizeof(int),add)
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
#define HASH_FIND_PTR(head,findptr,out) \
HASH_FIND(hh,head,findptr,sizeof(void *),out)
#define HASH_ADD_PTR(head,ptrfield,add) \
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
#define HASH_DEL(head,delptr) \
HASH_DELETE(hh,head,delptr)
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
*/
#ifdef HASH_DEBUG
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
#define HASH_FSCK(hh,head) \
do { \
struct UT_hash_handle *_thh; \
if (head) { \
unsigned _bkt_i; \
unsigned _count; \
char *_prev; \
_count = 0; \
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
unsigned _bkt_count = 0; \
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
_prev = NULL; \
while (_thh) { \
if (_prev != (char*)(_thh->hh_prev)) { \
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
_thh->hh_prev, _prev ); \
} \
_bkt_count++; \
_prev = (char*)(_thh); \
_thh = _thh->hh_next; \
} \
_count += _bkt_count; \
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
HASH_OOPS("invalid bucket count %u, actual %u\n", \
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
} \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid hh item count %u, actual %u\n", \
(head)->hh.tbl->num_items, _count ); \
} \
/* traverse hh in app order; check next/prev integrity, count */ \
_count = 0; \
_prev = NULL; \
_thh = &(head)->hh; \
while (_thh) { \
_count++; \
if (_prev !=(char*)(_thh->prev)) { \
HASH_OOPS("invalid prev %p, actual %p\n", \
_thh->prev, _prev ); \
} \
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
(head)->hh.tbl->hho) : NULL ); \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid app item count %u, actual %u\n", \
(head)->hh.tbl->num_items, _count ); \
} \
} \
} while (0)
#else
#define HASH_FSCK(hh,head)
#endif
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
do { \
unsigned _klen = fieldlen; \
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
#else
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hb_keylen=keylen; \
char *_hb_key=(char*)(key); \
(hashv) = 0; \
while (_hb_keylen--) { (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; } \
bkt = (hashv) & (num_bkts-1); \
} while (0)
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _sx_i; \
char *_hs_key=(char*)(key); \
hashv = 0; \
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
bkt = hashv & (num_bkts-1); \
} while (0)
/* FNV-1a variation */
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _fn_i; \
char *_hf_key=(char*)(key); \
hashv = 2166136261UL; \
for(_fn_i=0; _fn_i < keylen; _fn_i++) { \
hashv = hashv ^ _hf_key[_fn_i]; \
hashv = hashv * 16777619; \
} \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _ho_i; \
char *_ho_key=(char*)(key); \
hashv = 0; \
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
hashv += _ho_key[_ho_i]; \
hashv += (hashv << 10); \
hashv ^= (hashv >> 6); \
} \
hashv += (hashv << 3); \
hashv ^= (hashv >> 11); \
hashv += (hashv << 15); \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_JEN_MIX(a,b,c) \
do { \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
} while (0)
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hj_i,_hj_j,_hj_k; \
unsigned char *_hj_key=(unsigned char*)(key); \
hashv = 0xfeedbeef; \
_hj_i = _hj_j = 0x9e3779b9; \
_hj_k = (unsigned)(keylen); \
while (_hj_k >= 12) { \
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ ( (unsigned)_hj_key[2] << 16 ) \
+ ( (unsigned)_hj_key[3] << 24 ) ); \
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ ( (unsigned)_hj_key[6] << 16 ) \
+ ( (unsigned)_hj_key[7] << 24 ) ); \
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ ( (unsigned)_hj_key[10] << 16 ) \
+ ( (unsigned)_hj_key[11] << 24 ) ); \
\
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
\
_hj_key += 12; \
_hj_k -= 12; \
} \
hashv += keylen; \
switch ( _hj_k ) { \
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
case 5: _hj_j += _hj_key[4]; \
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
case 1: _hj_i += _hj_key[0]; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
bkt = hashv & (num_bkts-1); \
} while(0)
/* The Paul Hsieh hash function */
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned char *_sfh_key=(unsigned char*)(key); \
uint32_t _sfh_tmp, _sfh_len = keylen; \
\
int _sfh_rem = _sfh_len & 3; \
_sfh_len >>= 2; \
hashv = 0xcafebabe; \
\
/* Main loop */ \
for (;_sfh_len > 0; _sfh_len--) { \
hashv += get16bits (_sfh_key); \
_sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \
hashv = (hashv << 16) ^ _sfh_tmp; \
_sfh_key += 2*sizeof (uint16_t); \
hashv += hashv >> 11; \
} \
\
/* Handle end cases */ \
switch (_sfh_rem) { \
case 3: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 16; \
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \
hashv += hashv >> 11; \
break; \
case 2: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 11; \
hashv += hashv >> 17; \
break; \
case 1: hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
} \
\
/* Force "avalanching" of final 127 bits */ \
hashv ^= hashv << 3; \
hashv += hashv >> 5; \
hashv ^= hashv << 4; \
hashv += hashv >> 17; \
hashv ^= hashv << 25; \
hashv += hashv >> 6; \
bkt = hashv & (num_bkts-1); \
} while(0)
#ifdef HASH_USING_NO_STRICT_ALIASING
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
#define MUR_GETBLOCK(p,i) p[i]
#else /* non intel */
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
#else /* assume little endian non-intel */
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
#endif
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
MUR_ONE_THREE(p))))
#endif
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
#define MUR_FMIX(_h) \
do { \
_h ^= _h >> 16; \
_h *= 0x85ebca6b; \
_h ^= _h >> 13; \
_h *= 0xc2b2ae35l; \
_h ^= _h >> 16; \
} while(0)
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
do { \
const uint8_t *_mur_data = (const uint8_t*)(key); \
const int _mur_nblocks = (keylen) / 4; \
uint32_t _mur_h1 = 0xf88D5353; \
uint32_t _mur_c1 = 0xcc9e2d51; \
uint32_t _mur_c2 = 0x1b873593; \
uint32_t _mur_k1 = 0; \
const uint8_t *_mur_tail; \
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
int _mur_i; \
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
\
_mur_h1 ^= _mur_k1; \
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
_mur_h1 = _mur_h1*5+0xe6546b64; \
} \
_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
_mur_k1=0; \
switch((keylen) & 3) { \
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
case 1: _mur_k1 ^= _mur_tail[0]; \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
_mur_h1 ^= _mur_k1; \
} \
_mur_h1 ^= (keylen); \
MUR_FMIX(_mur_h1); \
hashv = _mur_h1; \
bkt = hashv & (num_bkts-1); \
} while(0)
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
do { \
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
else out=NULL; \
while (out) { \
if ((out)->hh.keylen == keylen_in) { \
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
} \
if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
else out = NULL; \
} \
} while(0)
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head,addhh) \
do { \
head.count++; \
(addhh)->hh_next = head.hh_head; \
(addhh)->hh_prev = NULL; \
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
(head).hh_head=addhh; \
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
&& (addhh)->tbl->noexpand != 1) { \
HASH_EXPAND_BUCKETS((addhh)->tbl); \
} \
} while(0)
/* remove an item from a given bucket */
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
(head).count--; \
if ((head).hh_head == hh_del) { \
(head).hh_head = hh_del->hh_next; \
} \
if (hh_del->hh_prev) { \
hh_del->hh_prev->hh_next = hh_del->hh_next; \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
}
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
* the hash function as it applies to the key domain).
*
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
* the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
*
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
* Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
*
* ceil(n/b) = (n/b) + ((n%b)?1:0)
*
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
*
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
*
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
unsigned _he_bkt; \
unsigned _he_bkt_i; \
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
memset(_he_new_buckets, 0, \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->ideal_chain_maxlen = \
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
tbl->nonideal_items = 0; \
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
{ \
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
while (_he_thh) { \
_he_hh_nxt = _he_thh->hh_next; \
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
tbl->nonideal_items++; \
_he_newbkt->expand_mult = _he_newbkt->count / \
tbl->ideal_chain_maxlen; \
} \
_he_thh->hh_prev = NULL; \
_he_thh->hh_next = _he_newbkt->hh_head; \
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
_he_thh; \
_he_newbkt->hh_head = _he_thh; \
_he_thh = _he_hh_nxt; \
} \
} \
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
tbl->num_buckets *= 2; \
tbl->log2_num_buckets++; \
tbl->buckets = _he_new_buckets; \
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
(tbl->ineff_expands+1) : 0; \
if (tbl->ineff_expands > 1) { \
tbl->noexpand=1; \
uthash_noexpand_fyi(tbl); \
} \
uthash_expand_fyi(tbl); \
} while(0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
#define HASH_SRT(hh,head,cmpfcn) \
do { \
unsigned _hs_i; \
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
if (head) { \
_hs_insize = 1; \
_hs_looping = 1; \
_hs_list = &((head)->hh); \
while (_hs_looping) { \
_hs_p = _hs_list; \
_hs_list = NULL; \
_hs_tail = NULL; \
_hs_nmerges = 0; \
while (_hs_p) { \
_hs_nmerges++; \
_hs_q = _hs_p; \
_hs_psize = 0; \
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
_hs_psize++; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
if (! (_hs_q) ) break; \
} \
_hs_qsize = _hs_insize; \
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
if (_hs_psize == 0) { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
_hs_e = _hs_p; \
if (_hs_p){ \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
} \
_hs_psize--; \
} else if (( \
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
) <= 0) { \
_hs_e = _hs_p; \
if (_hs_p){ \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
} \
_hs_psize--; \
} else { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} \
if ( _hs_tail ) { \
_hs_tail->next = ((_hs_e) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
} else { \
_hs_list = _hs_e; \
} \
if (_hs_e) { \
_hs_e->prev = ((_hs_tail) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
} \
_hs_tail = _hs_e; \
} \
_hs_p = _hs_q; \
} \
if (_hs_tail){ \
_hs_tail->next = NULL; \
} \
if ( _hs_nmerges <= 1 ) { \
_hs_looping=0; \
(head)->hh.tbl->tail = _hs_tail; \
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
} \
_hs_insize *= 2; \
} \
HASH_FSCK(hh,head); \
} \
} while (0)
/* This function selects items from one hash into another hash.
* The end result is that the selected items have dual presence
* in both hashes. There is no copy of the items made; rather
* they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
unsigned _src_bkt, _dst_bkt; \
void *_last_elt=NULL, *_elt; \
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
if (src) { \
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
_src_hh; \
_src_hh = _src_hh->hh_next) { \
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
if (cond(_elt)) { \
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
_dst_hh->key = _src_hh->key; \
_dst_hh->keylen = _src_hh->keylen; \
_dst_hh->hashv = _src_hh->hashv; \
_dst_hh->prev = _last_elt; \
_dst_hh->next = NULL; \
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
if (!dst) { \
DECLTYPE_ASSIGN(dst,_elt); \
HASH_MAKE_TABLE(hh_dst,dst); \
} else { \
_dst_hh->tbl = (dst)->hh_dst.tbl; \
} \
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
(dst)->hh_dst.tbl->num_items++; \
_last_elt = _elt; \
_last_elt_hh = _dst_hh; \
} \
} \
} \
} \
HASH_FSCK(hh_dst,dst); \
} while (0)
#define HASH_CLEAR(hh,head) \
do { \
if (head) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
(head)=NULL; \
} \
} while(0)
#define HASH_OVERHEAD(hh,head) \
((head) ? ( \
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
(sizeof(UT_hash_table)) + \
(HASH_BLOOM_BYTELEN)))) : 0)
#ifdef NO_DECLTYPE
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
#else
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
#endif
/* obtain a count of items in the hash */
#define HASH_COUNT(head) HASH_CNT(hh,head)
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
typedef struct UT_hash_bucket {
struct UT_hash_handle *hh_head;
unsigned count;
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
* the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* (The multiplier is simply expand_mult+1). The whole idea of this
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
* value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
} UT_hash_bucket;
/* random signature used only to find hash tables in external analysis */
#define HASH_SIGNATURE 0xa0111fe1
#define HASH_BLOOM_SIGNATURE 0xb12220f2
typedef struct UT_hash_table {
UT_hash_bucket *buckets;
unsigned num_buckets, log2_num_buckets;
unsigned num_items;
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
/* in an ideal situation (all buckets used equally), no bucket would have
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
unsigned ideal_chain_maxlen;
/* nonideal_items is the number of items in the hash whose chain position
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
/* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
* function isn't a good fit for the key domain. When expansion is inhibited
* the hash will still work, albeit no longer in constant time. */
unsigned ineff_expands, noexpand;
uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOM
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
uint8_t *bloom_bv;
char bloom_nbits;
#endif
} UT_hash_table;
typedef struct UT_hash_handle {
struct UT_hash_table *tbl;
void *prev; /* prev element in app order */
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
#endif /* UTHASH_H */

View File

@ -0,0 +1,34 @@
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
# $Id$
PortSystem 1.0
PortGroup cmake 1.0
PortGroup github 1.0
github.setup greatscottgadgets libbtbb 2014-02-R2
categories net security
platforms darwin
maintainers gmail.com:dominicgs
license GPL-2+
description Bluetooth Baseband Decoding Library
long_description \
LibBTBB is a Bluetooth Baseband processing library that supports Basic \
Rate and Bluetooth Smart (BLE) packets. It is used by the Ubertooth and \
gr-bluetooth packet sniffer implementations.
homepage https://github.com/greatscottgadgets/libbtbb
checksums rmd160 0adc5d59e611509cdcf8959be8b6e31704529e48 \
sha256 04a187b6f17836437e5f9deecb0b643c75ec0eafce671e373d1d4c13fc104984
configure.dir ${workpath}/build
build.dir ${configure.dir}
post-extract {
file mkdir ${configure.dir}
}
configure.post_args ../${name}-${version}
configure.args-append -DPACKAGE_MANAGER=1

View File

@ -0,0 +1,26 @@
require "formula"
class Libbtbb < Formula
homepage "https://github.com/greatscottgadgets/libbtbb"
url "https://github.com/greatscottgadgets/libbtbb/archive/2014-02-R2.tar.gz"
sha1 "aa94b7d92465704aa647123f11e906491a26d090"
version "2014-02-R2"
head "https://github.com/greatscottgadgets/libbtbb.git"
option :universal
depends_on "cmake" => :build
depends_on :python
def install
if build.universal?
ENV.universal_binary
ENV["CMAKE_OSX_ARCHITECTURES"] = Hardware::CPU.universal_archs.as_cmake_arch_flags
end
mkdir "build" do
system "cmake", "..", *std_cmake_args
system "make", "install"
end
end
end

View File

@ -0,0 +1,64 @@
#
#Copyright 2013 Dominic Spill
#
#This file is part of libbtbb
#
#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, 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 libbtbb; see the file COPYING. If not, write to
#the Free Software Foundation, Inc., 51 Franklin Street,
#Boston, MA 02110-1301, USA.
#
Summary: Bluetooth baseband library
Name: libbtbb
Version: 2013.06
Release: 1
Summary: A Bluetooth basebad decoding library
License: GPLv2
URL: http://mooedit.sourceforge.net/
Source: %{name}-%{version}.tar.gz
BuildRequires: cmake gcc python
Autoreqprov: on
%description
A library for decoding and processing Bluetooth baseband packets.
It can be used with any raw bitstream receiver, such as Ubertooth or
gr-bluetooth.
%prep
%setup -q
%build
cmake -DCMAKE_SKIP_RPATH=ON \
-DCMAKE_INSTALL_PREFIX=%{_prefix} \
-DBUILD_ROOT=%{buildroot}
%{__make} %{?jobs:-j%jobs}
%install
%{__make} DESTDIR=%{buildroot} install
%files
%{_prefix}/lib/libbtbb.so
%{_prefix}/lib/libbtbb.so.0
%{_prefix}/lib/libbtbb.so.0.2.0
%{_prefix}/lib/python*
%{_bindir}/btaptap
%{_libdir}/../include/libbtbb/bluetooth_le_packet.h
%{_libdir}/../include/libbtbb/btbb.h
%doc COPYING README.md
%changelog
* Thu Jun 06 2013 Dominic Spill <dominincgs@gmail.com> - 0.2.0
- First binary release

View File

@ -0,0 +1,40 @@
# Copyright 2013 Dominic Spill
#
# This file is part of Libbtbb
#
# GNU Radio 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, or (at your option)
# any later version.
#
# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
project(btbb-python)
# Check for python installation
find_package(PythonInterp)
if(NOT PYTHONINTERP_FOUND)
return()
else()
add_subdirectory(pcaptools)
endif()
# Create uninstall target
if(NOT libbtbb_all_SOURCE_DIR)
configure_file(
${PROJECT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)
add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)
endif()

View File

@ -0,0 +1,38 @@
# Copyright 2013 Dominic Spill
#
# This file is part of Libbtbb (pcapdump)
#
# GNU Radio 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, or (at your option)
# any later version.
#
# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
set(SETUP_PY_IN ${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in)
set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
set(DEPS ${CMAKE_CURRENT_SOURCE_DIR}/pcapdump/__init__.py
${CMAKE_CURRENT_SOURCE_DIR}/pcapdump/pcapdump.py)
set(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/build)
configure_file(${SETUP_PY_IN} ${SETUP_PY})
add_custom_command(OUTPUT ${OUTPUT}/timestamp
COMMAND ${PYTHON_EXECUTABLE} setup.py build
COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}/timestamp
DEPENDS ${DEPS})
add_custom_target(pcapdump ALL DEPENDS ${OUTPUT}/timestamp)
install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build -b ${OUTPUT} install --prefix=${BUILD_ROOT}/${CMAKE_INSTALL_PREFIX})")
add_custom_target(btaptap ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/btaptap)
install(PROGRAMS btaptap DESTINATION ${INSTALL_DEFAULT_BINDIR})

View File

@ -0,0 +1,39 @@
# Copyright 2012 Michael Ossmann, Dominic Spill
#
# This file is part of Project Ubertooth.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
INSTALL ?= /usr/bin/install
PYTHON ?= /usr/bin/env python
INSTALL_DIR ?= /usr/bin
EXECUTABLE_FILES = btaptap
all: pcapdump
pcapdump:
$(PYTHON) setup.py build
clean:
rm -rf build
install: pcapdump
$(PYTHON) setup.py install
$(INSTALL) -m 0755 $(EXECUTABLE_FILES) $(INSTALL_DIR)
.PHONY: all clean install pcapdump

View File

@ -0,0 +1,20 @@
This directory contains supplemental tools for working with pcap files produced
by libbtbb. (Actually libbtbb doesn't produce such files by itself at this
time, but you can produce them with the Ubertooth tools.
These tools are not automatically installed as part of the libbtbb
installation but can be used right out of this directory or manually installed.
pcapdump: a Python module for pcap
Pcapdump us used by btaptap to read and write pcap files. It should work with
python 2.4 and above (python 3 support requires using the 2to3 tool).
btaptap: a Bluetooth keyboard sniffer
Many Bluetooth keyboards operate by default in "boot mode" which features
simplified HID messaging that can be interpreted, for example, by a PC BIOS.
Some of those keyboards also transmit these messages over unencrypted
Bluetooth. This tool can be used to extract keystrokes from such
transmissions.

View File

@ -0,0 +1,520 @@
#!/usr/bin/env python
#
# Copyright 2009 Joshua Wright, Michael Ossmann
#
# This file is part of gr-bluetooth
#
# gr-bluetooth 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, or (at your option)
# any later version.
#
# gr-bluetooth 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 gr-bluetooth; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
import sys
import struct
import time
from pcapdump.pcapdump import *
DLT_EN10MB = 1
DLT_BLUETOOTH_HCI_H4 = 187
ELLISYS_CSV_HDR = "\"Depth\",\"Time\",\"Name\",\"Data\"\x0d\x0a"
ELLISYS_HID_INPUT = "HID Input 1"
USBHID_MAP = {
0x04 : "a",
0x05 : "b",
0x06 : "c",
0x07 : "d",
0x08 : "e",
0x09 : "f",
0x0A : "g",
0x0B : "h",
0x0C : "i",
0x0D : "j",
0x0E : "k",
0x0F : "l",
0x10 : "m",
0x11 : "n",
0x12 : "o",
0x13 : "p",
0x14 : "q",
0x15 : "r",
0x16 : "s",
0x17 : "t",
0x18 : "u",
0x19 : "v",
0x1A : "w",
0x1B : "x",
0x1C : "y",
0x1D : "z",
0x1E : "1",
0x1F : "2",
0x20 : "3",
0x21 : "4",
0x22 : "5",
0x23 : "6",
0x24 : "7",
0x25 : "8",
0x26 : "9",
0x27 : "0",
0x28 : "[Return]\n",
0x29 : "[Esc]",
0x2A : "[Backspace]",
0x2B : "[Tab]\t",
0x2C : " ",
0x2D : "-",
0x2E : "=",
0x2F : "[",
0x30 : "]",
0x31 : "\\",
0x32 : "#",
0x33 : ";",
0x34 : "'",
0x35 : "[Grave Accent]",
0x36 : ",",
0x37 : ".",
0x38 : "/",
0x39 : "[Caps Lock]",
0x3A : "[F1]",
0x3B : "[F2]",
0x3C : "[F3]",
0x3D : "[F4]",
0x3E : "[F5]",
0x3F : "[F6]",
0x40 : "[F7]",
0x41 : "[F8]",
0x42 : "[F9]",
0x43 : "[F10]",
0x44 : "[F11]",
0x45 : "[F12]",
0x46 : "[PrintScreen]",
0x47 : "[Scroll]",
0x48 : "[Pause]",
0x49 : "[Insert]",
0x4A : "[Home]",
0x4B : "[PageUp]",
0x4C : "[Delete]",
0x4D : "[End]",
0x4E : "[PageDown]",
0x4F : "[RightArrow]",
0x50 : "[LeftArrow]",
0x51 : "[DownArrow]",
0x52 : "[UpArrow]",
0x53 : "[Keypad Num Lock and Clear]",
0x54 : "[Keypad /]",
0x55 : "[Keypad *]",
0x56 : "[Keypad -]",
0x57 : "[Keypad +]",
0x58 : "[Keypad Enter]\n",
0x59 : "[Keypad 1 and End]",
0x5A : "[Keypad 2 and Down Arrow]",
0x5B : "[Keypad 3 and PageDn]",
0x5C : "[Keypad 4 and Left Arrow]",
0x5D : "[Keypad 5]",
0x5E : "[Keypad 6 and Right Arrow]",
0x5F : "[Keypad 7 and Home]",
0x60 : "[Keypad 8 and Up Arrow]",
0x61 : "[Keypad 9 and PageUp]",
0x62 : "[Keypad 0 and Insert]",
0x63 : "[Keypad . and Delete]",
0x64 : "\\",
0x65 : "[WinKey]",
0x66 : "[Power9]",
0x67 : "[Keypad =]",
0x68 : "[F13]",
0x69 : "[F14]",
0x6A : "[F15]",
0x6B : "[F16]",
0x6C : "[F17]",
0x6D : "[F18]",
0x6E : "[F19]",
0x6F : "[F20]",
0x70 : "[F21]",
0x71 : "[F22]",
0x72 : "[F23]",
0x73 : "[F24]",
0x74 : "[Execute]",
0x75 : "[Help]",
0x76 : "[Menu]",
0x77 : "[Select]",
0x78 : "[Stop]",
0x79 : "[Again]",
0x7A : "[Undo]",
0x7B : "[Cut]",
0x7C : "[Copy]",
0x7D : "[Paste]",
0x7E : "[Find]",
0x7F : "[Mute]",
0x80 : "[Volume Up]",
0x81 : "[Volume Down]",
0x82 : "[Locking Caps Lock]",
0x83 : "[Locking Num Lock]",
0x84 : "[Locking Scroll Lock]",
0x85 : "[Keypad Comma]",
0x86 : "[Keypad Equal]",
0x87 : "[International1]",
0x88 : "[International2]",
0x89 : "[International3]",
0x8A : "[International4]",
0x8B : "[International5]",
0x8C : "[International6]",
0x8D : "[International7]",
0x8E : "[International8]",
0x8F : "[International9]",
0x90 : "[LANG1]",
0x91 : "[LANG2]",
0x92 : "[LANG3]",
0x93 : "[LANG4]",
0x94 : "[LANG5]",
0x95 : "[LANG6]",
0x96 : "[LANG7]",
0x97 : "[LANG8]",
0x98 : "[LANG9]",
0x99 : "[Alternate Erase]",
0x9A : "[SysReq/Attention]",
0x9B : "[Cancel]",
0x9C : "[Clear]",
0x9D : "[Prior]",
0x9E : "[Return]\n",
0x9F : "[Separator]",
0xA0 : "[Out]",
0xA1 : "[Oper]",
0xA2 : "[Clear/Again]",
0xA3 : "[CrSel/Props]",
0xA4 : "[ExSel]",
0xB0 : "[Keypad 00]",
0xB1 : "[Keypad 000]",
0xB2 : "[Thousands Separator]",
0xB3 : "[Decimal Separator]",
0xB4 : "[Currency Unit]",
0xB5 : "[Currency Sub-unit]",
0xB6 : "[Keypad (]",
0xB7 : "[Keypad )]",
0xB8 : "[Keypad {]",
0xB9 : "[Keypad }]",
0xBA : "[Keypad Tab]\t",
0xBB : "[Keypad Backspace]",
0xBC : "[Keypad A]",
0xBD : "[Keypad B]",
0xBE : "[Keypad C]",
0xBF : "[Keypad D]",
0xC0 : "[Keypad E]",
0xC1 : "[Keypad F]",
0xC2 : "[Keypad XOR]",
0xC3 : "[Keypad ^]",
0xC4 : "[Keypad %]",
0xC5 : "[Keypad <]",
0xC6 : "[Keypad >]",
0xC7 : "[Keypad &]",
0xC8 : "[Keypad &&]",
0xC9 : "[Keypad |]",
0xCA : "[Keypad ||]",
0xCB : "[Keypad :]",
0xCC : "[Keypad #]",
0xCD : "[Keypad Space]",
0xCE : "[Keypad @]",
0xCF : "[Keypad !]",
0xD0 : "[Keypad Memory Store]",
0xD1 : "[Keypad Memory Recall]",
0xD2 : "[Keypad Memory Clear]",
0xD3 : "[Keypad Memory Add]",
0xD4 : "[Keypad Memory Subtract]",
0xD5 : "[Keypad Memory Multiply]",
0xD6 : "[Keypad Memory Divide]",
0xD7 : "[Keypad +/-]",
0xD8 : "[Keypad Clear]",
0xD9 : "[Keypad Clear Entry]",
0xDA : "[Keypad Binary]",
0xDB : "[Keypad Octal]",
0xDC : "[Keypad Decimal]",
0xDD : "[Keypad Hexadecimal]",
0xE0 : "[LeftControl]",
0xE1 : "[LeftShift]",
0xE2 : "[LeftAlt]",
0xE3 : "[LeftWinKey]",
0xE4 : "[RightControl]",
0xE5 : "[RightShift]",
0xE6 : "[RightAlt]",
0xE7 : "[RightWinKey]"
}
# some keycodes represent different things when Shift is held down
USBHID_SHIFT_MAP = {
0x04 : "A",
0x05 : "B",
0x06 : "C",
0x07 : "D",
0x08 : "E",
0x09 : "F",
0x0A : "G",
0x0B : "H",
0x0C : "I",
0x0D : "J",
0x0E : "K",
0x0F : "L",
0x10 : "M",
0x11 : "N",
0x12 : "O",
0x13 : "P",
0x14 : "Q",
0x15 : "R",
0x16 : "S",
0x17 : "T",
0x18 : "U",
0x19 : "V",
0x1A : "W",
0x1B : "X",
0x1C : "Y",
0x1D : "Z",
0x1E : "!",
0x1F : "@",
0x20 : "#",
0x21 : "$",
0x22 : "%",
0x23 : "^",
0x24 : "&",
0x25 : "*",
0x26 : "(",
0x27 : ")",
0x2D : "_",
0x2E : "+",
0x2F : "{",
0x30 : "}",
0x31 : "|",
0x32 : "~",
0x33 : ":",
0x34 : "\"",
0x35 : "~",
0x36 : "<",
0x37 : ">",
0x38 : "?",
0x64 : "|"
}
# global variable to track currently depressed keys
active_keys = []
def hid2ascii(scancode, shift):
'''
Convert the specified scancode value to the ASCII equivalent using the
USBHID_MAP list.
'''
if shift:
try:
code = USBHID_SHIFT_MAP[scancode]
return code
except KeyError:
pass
try:
code = USBHID_MAP[scancode]
except KeyError:
return "[Reserved]"
return code
def usage():
print >>sys.stderr, "Usage: btaptap [-r pcapfile.pcap | -e ellisysfile.csv] [-c count] [-h]\n"
sys.exit(0)
def parse_l2cap_keydata(l2cappkt):
global active_keys
TRANS_HDR_IN_DATA = 0xA1
REPORT_ID_KEYBOARD = 0x01
CTRL = 1
SHIFT = 2
ALT = 4
GUI = 8
# Keyboard keystrokes are only seen in L2CAP packets at least 10 bytes long
l2clen = (ord(l2cappkt[1]) << 8) | ord(l2cappkt[0])
if l2clen < 10:
return
# Keyboard keystrokes are only carried by Channel ID >= 0x40
cid = (ord(l2cappkt[3]) << 8) | ord(l2cappkt[2])
if cid < 0x40:
return
# Ideally we would check for the particular CID for the HID_INTERRUPT
# channel, but we don't handle the negotiation (and may not have even
# seen it).
# Transaction Header should indicate input data
thdr = ord(l2cappkt[4])
if thdr != TRANS_HDR_IN_DATA:
return
# Report ID should indicate this is a keyboard
rid = ord(l2cappkt[5])
if rid != REPORT_ID_KEYBOARD:
return
# This byte describes modifier key status (one bit per key)
mod = ord(l2cappkt[6])
# We don't care whether left or right modifier keys are pressed, so we
# combine the status bits.
leftmod = mod & 0x0f
rightmod = (mod & 0xf0) >> 4
mod = leftmod | rightmod
# up to six keys can be reported at once
keycodes = []
#for byte in range(8,14):
for byte in range(8,11):
keystroke = ord(l2cappkt[byte])
if keystroke != 0x00:
keycodes.append(keystroke)
for keystroke in keycodes:
# don't repeat keys that are still held down
if active_keys.count(keystroke) == 0:
if (mod & CTRL):
sys.stdout.write("CTRL^")
if (mod & ALT):
sys.stdout.write("ALT^")
if (mod & GUI): # e.g. Windows key
sys.stdout.write("GUI^")
sys.stdout.write(hid2ascii(keystroke, mod & SHIFT))
active_keys = keycodes
def parse_ellisys_export(exportfile):
try:
cap = open(exportfile, "r")
except (OSError, IOError) as e:
print >>sys.stderr, "Unable to open Ellisys capture file."
return
# Check to make sure the CSV file header matches out expectations
hdr=cap.readline()
if (hdr != ELLISYS_CSV_HDR):
print >>sys.stderr, "Invalid CSV file (does not match Ellisys export format)"
return
for packetline in cap.xreadlines():
try:
(edepth, etime, ename, edata) = packetline.replace('"', '').strip().split(",")
except ValueError:
continue
# We are only interedted in HID Input data
if (ename != ELLISYS_HID_INPUT): continue
parse_ellisys_keydata(edata)
def parse_ellisys_keydata(payload):
TRANS_HDR_IN_DATA = "\xA1"
DEST_CHANNEL_ID = "\x06\x03"
# Convert space-separated hex into string
payload = payload.replace(' ','').decode("hex")
# The Ellisys CSV file format doesn't give us the L2CAP data, so we fake it here by adding
# a 2-byte length field, destination CID, and transaction header
packet = chr(len(payload)+1) + "\x00" + DEST_CHANNEL_ID + TRANS_HDR_IN_DATA + payload
parse_l2cap_keydata(packet)
def parse_bb_keydata(packet):
BTBBHDR_TYPE_MASK = 0x78
BTBBHDR_TYPE_SHIFT = 3
BTBBHDR_TYPE_DM1 = 3
BTBBPAYLOADHDR_LLID_MASK = 0x03
BTBBPAYLOADHDR_LLID_SHIFT = 0
BTBBPAYLOADHDR_LEN_MASK = 0xF8
BTBBPAYLOADHDR_LEN_SHIFT = 3
LLID_L2CAP = 2
# Keyboard keystrokes are only seen in frames at least 40 bytes long
if len(packet) < 40:
return
# Keyboard keystrokes are only seen in DM1 frames
btbbhdr = packet[20:23]
type = (ord(btbbhdr[0]) & BTBBHDR_TYPE_MASK) >> BTBBHDR_TYPE_SHIFT
if type != BTBBHDR_TYPE_DM1:
return
# Keyboard keystrokes are only seen in L2CAP packets 14 bytes long
btbbpayloadhdr = ord(packet[23])
llid = btbbpayloadhdr & (BTBBPAYLOADHDR_LLID_MASK) >> BTBBPAYLOADHDR_LLID_SHIFT
l2clen = (btbbpayloadhdr & BTBBPAYLOADHDR_LEN_MASK) >> BTBBPAYLOADHDR_LEN_SHIFT
#print "Debug btbbpayloadhdr 0x%02x, llid %d, l2clen %d"%(btbbpayloadhdr, llid, l2clen)
if llid != LLID_L2CAP or l2clen < 14:
return
parse_l2cap_keydata(packet[24:38])
def parse_hci_keydata(packet):
HCI_TYPE_ACL_DATA = 2
# Keyboard keystrokes are only seen in frames at least 19 bytes long
if len(packet) < 19:
return
# Keyboard keystrokes are only seen in ACL Data frames
type = ord(packet[0])
if type != HCI_TYPE_ACL_DATA:
return
parse_l2cap_keydata(packet[5:])
if __name__ == '__main__':
arg_pcapfile = None
arg_ellisysfile = None
arg_count = -1
packetcount = 0
while len(sys.argv) > 1:
op = sys.argv.pop(1)
if op == '-r':
arg_pcapfile = sys.argv.pop(1)
if op == '-c':
arg_count = int(sys.argv.pop(1))
if op == '-e':
arg_ellisysfile = sys.argv.pop(1)
if op == '-h':
usage()
sys.exit(0)
if (arg_ellisysfile == None and arg_pcapfile == None):
print >>sys.stderr, "Must specify a libpcap capture or an Ellisys CSV file"
usage()
sys.exit(0)
if arg_pcapfile != None:
cap = PcapReader(arg_pcapfile)
while arg_count != packetcount:
try:
(pheader, packet) = cap.pnext()
pkttime = pheader[0]
packetcount+=1
if cap.datalink() == DLT_EN10MB:
parse_bb_keydata(packet)
elif cap.datalink() == DLT_BLUETOOTH_HCI_H4:
parse_hci_keydata(packet)
else:
print >>sys.stderr, "Unsupported libpcap data link layer: %d\n" % cap.datalink()
except TypeError: # raised when pnext returns Null (end of capture)
break
cap.close()
if arg_ellisysfile != None:
parse_ellisys_export(arg_ellisysfile)
print

View File

@ -0,0 +1,193 @@
# Copyright 2009 Joshua Wright
#
# This file is part of gr-bluetooth
#
# gr-bluetooth 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, or (at your option)
# any later version.
#
# gr-bluetooth 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 gr-bluetooth; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
import struct
import time
PCAPH_MAGIC_NUM = 0xa1b2c3d4
PCAPH_VER_MAJOR = 2
PCAPH_VER_MINOR = 4
PCAPH_THISZONE = 0
PCAPH_SIGFIGS = 0
PCAPH_SNAPLEN = 65535
class PcapReader:
def __init__(self, savefile):
'''
Opens the specified file, validates a libpcap header is present.
@type savefile: String
@param savefile: Input libpcap filename to open
@rtype: None
'''
PCAPH_LEN = 24
self.__fh = open(savefile, mode='rb')
self._pcaphsnaplen = 0
header = self.__fh.read(PCAPH_LEN)
# Read the first 4 bytes for the magic number, determine endianness
magicnum = struct.unpack("I", header[0:4])[0]
if magicnum != 0xd4c3b2a1:
# Little endian
self.__endflag = "<"
elif magicnum == 0xa1b2c3d4:
# Big endign
self.__endflag = ">"
else:
raise Exception('Specified file is not a libpcap capture')
pcaph = struct.unpack("%sIHHIIII"%self.__endflag, header)
if pcaph[1] != PCAPH_VER_MAJOR and pcaph[2] != PCAPH_VER_MINOR \
and pcaph[3] != PCAPH_THISZONE and pcaph[4] != PCAPH_SIGFIGS \
and pcaph[5] != PCAPH_SNAPLEN:
raise Exception('Unsupported pcap header format or version')
self._pcaphsnaplen = pcaph[5]
self._datalink = pcaph[6]
def datalink(self):
return self._datalink
def close(self):
'''
Closes the output packet capture; wrapper for pcap_close().
@rtype: None
'''
self.pcap_close()
def pcap_close(self):
'''
Closes the output packet capture.
@rtype: None
'''
self.__fh.close()
def pnext(self):
'''
Wrapper for pcap_next to mimic method for Daintree SNA
'''
return self.pcap_next()
def pcap_next(self):
'''
Retrieves the next packet from the capture file. Returns a list of
[Hdr, packet] where Hdr is a list of [timestamp, snaplen, plen] and
packet is a string of the payload content. Returns None at the end
of the packet capture.
@rtype: List
'''
# Read the next header block
PCAPH_RECLEN = 16
rechdrdata = self.__fh.read(PCAPH_RECLEN)
try:
rechdrtmp = struct.unpack("%sIIII"%self.__endflag, rechdrdata)
except struct.error:
return [None,None]
rechdr = [
float("%s.%s"%(rechdrtmp[0],rechdrtmp[1])),
rechdrtmp[2],
rechdrtmp[3]
]
if rechdr[1] > rechdr[2] or rechdr[1] > self._pcaphsnaplen or rechdr[2] > self._pcaphsnaplen:
raise Exception('Corrupted or invalid libpcap record header (included length exceeds actual length)')
# Read the included packet length
frame = self.__fh.read(rechdr[1])
return [rechdr, frame]
class PcapDumper:
def __init__(self, datalink, savefile):
'''
Creates a libpcap file using the specified datalink type.
@type datalink: Integer
@param datalink: Datalink type, one of DLT_* defined in pcap-bpf.h
@type savefile: String
@param savefile: Output libpcap filename to open
@rtype: None
'''
self.__fh = open(savefile, mode='wb')
self.__fh.write(''.join([
struct.pack("I", PCAPH_MAGIC_NUM),
struct.pack("H", PCAPH_VER_MAJOR),
struct.pack("H", PCAPH_VER_MINOR),
struct.pack("I", PCAPH_THISZONE),
struct.pack("I", PCAPH_SIGFIGS),
struct.pack("I", PCAPH_SNAPLEN),
struct.pack("I", datalink)
]))
def pcap_dump(self, packet, ts_sec=None, ts_usec=None, orig_len=None):
'''
Appends a new packet to the libpcap file. Optionally specify ts_sec
and tv_usec for timestamp information, otherwise the current time is
used. Specify orig_len if your snaplen is smaller than the entire
packet contents.
@type ts_sec: Integer
@param ts_sec: Timestamp, number of seconds since Unix epoch. Default
is the current timestamp.
@type ts_usec: Integer
@param ts_usec: Timestamp microseconds. Defaults to current timestamp.
@type orig_len: Integer
@param orig_len: Length of the original packet, used if the packet you
are writing is smaller than the original packet. Defaults to the
specified packet's length.
@type packet: String
@param packet: Packet contents
@rtype: None
'''
if ts_sec == None or ts_usec == None:
# There must be a better way here that I don't know -JW
s_sec, s_usec = str(time.time()).split(".")
ts_sec = int(s_sec)
ts_usec = int(s_usec)
if orig_len == None:
orig_len = len(packet)
plen = len(packet)
self.__fh.write(''.join([
struct.pack("I", ts_sec),
struct.pack("I", ts_usec),
struct.pack("I", orig_len),
struct.pack("I", plen),
packet
]))
return
def close(self):
'''
Closes the output packet capture; wrapper for pcap_close().
@rtype: None
'''
self.pcap_close()
def pcap_close(self):
'''
Closed the output packet capture.
@rtype: None
'''
self.__fh.close()

View File

@ -0,0 +1,31 @@
#!/usr/bin/env python
"""
pcapdump setup
Install script for pcapdump
Usage: python setup.py install
This file is part of libbtbb
Copyright 2012 Dominic Spill
"""
from distutils.core import setup
setup(
name = "pcapdump",
version = "0.8",
description = "A reader and dump utility for Pcap files",
author = "Joshua Wright",
url = "https://sourceforge.net/projects/libbtbb/",
license = "GPL",
packages = ['pcapdump'],
classifiers=[
'Development Status :: 5 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Programming Language :: Python',
'Operating System :: OS Independent',
'Topic :: System :: Networking :: Monitoring',
],
)

View File

@ -0,0 +1,32 @@
#!/usr/bin/env python
"""
pcapdump setup
Install script for pcapdump
Usage: python setup.py install
This file is part of libbtbb
Copyright 2012-2013 Dominic Spill
"""
from distutils.core import setup
setup(
name = "pcapdump",
description = "A reader and dump utility for Pcap files",
author = "Joshua Wright",
url = "https://sourceforge.net/projects/libbtbb/",
license = "GPL",
version = '${PACKAGE_VERSION}',
package_dir = { '': '${CMAKE_CURRENT_SOURCE_DIR}' },
packages = ['pcapdump'],
classifiers=[
'Development Status :: 5 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Programming Language :: Python',
'Operating System :: OS Independent',
'Topic :: System :: Networking :: Monitoring',
],
)

View File

@ -0,0 +1,866 @@
"Depth","Time","Name","Data"
"0","7.248613000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","7.249863000","HID Input 1","01 00 00 28 00 00 00 00 00"
"0","7.251113000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","10.646359000","HID Input 1","01 00 00 28 00 00 00 00 00"
"0","10.658858750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","10.681358750","HID Input 1","01 00 00 28 00 00 00 00 00"
"0","10.758865000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","10.893876750","HID Input 1","01 00 00 28 00 00 00 00 00"
"0","10.983884250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","12.558997750","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","13.009032500","HID Input 1","01 02 00 08 00 00 00 00 00"
"0","13.144044625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","13.189048625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","13.324059500","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","13.414067500","HID Input 1","01 00 00 11 17 00 00 00 00"
"0","13.459070500","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","13.504074375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","13.549077875","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","13.594078750","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","13.684083375","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","13.729087500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","13.774091625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","13.864099125","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","13.865349125","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","13.954107375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","13.955357375","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","13.999108000","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","14.044112125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","14.089117000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","14.134119250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","14.269131375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","14.270381375","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","14.404141250","HID Input 1","01 02 00 17 00 00 00 00 00"
"0","14.449145125","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","14.584155625","HID Input 1","01 02 00 06 00 00 00 00 00"
"0","14.674164250","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","14.675414250","HID Input 1","01 02 00 13 00 00 00 00 00"
"0","14.809176000","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","14.854179250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","14.855429250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","14.944184000","HID Input 1","01 00 00 2C 16 00 00 00 00"
"0","14.989186250","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","15.034189500","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","15.079194375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","15.169201125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","15.214205250","HID Input 1","01 00 00 14 00 00 00 00 00"
"0","15.349217625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","15.350467625","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","15.394222125","HID Input 1","01 00 00 18 08 00 00 00 00"
"0","15.439224500","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","15.484228000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","15.619238750","HID Input 1","01 00 00 11 06 00 00 00 00"
"0","15.620488750","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","15.709246125","HID Input 1","01 00 00 06 08 00 00 00 00"
"0","15.710496125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","15.754250625","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","15.799253375","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","15.844256875","HID Input 1","01 00 00 2C 11 00 00 00 00"
"0","15.889262250","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","15.934265375","HID Input 1","01 00 00 11 18 00 00 00 00"
"0","15.979269125","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","16.024272875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","16.114280375","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","16.249286750","HID Input 1","01 00 00 10 05 00 00 00 00"
"0","16.294289875","HID Input 1","01 00 00 05 00 00 00 00 00"
"0","16.295540000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","16.384296125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","16.474304000","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","16.519306375","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","16.564310750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","16.834333625","HID Input 1","01 20 00 00 00 00 00 00 00"
"0","16.924341375","HID Input 1","01 20 00 33 00 00 00 00 00"
"0","17.014348625","HID Input 1","01 00 00 33 00 00 00 00 00"
"0","17.059353250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","17.194365625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","17.329375625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","17.330625625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","17.419381000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","17.420631000","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","17.509384500","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","17.510634375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","17.554388500","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","17.599393125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","17.689399750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","17.734403750","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","17.869416125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","17.870666125","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","17.959421875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","18.004424875","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","18.184440500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","18.185690625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","18.274448625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","18.319453375","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","18.409461000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","18.454464375","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","18.544471500","HID Input 1","01 00 00 06 12 00 00 00 00"
"0","18.545721500","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","18.634478875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","18.724483000","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","18.814490375","HID Input 1","01 00 00 0F 2C 00 00 00 00"
"0","18.859493750","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","18.949501375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","18.994505500","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","19.129516125","HID Input 1","01 00 00 18 16 00 00 00 00"
"0","19.130766250","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","19.219524125","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","19.220773875","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","19.309531000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","19.354534125","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","19.444542000","HID Input 1","01 00 00 16 2C 00 00 00 00"
"0","19.445792000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","19.579553625","HID Input 1","01 00 00 2C 16 00 00 00 00"
"0","19.580803625","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","19.669561125","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","19.714563625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","19.759568375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","19.850826125","HID Input 1","01 00 00 14 00 00 00 00 00"
"0","19.939581000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","19.940831125","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","20.029584250","HID Input 1","01 00 00 18 08 00 00 00 00"
"0","20.074588375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","20.075838500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","20.164594500","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","20.209599125","HID Input 1","01 00 00 11 06 00 00 00 00"
"0","20.254602250","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","20.299605750","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","20.344609375","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","20.390862750","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","20.479621250","HID Input 1","01 00 00 2C 11 00 00 00 00"
"0","20.480871250","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","20.524623750","HID Input 1","01 00 00 11 18 00 00 00 00"
"0","20.569627750","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","20.614630625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","20.659633750","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","20.794646250","HID Input 1","01 00 00 10 05 00 00 00 00"
"0","20.839650500","HID Input 1","01 00 00 05 00 00 00 00 00"
"0","20.840900375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","20.929658125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","20.974661000","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","21.019666125","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","21.109672625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","21.110922625","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","21.199678625","HID Input 1","01 00 00 16 2C 00 00 00 00"
"0","21.244683250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","21.289683500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","21.334685625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","21.379689625","HID Input 1","01 00 00 17 12 00 00 00 00"
"0","21.424694000","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","21.425944125","HID Input 1","01 00 00 12 2C 00 00 00 00"
"0","21.514699625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","21.515949625","HID Input 1","01 00 00 2C 04 00 00 00 00"
"0","21.604709125","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","21.605959125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","21.694713500","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","21.784722750","HID Input 1","01 00 00 06 0E 00 00 00 00"
"0","21.785972625","HID Input 1","01 00 00 0E 00 00 00 00 00"
"0","21.829726625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","22.009742500","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","22.010992625","HID Input 1","01 00 00 11 12 00 00 00 00"
"0","22.054743875","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","22.144752500","HID Input 1","01 00 00 12 1A 00 00 00 00"
"0","22.146002500","HID Input 1","01 00 00 1A 00 00 00 00 00"
"0","22.189756125","HID Input 1","01 00 00 1A 08 00 00 00 00"
"0","22.191006125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","22.234757000","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","22.414772750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","22.416022875","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","22.549782750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","23.269841500","HID Input 1","01 00 00 0A 00 00 00 00 00"
"0","23.359849625","HID Input 1","01 00 00 0A 08 00 00 00 00"
"0","23.404853625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","23.494860375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","23.629872625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","23.764884000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","23.809888500","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","23.899893375","HID Input 1","01 00 00 17 0B 00 00 00 00"
"0","23.901143375","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","23.944895500","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","23.989898500","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","24.034901500","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","24.036151500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","24.079906625","HID Input 1","01 00 00 2C 15 00 00 00 00"
"0","24.169913375","HID Input 1","01 00 00 2C 15 08 00 00 00"
"0","24.171163250","HID Input 1","01 00 00 2C 08 00 00 00 00"
"0","24.214916375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","24.216166375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","24.259920750","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","24.394933000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","24.439935000","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","24.574946625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","24.619951625","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","24.754963125","HID Input 1","01 00 00 13 17 00 00 00 00"
"0","24.756213125","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","24.844968875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","24.979979750","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","25.024984125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","25.610031625","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","25.700039125","HID Input 1","01 00 00 12 09 00 00 00 00"
"0","25.745042375","HID Input 1","01 00 00 09 00 00 00 00 00"
"0","25.790047750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","25.880054250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","26.015066000","HID Input 1","01 00 00 2C 07 00 00 00 00"
"0","26.016316000","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","26.105073000","HID Input 1","01 00 00 07 04 00 00 00 00"
"0","26.150076625","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","26.240083250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","26.330091750","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","26.375095000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","26.465100250","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","26.555108125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","26.600111000","HID Input 1","01 00 00 37 00 00 00 00 00"
"0","26.690120000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","26.735123625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","26.825130625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","26.915137500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","26.960140750","HID Input 1","01 02 00 2C 00 00 00 00 00"
"0","27.005146375","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","27.095152500","HID Input 1","01 02 00 0C 00 00 00 00 00"
"0","27.140156250","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","27.185160250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","27.230164000","HID Input 1","01 00 00 09 00 00 00 00 00"
"0","27.275166750","HID Input 1","01 00 00 09 2C 00 00 00 00"
"0","27.276416875","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","27.365174625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","27.366424625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","27.410178500","HID Input 1","01 00 00 17 0B 00 00 00 00"
"0","27.455182125","HID Input 1","01 00 00 17 0B 08 00 00 00"
"0","27.456432125","HID Input 1","01 00 00 08 0B 00 00 00 00"
"0","27.500184375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","27.545187375","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","27.546437375","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","27.635196750","HID Input 1","01 00 00 2C 04 00 00 00 00"
"0","27.680197375","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","27.725198625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","27.815207125","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","27.860210750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","27.950218375","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","28.040226500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","28.085229750","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","28.220240875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","28.221490750","HID Input 1","01 00 00 0E 00 00 00 00 00"
"0","28.400254625","HID Input 1","01 00 00 0E 08 00 00 00 00"
"0","28.445259750","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","28.446509750","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","28.535264375","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","28.536514250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","28.580269250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","28.715280625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","28.716530750","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","28.805287875","HID Input 137","89 CA 52 04 12 00 00 00 00"
"0","28.850291125","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","28.851541125","HID Input 1","01 00 00 12 18 00 00 00 00"
"0","28.895294250","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","28.985298125","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","29.030302250","HID Input 1","01 00 00 0F 07 00 00 00 00"
"0","29.120309375","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","29.121559375","HID Input 1","01 00 00 07 2C 00 00 00 00"
"0","29.165310625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","29.210314625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","29.211564625","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","29.256569625","HID Input 1","01 00 00 13 15 00 00 00 00"
"0","29.300324125","HID Input 1","01 00 00 13 15 08 00 00 00"
"0","29.345327500","HID Input 1","01 00 00 13 08 00 00 00 00"
"0","29.390330125","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","29.391580000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","29.480336875","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","29.525340750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","29.570344125","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","29.615347125","HID Input 1","01 00 00 0C 06 00 00 00 00"
"0","29.705355375","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","29.706605375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","29.795362750","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","29.885371250","HID Input 1","01 00 00 17 2C 00 00 00 00"
"0","29.886621250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","29.975376500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","30.021631000","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","30.065381000","HID Input 1","01 00 00 17 0B 00 00 00 00"
"0","30.066631000","HID Input 1","01 00 00 17 0B 08 00 00 00"
"0","30.110383625","HID Input 1","01 00 00 08 0B 00 00 00 00"
"0","30.111633625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","30.155388250","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","30.156638250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","30.290395125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","30.650425125","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","30.740433125","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","30.741683125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","30.830439500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","30.875442375","HID Input 1","01 00 00 14 00 00 00 00 00"
"0","30.965450250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","30.966700250","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","31.055458375","HID Input 1","01 00 00 18 08 00 00 00 00"
"0","31.056708375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","31.100461875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","31.190469125","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","31.235472500","HID Input 1","01 00 00 11 06 00 00 00 00"
"0","31.236722375","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","31.280477250","HID Input 1","01 00 00 06 08 00 00 00 00"
"0","31.325481000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","31.326731000","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","31.370482500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","31.460490375","HID Input 1","01 00 00 2C 11 00 00 00 00"
"0","31.461740375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","31.550493750","HID Input 1","01 00 00 11 18 00 00 00 00"
"0","31.595498000","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","31.640501250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","31.685504375","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","31.820516875","HID Input 1","01 00 00 10 05 00 00 00 00"
"0","31.865519750","HID Input 1","01 00 00 05 00 00 00 00 00"
"0","31.866769750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","31.955528625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","32.000532625","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","32.090540250","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","32.091790000","HID Input 1","01 00 00 15 2C 00 00 00 00"
"0","32.135542000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","32.180545000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","32.225548750","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","32.270553125","HID Input 1","01 00 00 12 09 00 00 00 00"
"0","32.315557250","HID Input 1","01 00 00 12 09 2C 00 00 00"
"0","32.360559375","HID Input 1","01 00 00 12 2C 00 00 00 00"
"0","32.361809375","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","32.450569375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","32.451819250","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","32.495570750","HID Input 1","01 00 00 17 0B 00 00 00 00"
"0","32.540573375","HID Input 1","01 00 00 17 0B 08 00 00 00"
"0","32.541823375","HID Input 1","01 00 00 08 0B 00 00 00 00"
"0","32.585578375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","32.586828500","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","32.630580250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","32.675584750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","32.765592000","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","32.810591375","HID Input 1","01 00 00 13 04 00 00 00 00"
"0","32.900599250","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","32.901849250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","32.945604375","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","32.990608125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","33.035611125","HID Input 1","01 00 00 0E 00 00 00 00 00"
"0","33.125619250","HID Input 1","01 00 00 0E 08 00 00 00 00"
"0","33.170623500","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","33.171873500","HID Input 1","01 00 00 08 17 00 00 00 00"
"0","33.215623875","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","33.260627625","HID Input 1","01 00 00 17 2C 00 00 00 00"
"0","33.261877625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","33.395640500","HID Input 1","01 00 00 2C 05 00 00 00 00"
"0","33.396890500","HID Input 1","01 00 00 05 00 00 00 00 00"
"0","33.440643625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","33.485647375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","33.575654500","HID Input 1","01 00 00 08 0C 00 00 00 00"
"0","33.576904375","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","33.620658000","HID Input 1","01 00 00 0C 11 00 00 00 00"
"0","33.665661500","HID Input 1","01 00 00 0C 11 0A 00 00 00"
"0","33.666911500","HID Input 1","01 00 00 0A 11 00 00 00 00"
"0","33.755668250","HID Input 1","01 00 00 0A 00 00 00 00 00"
"0","33.756918125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","33.800673125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","33.845676250","HID Input 1","01 00 00 2C 16 00 00 00 00"
"0","33.890680625","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","33.935684125","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","33.980687375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","34.025691500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","34.026941500","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","34.115695000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","34.116945000","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","34.205701875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","34.206951875","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","34.295709250","HID Input 1","01 00 00 2C 09 00 00 00 00"
"0","34.340712875","HID Input 1","01 00 00 09 00 00 00 00 00"
"0","34.385717250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","34.430721000","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","34.520728875","HID Input 1","01 00 00 15 12 00 00 00 00"
"0","34.521978750","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","34.565731750","HID Input 1","01 00 00 12 10 00 00 00 00"
"0","34.610734500","HID Input 1","01 00 00 12 10 2C 00 00 00"
"0","34.700742750","HID Input 1","01 00 00 12 2C 00 00 00 00"
"0","34.701992750","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","34.745747375","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","34.746997375","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","34.790748375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","34.791998250","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","34.835752125","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","34.925760250","HID Input 1","01 00 00 0B 08 2C 00 00 00"
"0","34.927010125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","35.060771625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.062021500","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","35.105775000","HID Input 1","01 00 00 00 70 20 06 2C 00"
"0","35.195782250","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","35.285790375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.330794375","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","35.375792625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.465801500","HID Input 1","01 00 00 0A 00 00 00 00 00"
"0","35.555808750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.600812000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","35.645815375","HID Input 1","01 00 00 08 17 00 00 00 00"
"0","35.690818625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","35.735823875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.737074000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","35.825830875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.870835125","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","35.915839250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","35.960841500","HID Input 1","01 00 00 1C 00 00 00 00 00"
"0","36.005846000","HID Input 1","01 00 00 1C 16 00 00 00 00"
"0","36.050850500","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","36.095853625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","36.140856625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","36.230864750","HID Input 1","01 00 00 17 08 00 00 00 00"
"0","36.232114750","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","36.275867250","HID Input 1","01 00 00 08 10 00 00 00 00"
"0","36.320869875","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","36.365874125","HID Input 1","01 00 00 10 2C 00 00 00 00"
"0","36.410877625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","36.500885125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","36.502135125","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","36.545889500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","36.590893875","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","36.635894625","HID Input 1","01 00 00 12 2C 00 00 00 00"
"0","36.680895625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","36.682145625","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","36.725899500","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","36.770904625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","36.815908250","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","36.860910750","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","36.905914625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","36.907164500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","36.950917500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","36.995921250","HID Input 1","01 00 00 2C 15 00 00 00 00"
"0","37.040924750","HID Input 1","01 00 00 2C 15 08 00 00 00"
"0","37.085929000","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","37.087179000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","37.130933125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","37.220940750","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","37.265944250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","37.310947000","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","37.355951750","HID Input 1","01 00 00 0F 2C 00 00 00 00"
"0","37.445958625","HID Input 1","01 00 00 0F 2C 16 00 00 00"
"0","37.447208625","HID Input 1","01 00 00 16 2C 00 00 00 00"
"0","37.490961375","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","37.535965375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","37.580968750","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","37.625971750","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","37.670975375","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","37.672225500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","37.760984625","HID Input 1","01 00 00 19 00 00 00 00 00"
"0","37.805989000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","37.850992125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","37.940995250","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","37.985997750","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","37.987247625","HID Input 1","01 00 00 15 2C 00 00 00 00"
"0","38.031002125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","38.121009750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","38.122259750","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","38.166013250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","38.167263250","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","38.256020625","HID Input 1","01 00 00 18 15 00 00 00 00"
"0","38.302274625","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","38.346028500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","38.391031375","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","38.436035125","HID Input 1","01 00 00 0C 11 00 00 00 00"
"0","38.481040125","HID Input 1","01 00 00 0C 11 0A 00 00 00"
"0","38.482290125","HID Input 1","01 00 00 0C 11 0A 2C 00 00"
"0","38.526041625","HID Input 1","01 00 00 0C 11 2C 00 00 00"
"0","38.527291500","HID Input 1","01 00 00 2C 11 00 00 00 00"
"0","38.571045500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","38.616049125","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","38.617299125","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","38.661052375","HID Input 1","01 00 00 17 0B 00 00 00 00"
"0","38.706055375","HID Input 1","01 00 00 17 0B 08 00 00 00"
"0","38.707306500","HID Input 1","01 00 00 08 0B 00 00 00 00"
"0","38.751058750","HID Input 1","01 00 00 08 0B 2C 00 00 00"
"0","38.796062750","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","38.797312875","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","38.886069250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","38.931073625","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","38.976077250","HID Input 1","01 00 00 0C 11 00 00 00 00"
"0","39.066085000","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","39.156092000","HID Input 1","01 00 00 11 0C 00 00 00 00"
"0","39.157342000","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","39.246096250","HID Input 1","01 00 00 0C 17 00 00 00 00"
"0","39.247346125","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","39.291099375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","39.336103000","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","39.426111000","HID Input 1","01 00 00 0C 04 00 00 00 00"
"0","39.427361000","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","39.516119250","HID Input 1","01 00 00 04 0F 00 00 00 00"
"0","39.517369250","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","39.606125250","HID Input 1","01 00 00 0F 2C 00 00 00 00"
"0","39.607375250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","39.651128500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","39.741136750","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","39.831143875","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","39.876147375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","39.921152375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","39.966155750","HID Input 1","01 00 00 11 07 00 00 00 00"
"0","40.056163750","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","40.057413750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","40.146169625","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","40.236177500","HID Input 1","01 00 00 16 0B 00 00 00 00"
"0","40.237427500","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","40.327434250","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","40.461194250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","40.506195750","HID Input 1","01 00 00 0E 00 00 00 00 00"
"0","40.597453125","HID Input 1","01 00 00 0E 08 00 00 00 00"
"0","40.641202375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","40.731211125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","40.866222125","HID Input 1","01 00 00 36 00 00 00 00 00"
"0","40.956230125","HID Input 1","01 00 00 36 2C 00 00 00 00"
"0","41.001234000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","41.091241000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","41.226251750","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","41.316260625","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","41.317510625","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","41.361262875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","41.406265375","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","41.496272500","HID Input 1","01 00 00 2C 06 00 00 00 00"
"0","41.497522625","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","41.541277000","HID Input 1","01 00 00 06 12 00 00 00 00"
"0","41.586280625","HID Input 1","01 00 00 06 12 18 00 00 00"
"0","41.587530750","HID Input 1","01 00 00 18 12 00 00 00 00"
"0","41.631283125","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","41.721291500","HID Input 1","01 00 00 18 0F 00 00 00 00"
"0","41.722541500","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","41.766292625","HID Input 1","01 00 00 0F 07 00 00 00 00"
"0","41.811293250","HID Input 1","01 00 00 0F 07 2C 00 00 00"
"0","41.812543250","HID Input 1","01 00 00 0F 2C 00 00 00 00"
"0","41.856297750","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","41.946305125","HID Input 1","01 00 00 2C 06 00 00 00 00"
"0","41.947555125","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","42.037562000","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","42.081317000","HID Input 1","01 00 00 12 10 00 00 00 00"
"0","42.171324125","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","42.216328625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","42.261330625","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","42.351339750","HID Input 1","01 00 00 13 0F 00 00 00 00"
"0","42.396343375","HID Input 1","01 00 00 13 0F 08 00 00 00"
"0","42.441346125","HID Input 1","01 00 00 08 0F 00 00 00 00"
"0","42.486349500","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","42.487599500","HID Input 1","01 00 00 08 17 00 00 00 00"
"0","42.531352875","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","42.576356000","HID Input 1","01 00 00 17 08 00 00 00 00"
"0","42.621359000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","42.666363000","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","42.711367125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","42.756371250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","42.757621250","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","42.801376000","HID Input 1","01 00 00 17 0B 00 00 00 00"
"0","42.891383500","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","42.892633500","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","42.936384375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","42.937634250","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","42.981389000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","43.071391375","HID Input 1","01 00 00 2C 13 00 00 00 00"
"0","43.072641375","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","43.161397250","HID Input 1","01 00 00 13 15 00 00 00 00"
"0","43.162647250","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","43.206403125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","43.251407000","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","43.296409250","HID Input 1","01 00 00 12 06 00 00 00 00"
"0","43.386418125","HID Input 1","01 00 00 01 01 01 01 01 01"
"0","43.521429125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","43.522679000","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","43.611434875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","43.701442750","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","43.746447250","HID Input 1","01 00 00 16 2C 00 00 00 00"
"0","43.791449250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","43.881458500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","43.926462125","HID Input 1","01 00 00 05 00 00 00 00 00"
"0","43.971464750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","43.972714875","HID Input 1","01 00 00 1C 00 00 00 00 00"
"0","44.061472625","HID Input 1","01 00 00 1C 2C 00 00 00 00"
"0","44.106478000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","44.151481875","HID Input 1","01 00 00 2C 16 00 00 00 00"
"0","44.197735250","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","44.241489250","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","44.242739250","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","44.286490000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","44.331490375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","44.376494750","HID Input 1","01 00 00 11 07 00 00 00 00"
"0","44.421498625","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","44.466501000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","44.511505000","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","44.556509375","HID Input 1","01 00 00 0C 11 00 00 00 00"
"0","44.646516375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","44.691520375","HID Input 1","01 00 00 11 0A 00 00 00 00"
"0","44.692770500","HID Input 1","01 00 00 0A 00 00 00 00 00"
"0","44.736524875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","44.826532500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","44.961543750","HID Input 1","01 00 00 2C 04 00 00 00 00"
"0","44.962793625","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","45.096553625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","45.097803625","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","45.186561250","HID Input 1","01 00 00 11 2C 00 00 00 00"
"0","45.231566000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","45.232815875","HID Input 1","01 00 00 2C 04 00 00 00 00"
"0","45.276568500","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","45.321572375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","45.411580125","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","45.501587625","HID Input 1","01 00 00 06 0E 00 00 00 00"
"0","45.502837625","HID Input 1","01 00 00 0E 00 00 00 00 00"
"0","45.546591000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","45.681598375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","45.771605625","HID Input 1","01 00 00 11 12 00 00 00 00"
"0","45.816608750","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","45.861612250","HID Input 1","01 00 00 1A 00 00 00 00 00"
"0","45.951621250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","45.996624125","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","46.041626750","HID Input 1","01 00 00 0F 08 00 00 00 00"
"0","46.086630500","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","46.131635875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","46.176639250","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","46.266646625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","46.356654375","HID Input 1","01 00 00 0A 00 00 00 00 00"
"0","46.446661000","HID Input 1","01 00 00 0A 08 00 00 00 00"
"0","46.491665000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","46.536668125","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","46.581671750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","46.626677000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","46.716683375","HID Input 1","01 00 00 08 11 00 00 00 00"
"0","46.717933375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","46.806691875","HID Input 1","01 00 00 11 17 00 00 00 00"
"0","46.807942000","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","46.896693500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","46.941697625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","47.031705000","HID Input 1","01 00 00 2C 13 00 00 00 00"
"0","47.032955125","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","47.121712625","HID Input 1","01 00 00 13 04 00 00 00 00"
"0","47.211720625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","47.257972500","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","47.346731500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","47.347981500","HID Input 1","01 00 00 0E 00 00 00 00 00"
"0","47.481743250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","47.482993250","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","47.526745000","HID Input 1","01 00 00 08 17 00 00 00 00"
"0","47.571747750","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","47.616752750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","47.618002625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","47.751763625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","47.753013625","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","47.841771250","HID Input 1","01 02 00 25 00 00 00 00 00"
"0","47.976783000","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","48.246801750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","48.606832750","HID Input 1","01 00 00 2A 00 00 00 00 00"
"0","48.786848750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","48.876855500","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","49.011866500","HID Input 1","01 02 00 26 00 00 00 00 00"
"0","49.146879125","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","49.236886750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","49.371897125","HID Input 1","01 00 00 1A 00 00 00 00 00"
"0","49.461902125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","49.506905750","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","49.551908500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","49.596913250","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","49.641917250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","49.686919375","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","49.731923125","HID Input 1","01 00 00 0B 2C 00 00 00 00"
"0","49.821930625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","49.823180750","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","49.866936000","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","49.911939750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","49.913189750","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","49.956941750","HID Input 1","01 00 00 0B 08 00 00 00 00"
"0","50.001945000","HID Input 1","01 00 00 0B 08 2C 00 00 00"
"0","50.003194750","HID Input 1","01 00 00 2C 08 00 00 00 00"
"0","50.046949875","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","50.136957125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","50.183211125","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","50.226962625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","50.271965625","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","50.361975125","HID Input 1","01 00 00 12 15 00 00 00 00"
"0","50.406978625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","50.541989125","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","50.543239125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","50.631998250","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","50.677001500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","50.767003000","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","50.857010125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","50.948268375","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","51.037021125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","51.038271125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","51.172032125","HID Input 1","01 00 00 2C 16 00 00 00 00"
"0","51.217036750","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","51.218286625","HID Input 1","01 00 00 16 08 00 00 00 00"
"0","51.262039000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","51.352046625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","51.397049375","HID Input 1","01 00 00 14 00 00 00 00 00"
"0","51.487058500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","51.532061875","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","51.577066000","HID Input 1","01 00 00 18 08 00 00 00 00"
"0","51.622069125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","51.667073000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","51.712076250","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","51.802084625","HID Input 1","01 00 00 11 06 00 00 00 00"
"0","51.847088000","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","51.892091125","HID Input 1","01 00 00 06 08 00 00 00 00"
"0","51.893341250","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","51.982098250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","51.983348375","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","52.072100750","HID Input 1","01 00 00 2C 11 00 00 00 00"
"0","52.117105250","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","52.162109125","HID Input 1","01 00 00 11 18 00 00 00 00"
"0","52.207111750","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","52.252116125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","52.342123375","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","52.432130625","HID Input 1","01 00 00 10 05 00 00 00 00"
"0","52.477135375","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","52.478385250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","52.567143250","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","52.612147125","HID Input 1","01 00 00 08 15 00 00 00 00"
"0","52.657151250","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","52.747158125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","52.837166000","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","53.467215875","HID Input 1","01 02 00 26 00 00 00 00 00"
"0","53.468465875","HID Input 1","01 02 00 26 27 00 00 00 00"
"0","53.512220250","HID Input 1","01 02 00 26 00 00 00 00 00"
"0","53.557222375","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","53.872250500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","54.007262250","HID Input 1","01 00 00 2A 00 00 00 00 00"
"0","54.142273375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","54.277285625","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","54.457299750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","54.502303750","HID Input 1","01 00 00 2A 00 00 00 00 00"
"0","54.637311625","HID Input 1","01 02 00 2A 00 00 00 00 00"
"0","54.638561625","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","54.773573375","HID Input 1","01 02 00 27 00 00 00 00 00"
"0","54.862331375","HID Input 1","01 02 00 00 00 00 00 00 00"
"0","55.042347000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","55.222360250","HID Input 1","01 00 00 36 00 00 00 00 00"
"0","55.312369125","HID Input 1","01 00 00 36 2C 00 00 00 00"
"0","55.402376500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","55.492384125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","55.493634125","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","55.582389375","HID Input 1","01 00 00 04 11 00 00 00 00"
"0","55.627393375","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","55.672398250","HID Input 1","01 00 00 11 07 00 00 00 00"
"0","55.673648250","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","55.762406250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","55.763656000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","55.942415000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","55.943665000","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","55.987417000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","56.077425250","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","56.167432250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","56.302444625","HID Unknown",""
"0","56.392451875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","56.437456375","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","56.527463625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","56.662474625","HID Input 1","01 00 00 05 00 00 00 00 00"
"0","56.707480000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","56.708729875","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","56.797485375","HID Input 1","01 00 00 0F 0C 00 00 00 00"
"0","56.842489625","HID Input 1","01 00 00 0F 00 00 00 00 00"
"0","56.887493250","HID Input 1","01 00 00 0F 16 00 00 00 00"
"0","56.888743250","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","56.977502000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","57.022503625","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","57.067507500","HID Input 1","01 00 00 0B 2C 00 00 00 00"
"0","57.112511500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","57.157510875","HID Input 1","01 00 00 2C 04 00 00 00 00"
"0","57.158760750","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","57.247519000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","57.292522125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","57.382531000","HID Input 1","01 00 00 2C 06 00 00 00 00"
"0","57.517541500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","57.518791500","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","57.607548750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","57.652552250","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","57.742559750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","57.832567250","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","57.877572375","HID Input 1","01 00 00 11 08 00 00 00 00"
"0","57.922575875","HID Input 1","01 00 00 11 00 00 00 00 00"
"0","57.967580250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","58.012583250","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","58.102590750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","58.192599000","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","58.282606625","HID Input 1","01 00 00 17 0C 00 00 00 00"
"0","58.327609125","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","58.372612500","HID Input 1","01 00 00 0C 12 00 00 00 00"
"0","58.373862500","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","58.462618125","HID Input 1","01 00 00 12 11 00 00 00 00"
"0","58.507622375","HID Input 1","01 00 00 12 11 2C 00 00 00"
"0","58.508872375","HID Input 1","01 00 00 2C 11 00 00 00 00"
"0","58.552624250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","58.597627500","HID Input 1","01 00 00 2C 04 00 00 00 00"
"0","58.642631250","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","58.687634750","HID Input 1","01 00 00 04 13 00 00 00 00"
"0","58.688884625","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","58.732638750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","58.822646125","HID Input 1","01 00 00 13 00 00 00 00 00"
"0","58.912654125","HID Input 1","01 00 00 13 08 00 00 00 00"
"0","59.002661500","HID Input 1","01 00 00 13 08 04 00 00 00"
"0","59.003911500","HID Input 1","01 00 00 13 04 00 00 00 00"
"0","59.047665000","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","59.092668625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","59.137671250","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","59.227679750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","59.272683500","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","59.407694500","HID Input 1","01 00 00 0C 11 0A 00 00 00"
"0","59.452698250","HID Input 1","01 00 00 0A 11 00 00 00 00"
"0","59.453948250","HID Input 1","01 00 00 0A 00 00 00 00 00"
"0","59.497703125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","59.498953125","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","59.632713000","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","59.633963000","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","59.722715250","HID Input 1","01 00 00 17 12 00 00 00 00"
"0","59.723965250","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","59.767718375","HID Input 1","01 00 00 12 2C 00 00 00 00"
"0","59.857727375","HID Input 1","01 00 00 12 2C 05 00 00 00"
"0","59.902730250","HID Input 1","01 00 00 05 2C 00 00 00 00"
"0","59.903980250","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","59.947732125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","59.992735500","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","60.037739000","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","60.082743625","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","60.172751000","HID Input 1","01 00 00 2C 09 00 00 00 00"
"0","60.174001000","HID Input 1","01 00 00 09 00 00 00 00 00"
"0","60.262759500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","60.307763625","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","60.397771000","HID Input 1","01 00 00 15 12 00 00 00 00"
"0","60.399021000","HID Input 1","01 00 00 12 00 00 00 00 00"
"0","60.442772250","HID Input 1","01 00 00 12 10 00 00 00 00"
"0","60.487776000","HID Input 1","01 00 00 12 10 2C 00 00 00"
"0","60.577784000","HID Input 1","01 00 00 12 2C 00 00 00 00"
"0","60.579033875","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","60.622788500","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","60.624038625","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","60.667791250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","60.712794375","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","60.714044500","HID Input 1","01 00 00 08 0B 00 00 00 00"
"0","60.802801875","HID Input 1","01 00 00 08 0B 2C 00 00 00"
"0","60.804052000","HID Input 1","01 00 00 08 2C 00 00 00 00"
"0","60.847804000","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","60.937812125","HID Input 1","01 00 00 2C 17 00 00 00 00"
"0","60.939062375","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","60.982813125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","61.072820000","HID Input 1","01 00 00 15 00 00 00 00 00"
"0","61.162828125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","61.207832375","HID Input 1","01 00 00 18 00 00 00 00 00"
"0","61.252834500","HID Input 1","01 00 00 18 16 00 00 00 00"
"0","61.344092625","HID Input 1","01 00 00 16 00 00 00 00 00"
"0","61.387843500","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","61.432846875","HID Input 1","01 00 00 17 00 00 00 00 00"
"0","61.522854875","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","61.567857750","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","61.657865625","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","61.702869375","HID Input 1","01 00 00 07 00 00 00 00 00"
"0","61.837880125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","62.332919500","HID Input 1","01 00 00 2C 00 00 00 00 00"
"0","62.422927500","HID Input 1","01 00 00 2C 10 00 00 00 00"
"0","62.424177500","HID Input 1","01 00 00 10 00 00 00 00 00"
"0","62.557937875","HID Input 1","01 00 00 10 04 00 00 00 00"
"0","62.602940875","HID Input 1","01 00 00 04 00 00 00 00 00"
"0","62.604190750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","62.692948750","HID Input 1","01 00 00 06 00 00 00 00 00"
"0","62.737952750","HID Input 1","01 00 00 06 0B 00 00 00 00"
"0","62.782957500","HID Input 1","01 00 00 0B 00 00 00 00 00"
"0","62.872964375","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","62.874214250","HID Input 1","01 00 00 0C 00 00 00 00 00"
"0","62.962971250","HID Input 1","01 00 00 0C 11 00 00 00 00"
"0","63.007974750","HID Input 1","01 00 00 0C 11 08 00 00 00"
"0","63.052978125","HID Input 1","01 00 00 08 11 00 00 00 00"
"0","63.054228125","HID Input 1","01 00 00 08 00 00 00 00 00"
"0","63.097981750","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","63.187990000","HID Input 1","01 00 00 37 00 00 00 00 00"
"0","63.323001250","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","63.593020125","HID Input 1","01 00 00 28 00 00 00 00 00"
"0","63.683028125","HID Input 1","01 00 00 00 00 00 00 00 00"
"0","63.773035125","HID Input 1","01 00 00 28 00 00 00 00 00"
"0","63.818038625","HID Input 1","01 00 00 00 00 00 00 00 00"
1 Depth Time Name Data
2 0 7.248613000 HID Input 1 01 00 00 00 00 00 00 00 00
3 0 7.249863000 HID Input 1 01 00 00 28 00 00 00 00 00
4 0 7.251113000 HID Input 1 01 00 00 00 00 00 00 00 00
5 0 10.646359000 HID Input 1 01 00 00 28 00 00 00 00 00
6 0 10.658858750 HID Input 1 01 00 00 00 00 00 00 00 00
7 0 10.681358750 HID Input 1 01 00 00 28 00 00 00 00 00
8 0 10.758865000 HID Input 1 01 00 00 00 00 00 00 00 00
9 0 10.893876750 HID Input 1 01 00 00 28 00 00 00 00 00
10 0 10.983884250 HID Input 1 01 00 00 00 00 00 00 00 00
11 0 12.558997750 HID Input 1 01 02 00 00 00 00 00 00 00
12 0 13.009032500 HID Input 1 01 02 00 08 00 00 00 00 00
13 0 13.144044625 HID Input 1 01 00 00 08 00 00 00 00 00
14 0 13.189048625 HID Input 1 01 00 00 00 00 00 00 00 00
15 0 13.324059500 HID Input 1 01 00 00 11 00 00 00 00 00
16 0 13.414067500 HID Input 1 01 00 00 11 17 00 00 00 00
17 0 13.459070500 HID Input 1 01 00 00 17 00 00 00 00 00
18 0 13.504074375 HID Input 1 01 00 00 00 00 00 00 00 00
19 0 13.549077875 HID Input 1 01 00 00 08 00 00 00 00 00
20 0 13.594078750 HID Input 1 01 00 00 08 15 00 00 00 00
21 0 13.684083375 HID Input 1 01 00 00 15 00 00 00 00 00
22 0 13.729087500 HID Input 1 01 00 00 00 00 00 00 00 00
23 0 13.774091625 HID Input 1 01 00 00 2C 00 00 00 00 00
24 0 13.864099125 HID Input 1 01 00 00 2C 17 00 00 00 00
25 0 13.865349125 HID Input 1 01 00 00 17 00 00 00 00 00
26 0 13.954107375 HID Input 1 01 00 00 00 00 00 00 00 00
27 0 13.955357375 HID Input 1 01 00 00 0B 00 00 00 00 00
28 0 13.999108000 HID Input 1 01 00 00 0B 08 00 00 00 00
29 0 14.044112125 HID Input 1 01 00 00 08 00 00 00 00 00
30 0 14.089117000 HID Input 1 01 00 00 00 00 00 00 00 00
31 0 14.134119250 HID Input 1 01 00 00 2C 00 00 00 00 00
32 0 14.269131375 HID Input 1 01 00 00 00 00 00 00 00 00
33 0 14.270381375 HID Input 1 01 02 00 00 00 00 00 00 00
34 0 14.404141250 HID Input 1 01 02 00 17 00 00 00 00 00
35 0 14.449145125 HID Input 1 01 02 00 00 00 00 00 00 00
36 0 14.584155625 HID Input 1 01 02 00 06 00 00 00 00 00
37 0 14.674164250 HID Input 1 01 02 00 00 00 00 00 00 00
38 0 14.675414250 HID Input 1 01 02 00 13 00 00 00 00 00
39 0 14.809176000 HID Input 1 01 02 00 00 00 00 00 00 00
40 0 14.854179250 HID Input 1 01 00 00 00 00 00 00 00 00
41 0 14.855429250 HID Input 1 01 00 00 2C 00 00 00 00 00
42 0 14.944184000 HID Input 1 01 00 00 2C 16 00 00 00 00
43 0 14.989186250 HID Input 1 01 00 00 16 00 00 00 00 00
44 0 15.034189500 HID Input 1 01 00 00 16 08 00 00 00 00
45 0 15.079194375 HID Input 1 01 00 00 08 00 00 00 00 00
46 0 15.169201125 HID Input 1 01 00 00 00 00 00 00 00 00
47 0 15.214205250 HID Input 1 01 00 00 14 00 00 00 00 00
48 0 15.349217625 HID Input 1 01 00 00 00 00 00 00 00 00
49 0 15.350467625 HID Input 1 01 00 00 18 00 00 00 00 00
50 0 15.394222125 HID Input 1 01 00 00 18 08 00 00 00 00
51 0 15.439224500 HID Input 1 01 00 00 08 00 00 00 00 00
52 0 15.484228000 HID Input 1 01 00 00 00 00 00 00 00 00
53 0 15.619238750 HID Input 1 01 00 00 11 06 00 00 00 00
54 0 15.620488750 HID Input 1 01 00 00 06 00 00 00 00 00
55 0 15.709246125 HID Input 1 01 00 00 06 08 00 00 00 00
56 0 15.710496125 HID Input 1 01 00 00 08 00 00 00 00 00
57 0 15.754250625 HID Input 1 01 00 00 08 2C 00 00 00 00
58 0 15.799253375 HID Input 1 01 00 00 2C 00 00 00 00 00
59 0 15.844256875 HID Input 1 01 00 00 2C 11 00 00 00 00
60 0 15.889262250 HID Input 1 01 00 00 11 00 00 00 00 00
61 0 15.934265375 HID Input 1 01 00 00 11 18 00 00 00 00
62 0 15.979269125 HID Input 1 01 00 00 18 00 00 00 00 00
63 0 16.024272875 HID Input 1 01 00 00 00 00 00 00 00 00
64 0 16.114280375 HID Input 1 01 00 00 10 00 00 00 00 00
65 0 16.249286750 HID Input 1 01 00 00 10 05 00 00 00 00
66 0 16.294289875 HID Input 1 01 00 00 05 00 00 00 00 00
67 0 16.295540000 HID Input 1 01 00 00 00 00 00 00 00 00
68 0 16.384296125 HID Input 1 01 00 00 08 00 00 00 00 00
69 0 16.474304000 HID Input 1 01 00 00 08 15 00 00 00 00
70 0 16.519306375 HID Input 1 01 00 00 15 00 00 00 00 00
71 0 16.564310750 HID Input 1 01 00 00 00 00 00 00 00 00
72 0 16.834333625 HID Input 1 01 20 00 00 00 00 00 00 00
73 0 16.924341375 HID Input 1 01 20 00 33 00 00 00 00 00
74 0 17.014348625 HID Input 1 01 00 00 33 00 00 00 00 00
75 0 17.059353250 HID Input 1 01 00 00 00 00 00 00 00 00
76 0 17.194365625 HID Input 1 01 00 00 2C 00 00 00 00 00
77 0 17.329375625 HID Input 1 01 00 00 00 00 00 00 00 00
78 0 17.330625625 HID Input 1 01 00 00 17 00 00 00 00 00
79 0 17.419381000 HID Input 1 01 00 00 00 00 00 00 00 00
80 0 17.420631000 HID Input 1 01 00 00 0B 00 00 00 00 00
81 0 17.509384500 HID Input 1 01 00 00 0B 08 00 00 00 00
82 0 17.510634375 HID Input 1 01 00 00 08 00 00 00 00 00
83 0 17.554388500 HID Input 1 01 00 00 08 2C 00 00 00 00
84 0 17.599393125 HID Input 1 01 00 00 2C 00 00 00 00 00
85 0 17.689399750 HID Input 1 01 00 00 00 00 00 00 00 00
86 0 17.734403750 HID Input 1 01 00 00 13 00 00 00 00 00
87 0 17.869416125 HID Input 1 01 00 00 00 00 00 00 00 00
88 0 17.870666125 HID Input 1 01 00 00 15 00 00 00 00 00
89 0 17.959421875 HID Input 1 01 00 00 00 00 00 00 00 00
90 0 18.004424875 HID Input 1 01 00 00 12 00 00 00 00 00
91 0 18.184440500 HID Input 1 01 00 00 00 00 00 00 00 00
92 0 18.185690625 HID Input 1 01 00 00 17 00 00 00 00 00
93 0 18.274448625 HID Input 1 01 00 00 00 00 00 00 00 00
94 0 18.319453375 HID Input 1 01 00 00 12 00 00 00 00 00
95 0 18.409461000 HID Input 1 01 00 00 00 00 00 00 00 00
96 0 18.454464375 HID Input 1 01 00 00 06 00 00 00 00 00
97 0 18.544471500 HID Input 1 01 00 00 06 12 00 00 00 00
98 0 18.545721500 HID Input 1 01 00 00 12 00 00 00 00 00
99 0 18.634478875 HID Input 1 01 00 00 00 00 00 00 00 00
100 0 18.724483000 HID Input 1 01 00 00 0F 00 00 00 00 00
101 0 18.814490375 HID Input 1 01 00 00 0F 2C 00 00 00 00
102 0 18.859493750 HID Input 1 01 00 00 2C 00 00 00 00 00
103 0 18.949501375 HID Input 1 01 00 00 00 00 00 00 00 00
104 0 18.994505500 HID Input 1 01 00 00 18 00 00 00 00 00
105 0 19.129516125 HID Input 1 01 00 00 18 16 00 00 00 00
106 0 19.130766250 HID Input 1 01 00 00 16 00 00 00 00 00
107 0 19.219524125 HID Input 1 01 00 00 16 08 00 00 00 00
108 0 19.220773875 HID Input 1 01 00 00 08 00 00 00 00 00
109 0 19.309531000 HID Input 1 01 00 00 00 00 00 00 00 00
110 0 19.354534125 HID Input 1 01 00 00 16 00 00 00 00 00
111 0 19.444542000 HID Input 1 01 00 00 16 2C 00 00 00 00
112 0 19.445792000 HID Input 1 01 00 00 2C 00 00 00 00 00
113 0 19.579553625 HID Input 1 01 00 00 2C 16 00 00 00 00
114 0 19.580803625 HID Input 1 01 00 00 16 00 00 00 00 00
115 0 19.669561125 HID Input 1 01 00 00 16 08 00 00 00 00
116 0 19.714563625 HID Input 1 01 00 00 08 00 00 00 00 00
117 0 19.759568375 HID Input 1 01 00 00 00 00 00 00 00 00
118 0 19.850826125 HID Input 1 01 00 00 14 00 00 00 00 00
119 0 19.939581000 HID Input 1 01 00 00 00 00 00 00 00 00
120 0 19.940831125 HID Input 1 01 00 00 18 00 00 00 00 00
121 0 20.029584250 HID Input 1 01 00 00 18 08 00 00 00 00
122 0 20.074588375 HID Input 1 01 00 00 08 00 00 00 00 00
123 0 20.075838500 HID Input 1 01 00 00 00 00 00 00 00 00
124 0 20.164594500 HID Input 1 01 00 00 11 00 00 00 00 00
125 0 20.209599125 HID Input 1 01 00 00 11 06 00 00 00 00
126 0 20.254602250 HID Input 1 01 00 00 06 00 00 00 00 00
127 0 20.299605750 HID Input 1 01 00 00 08 00 00 00 00 00
128 0 20.344609375 HID Input 1 01 00 00 08 2C 00 00 00 00
129 0 20.390862750 HID Input 1 01 00 00 2C 00 00 00 00 00
130 0 20.479621250 HID Input 1 01 00 00 2C 11 00 00 00 00
131 0 20.480871250 HID Input 1 01 00 00 11 00 00 00 00 00
132 0 20.524623750 HID Input 1 01 00 00 11 18 00 00 00 00
133 0 20.569627750 HID Input 1 01 00 00 18 00 00 00 00 00
134 0 20.614630625 HID Input 1 01 00 00 00 00 00 00 00 00
135 0 20.659633750 HID Input 1 01 00 00 10 00 00 00 00 00
136 0 20.794646250 HID Input 1 01 00 00 10 05 00 00 00 00
137 0 20.839650500 HID Input 1 01 00 00 05 00 00 00 00 00
138 0 20.840900375 HID Input 1 01 00 00 00 00 00 00 00 00
139 0 20.929658125 HID Input 1 01 00 00 08 00 00 00 00 00
140 0 20.974661000 HID Input 1 01 00 00 08 15 00 00 00 00
141 0 21.019666125 HID Input 1 01 00 00 15 00 00 00 00 00
142 0 21.109672625 HID Input 1 01 00 00 00 00 00 00 00 00
143 0 21.110922625 HID Input 1 01 00 00 16 00 00 00 00 00
144 0 21.199678625 HID Input 1 01 00 00 16 2C 00 00 00 00
145 0 21.244683250 HID Input 1 01 00 00 2C 00 00 00 00 00
146 0 21.289683500 HID Input 1 01 00 00 00 00 00 00 00 00
147 0 21.334685625 HID Input 1 01 00 00 17 00 00 00 00 00
148 0 21.379689625 HID Input 1 01 00 00 17 12 00 00 00 00
149 0 21.424694000 HID Input 1 01 00 00 12 00 00 00 00 00
150 0 21.425944125 HID Input 1 01 00 00 12 2C 00 00 00 00
151 0 21.514699625 HID Input 1 01 00 00 2C 00 00 00 00 00
152 0 21.515949625 HID Input 1 01 00 00 2C 04 00 00 00 00
153 0 21.604709125 HID Input 1 01 00 00 04 00 00 00 00 00
154 0 21.605959125 HID Input 1 01 00 00 00 00 00 00 00 00
155 0 21.694713500 HID Input 1 01 00 00 06 00 00 00 00 00
156 0 21.784722750 HID Input 1 01 00 00 06 0E 00 00 00 00
157 0 21.785972625 HID Input 1 01 00 00 0E 00 00 00 00 00
158 0 21.829726625 HID Input 1 01 00 00 00 00 00 00 00 00
159 0 22.009742500 HID Input 1 01 00 00 11 00 00 00 00 00
160 0 22.010992625 HID Input 1 01 00 00 11 12 00 00 00 00
161 0 22.054743875 HID Input 1 01 00 00 12 00 00 00 00 00
162 0 22.144752500 HID Input 1 01 00 00 12 1A 00 00 00 00
163 0 22.146002500 HID Input 1 01 00 00 1A 00 00 00 00 00
164 0 22.189756125 HID Input 1 01 00 00 1A 08 00 00 00 00
165 0 22.191006125 HID Input 1 01 00 00 00 00 00 00 00 00
166 0 22.234757000 HID Input 1 01 00 00 0F 00 00 00 00 00
167 0 22.414772750 HID Input 1 01 00 00 00 00 00 00 00 00
168 0 22.416022875 HID Input 1 01 00 00 07 00 00 00 00 00
169 0 22.549782750 HID Input 1 01 00 00 00 00 00 00 00 00
170 0 23.269841500 HID Input 1 01 00 00 0A 00 00 00 00 00
171 0 23.359849625 HID Input 1 01 00 00 0A 08 00 00 00 00
172 0 23.404853625 HID Input 1 01 00 00 08 00 00 00 00 00
173 0 23.494860375 HID Input 1 01 00 00 00 00 00 00 00 00
174 0 23.629872625 HID Input 1 01 00 00 2C 00 00 00 00 00
175 0 23.764884000 HID Input 1 01 00 00 00 00 00 00 00 00
176 0 23.809888500 HID Input 1 01 00 00 17 00 00 00 00 00
177 0 23.899893375 HID Input 1 01 00 00 17 0B 00 00 00 00
178 0 23.901143375 HID Input 1 01 00 00 0B 00 00 00 00 00
179 0 23.944895500 HID Input 1 01 00 00 0B 08 00 00 00 00
180 0 23.989898500 HID Input 1 01 00 00 08 00 00 00 00 00
181 0 24.034901500 HID Input 1 01 00 00 08 2C 00 00 00 00
182 0 24.036151500 HID Input 1 01 00 00 2C 00 00 00 00 00
183 0 24.079906625 HID Input 1 01 00 00 2C 15 00 00 00 00
184 0 24.169913375 HID Input 1 01 00 00 2C 15 08 00 00 00
185 0 24.171163250 HID Input 1 01 00 00 2C 08 00 00 00 00
186 0 24.214916375 HID Input 1 01 00 00 08 00 00 00 00 00
187 0 24.216166375 HID Input 1 01 00 00 00 00 00 00 00 00
188 0 24.259920750 HID Input 1 01 00 00 06 00 00 00 00 00
189 0 24.394933000 HID Input 1 01 00 00 00 00 00 00 00 00
190 0 24.439935000 HID Input 1 01 00 00 0C 00 00 00 00 00
191 0 24.574946625 HID Input 1 01 00 00 00 00 00 00 00 00
192 0 24.619951625 HID Input 1 01 00 00 13 00 00 00 00 00
193 0 24.754963125 HID Input 1 01 00 00 13 17 00 00 00 00
194 0 24.756213125 HID Input 1 01 00 00 17 00 00 00 00 00
195 0 24.844968875 HID Input 1 01 00 00 00 00 00 00 00 00
196 0 24.979979750 HID Input 1 01 00 00 2C 00 00 00 00 00
197 0 25.024984125 HID Input 1 01 00 00 00 00 00 00 00 00
198 0 25.610031625 HID Input 1 01 00 00 12 00 00 00 00 00
199 0 25.700039125 HID Input 1 01 00 00 12 09 00 00 00 00
200 0 25.745042375 HID Input 1 01 00 00 09 00 00 00 00 00
201 0 25.790047750 HID Input 1 01 00 00 00 00 00 00 00 00
202 0 25.880054250 HID Input 1 01 00 00 2C 00 00 00 00 00
203 0 26.015066000 HID Input 1 01 00 00 2C 07 00 00 00 00
204 0 26.016316000 HID Input 1 01 00 00 07 00 00 00 00 00
205 0 26.105073000 HID Input 1 01 00 00 07 04 00 00 00 00
206 0 26.150076625 HID Input 1 01 00 00 04 00 00 00 00 00
207 0 26.240083250 HID Input 1 01 00 00 00 00 00 00 00 00
208 0 26.330091750 HID Input 1 01 00 00 17 00 00 00 00 00
209 0 26.375095000 HID Input 1 01 00 00 00 00 00 00 00 00
210 0 26.465100250 HID Input 1 01 00 00 04 00 00 00 00 00
211 0 26.555108125 HID Input 1 01 00 00 00 00 00 00 00 00
212 0 26.600111000 HID Input 1 01 00 00 37 00 00 00 00 00
213 0 26.690120000 HID Input 1 01 00 00 00 00 00 00 00 00
214 0 26.735123625 HID Input 1 01 00 00 2C 00 00 00 00 00
215 0 26.825130625 HID Input 1 01 00 00 00 00 00 00 00 00
216 0 26.915137500 HID Input 1 01 00 00 2C 00 00 00 00 00
217 0 26.960140750 HID Input 1 01 02 00 2C 00 00 00 00 00
218 0 27.005146375 HID Input 1 01 02 00 00 00 00 00 00 00
219 0 27.095152500 HID Input 1 01 02 00 0C 00 00 00 00 00
220 0 27.140156250 HID Input 1 01 00 00 0C 00 00 00 00 00
221 0 27.185160250 HID Input 1 01 00 00 00 00 00 00 00 00
222 0 27.230164000 HID Input 1 01 00 00 09 00 00 00 00 00
223 0 27.275166750 HID Input 1 01 00 00 09 2C 00 00 00 00
224 0 27.276416875 HID Input 1 01 00 00 2C 00 00 00 00 00
225 0 27.365174625 HID Input 1 01 00 00 00 00 00 00 00 00
226 0 27.366424625 HID Input 1 01 00 00 17 00 00 00 00 00
227 0 27.410178500 HID Input 1 01 00 00 17 0B 00 00 00 00
228 0 27.455182125 HID Input 1 01 00 00 17 0B 08 00 00 00
229 0 27.456432125 HID Input 1 01 00 00 08 0B 00 00 00 00
230 0 27.500184375 HID Input 1 01 00 00 08 00 00 00 00 00
231 0 27.545187375 HID Input 1 01 00 00 08 2C 00 00 00 00
232 0 27.546437375 HID Input 1 01 00 00 2C 00 00 00 00 00
233 0 27.635196750 HID Input 1 01 00 00 2C 04 00 00 00 00
234 0 27.680197375 HID Input 1 01 00 00 04 00 00 00 00 00
235 0 27.725198625 HID Input 1 01 00 00 00 00 00 00 00 00
236 0 27.815207125 HID Input 1 01 00 00 17 00 00 00 00 00
237 0 27.860210750 HID Input 1 01 00 00 00 00 00 00 00 00
238 0 27.950218375 HID Input 1 01 00 00 17 00 00 00 00 00
239 0 28.040226500 HID Input 1 01 00 00 00 00 00 00 00 00
240 0 28.085229750 HID Input 1 01 00 00 04 00 00 00 00 00
241 0 28.220240875 HID Input 1 01 00 00 00 00 00 00 00 00
242 0 28.221490750 HID Input 1 01 00 00 0E 00 00 00 00 00
243 0 28.400254625 HID Input 1 01 00 00 0E 08 00 00 00 00
244 0 28.445259750 HID Input 1 01 00 00 08 00 00 00 00 00
245 0 28.446509750 HID Input 1 01 00 00 08 15 00 00 00 00
246 0 28.535264375 HID Input 1 01 00 00 15 00 00 00 00 00
247 0 28.536514250 HID Input 1 01 00 00 00 00 00 00 00 00
248 0 28.580269250 HID Input 1 01 00 00 2C 00 00 00 00 00
249 0 28.715280625 HID Input 1 01 00 00 00 00 00 00 00 00
250 0 28.716530750 HID Input 1 01 00 00 06 00 00 00 00 00
251 0 28.805287875 HID Input 137 89 CA 52 04 12 00 00 00 00
252 0 28.850291125 HID Input 1 01 00 00 12 00 00 00 00 00
253 0 28.851541125 HID Input 1 01 00 00 12 18 00 00 00 00
254 0 28.895294250 HID Input 1 01 00 00 18 00 00 00 00 00
255 0 28.985298125 HID Input 1 01 00 00 0F 00 00 00 00 00
256 0 29.030302250 HID Input 1 01 00 00 0F 07 00 00 00 00
257 0 29.120309375 HID Input 1 01 00 00 07 00 00 00 00 00
258 0 29.121559375 HID Input 1 01 00 00 07 2C 00 00 00 00
259 0 29.165310625 HID Input 1 01 00 00 2C 00 00 00 00 00
260 0 29.210314625 HID Input 1 01 00 00 00 00 00 00 00 00
261 0 29.211564625 HID Input 1 01 00 00 13 00 00 00 00 00
262 0 29.256569625 HID Input 1 01 00 00 13 15 00 00 00 00
263 0 29.300324125 HID Input 1 01 00 00 13 15 08 00 00 00
264 0 29.345327500 HID Input 1 01 00 00 13 08 00 00 00 00
265 0 29.390330125 HID Input 1 01 00 00 13 00 00 00 00 00
266 0 29.391580000 HID Input 1 01 00 00 00 00 00 00 00 00
267 0 29.480336875 HID Input 1 01 00 00 07 00 00 00 00 00
268 0 29.525340750 HID Input 1 01 00 00 00 00 00 00 00 00
269 0 29.570344125 HID Input 1 01 00 00 0C 00 00 00 00 00
270 0 29.615347125 HID Input 1 01 00 00 0C 06 00 00 00 00
271 0 29.705355375 HID Input 1 01 00 00 06 00 00 00 00 00
272 0 29.706605375 HID Input 1 01 00 00 00 00 00 00 00 00
273 0 29.795362750 HID Input 1 01 00 00 17 00 00 00 00 00
274 0 29.885371250 HID Input 1 01 00 00 17 2C 00 00 00 00
275 0 29.886621250 HID Input 1 01 00 00 2C 00 00 00 00 00
276 0 29.975376500 HID Input 1 01 00 00 00 00 00 00 00 00
277 0 30.021631000 HID Input 1 01 00 00 17 00 00 00 00 00
278 0 30.065381000 HID Input 1 01 00 00 17 0B 00 00 00 00
279 0 30.066631000 HID Input 1 01 00 00 17 0B 08 00 00 00
280 0 30.110383625 HID Input 1 01 00 00 08 0B 00 00 00 00
281 0 30.111633625 HID Input 1 01 00 00 08 00 00 00 00 00
282 0 30.155388250 HID Input 1 01 00 00 08 2C 00 00 00 00
283 0 30.156638250 HID Input 1 01 00 00 2C 00 00 00 00 00
284 0 30.290395125 HID Input 1 01 00 00 00 00 00 00 00 00
285 0 30.650425125 HID Input 1 01 00 00 16 00 00 00 00 00
286 0 30.740433125 HID Input 1 01 00 00 16 08 00 00 00 00
287 0 30.741683125 HID Input 1 01 00 00 08 00 00 00 00 00
288 0 30.830439500 HID Input 1 01 00 00 00 00 00 00 00 00
289 0 30.875442375 HID Input 1 01 00 00 14 00 00 00 00 00
290 0 30.965450250 HID Input 1 01 00 00 00 00 00 00 00 00
291 0 30.966700250 HID Input 1 01 00 00 18 00 00 00 00 00
292 0 31.055458375 HID Input 1 01 00 00 18 08 00 00 00 00
293 0 31.056708375 HID Input 1 01 00 00 08 00 00 00 00 00
294 0 31.100461875 HID Input 1 01 00 00 00 00 00 00 00 00
295 0 31.190469125 HID Input 1 01 00 00 11 00 00 00 00 00
296 0 31.235472500 HID Input 1 01 00 00 11 06 00 00 00 00
297 0 31.236722375 HID Input 1 01 00 00 06 00 00 00 00 00
298 0 31.280477250 HID Input 1 01 00 00 06 08 00 00 00 00
299 0 31.325481000 HID Input 1 01 00 00 08 00 00 00 00 00
300 0 31.326731000 HID Input 1 01 00 00 08 2C 00 00 00 00
301 0 31.370482500 HID Input 1 01 00 00 2C 00 00 00 00 00
302 0 31.460490375 HID Input 1 01 00 00 2C 11 00 00 00 00
303 0 31.461740375 HID Input 1 01 00 00 11 00 00 00 00 00
304 0 31.550493750 HID Input 1 01 00 00 11 18 00 00 00 00
305 0 31.595498000 HID Input 1 01 00 00 18 00 00 00 00 00
306 0 31.640501250 HID Input 1 01 00 00 00 00 00 00 00 00
307 0 31.685504375 HID Input 1 01 00 00 10 00 00 00 00 00
308 0 31.820516875 HID Input 1 01 00 00 10 05 00 00 00 00
309 0 31.865519750 HID Input 1 01 00 00 05 00 00 00 00 00
310 0 31.866769750 HID Input 1 01 00 00 00 00 00 00 00 00
311 0 31.955528625 HID Input 1 01 00 00 08 00 00 00 00 00
312 0 32.000532625 HID Input 1 01 00 00 08 15 00 00 00 00
313 0 32.090540250 HID Input 1 01 00 00 15 00 00 00 00 00
314 0 32.091790000 HID Input 1 01 00 00 15 2C 00 00 00 00
315 0 32.135542000 HID Input 1 01 00 00 2C 00 00 00 00 00
316 0 32.180545000 HID Input 1 01 00 00 00 00 00 00 00 00
317 0 32.225548750 HID Input 1 01 00 00 12 00 00 00 00 00
318 0 32.270553125 HID Input 1 01 00 00 12 09 00 00 00 00
319 0 32.315557250 HID Input 1 01 00 00 12 09 2C 00 00 00
320 0 32.360559375 HID Input 1 01 00 00 12 2C 00 00 00 00
321 0 32.361809375 HID Input 1 01 00 00 2C 00 00 00 00 00
322 0 32.450569375 HID Input 1 01 00 00 00 00 00 00 00 00
323 0 32.451819250 HID Input 1 01 00 00 17 00 00 00 00 00
324 0 32.495570750 HID Input 1 01 00 00 17 0B 00 00 00 00
325 0 32.540573375 HID Input 1 01 00 00 17 0B 08 00 00 00
326 0 32.541823375 HID Input 1 01 00 00 08 0B 00 00 00 00
327 0 32.585578375 HID Input 1 01 00 00 08 00 00 00 00 00
328 0 32.586828500 HID Input 1 01 00 00 08 2C 00 00 00 00
329 0 32.630580250 HID Input 1 01 00 00 2C 00 00 00 00 00
330 0 32.675584750 HID Input 1 01 00 00 00 00 00 00 00 00
331 0 32.765592000 HID Input 1 01 00 00 13 00 00 00 00 00
332 0 32.810591375 HID Input 1 01 00 00 13 04 00 00 00 00
333 0 32.900599250 HID Input 1 01 00 00 04 00 00 00 00 00
334 0 32.901849250 HID Input 1 01 00 00 00 00 00 00 00 00
335 0 32.945604375 HID Input 1 01 00 00 06 00 00 00 00 00
336 0 32.990608125 HID Input 1 01 00 00 00 00 00 00 00 00
337 0 33.035611125 HID Input 1 01 00 00 0E 00 00 00 00 00
338 0 33.125619250 HID Input 1 01 00 00 0E 08 00 00 00 00
339 0 33.170623500 HID Input 1 01 00 00 08 00 00 00 00 00
340 0 33.171873500 HID Input 1 01 00 00 08 17 00 00 00 00
341 0 33.215623875 HID Input 1 01 00 00 17 00 00 00 00 00
342 0 33.260627625 HID Input 1 01 00 00 17 2C 00 00 00 00
343 0 33.261877625 HID Input 1 01 00 00 2C 00 00 00 00 00
344 0 33.395640500 HID Input 1 01 00 00 2C 05 00 00 00 00
345 0 33.396890500 HID Input 1 01 00 00 05 00 00 00 00 00
346 0 33.440643625 HID Input 1 01 00 00 00 00 00 00 00 00
347 0 33.485647375 HID Input 1 01 00 00 08 00 00 00 00 00
348 0 33.575654500 HID Input 1 01 00 00 08 0C 00 00 00 00
349 0 33.576904375 HID Input 1 01 00 00 0C 00 00 00 00 00
350 0 33.620658000 HID Input 1 01 00 00 0C 11 00 00 00 00
351 0 33.665661500 HID Input 1 01 00 00 0C 11 0A 00 00 00
352 0 33.666911500 HID Input 1 01 00 00 0A 11 00 00 00 00
353 0 33.755668250 HID Input 1 01 00 00 0A 00 00 00 00 00
354 0 33.756918125 HID Input 1 01 00 00 00 00 00 00 00 00
355 0 33.800673125 HID Input 1 01 00 00 2C 00 00 00 00 00
356 0 33.845676250 HID Input 1 01 00 00 2C 16 00 00 00 00
357 0 33.890680625 HID Input 1 01 00 00 16 00 00 00 00 00
358 0 33.935684125 HID Input 1 01 00 00 16 08 00 00 00 00
359 0 33.980687375 HID Input 1 01 00 00 08 00 00 00 00 00
360 0 34.025691500 HID Input 1 01 00 00 00 00 00 00 00 00
361 0 34.026941500 HID Input 1 01 00 00 11 00 00 00 00 00
362 0 34.115695000 HID Input 1 01 00 00 00 00 00 00 00 00
363 0 34.116945000 HID Input 1 01 00 00 17 00 00 00 00 00
364 0 34.205701875 HID Input 1 01 00 00 00 00 00 00 00 00
365 0 34.206951875 HID Input 1 01 00 00 2C 00 00 00 00 00
366 0 34.295709250 HID Input 1 01 00 00 2C 09 00 00 00 00
367 0 34.340712875 HID Input 1 01 00 00 09 00 00 00 00 00
368 0 34.385717250 HID Input 1 01 00 00 00 00 00 00 00 00
369 0 34.430721000 HID Input 1 01 00 00 15 00 00 00 00 00
370 0 34.520728875 HID Input 1 01 00 00 15 12 00 00 00 00
371 0 34.521978750 HID Input 1 01 00 00 12 00 00 00 00 00
372 0 34.565731750 HID Input 1 01 00 00 12 10 00 00 00 00
373 0 34.610734500 HID Input 1 01 00 00 12 10 2C 00 00 00
374 0 34.700742750 HID Input 1 01 00 00 12 2C 00 00 00 00
375 0 34.701992750 HID Input 1 01 00 00 2C 00 00 00 00 00
376 0 34.745747375 HID Input 1 01 00 00 2C 17 00 00 00 00
377 0 34.746997375 HID Input 1 01 00 00 17 00 00 00 00 00
378 0 34.790748375 HID Input 1 01 00 00 00 00 00 00 00 00
379 0 34.791998250 HID Input 1 01 00 00 0B 00 00 00 00 00
380 0 34.835752125 HID Input 1 01 00 00 0B 08 00 00 00 00
381 0 34.925760250 HID Input 1 01 00 00 0B 08 2C 00 00 00
382 0 34.927010125 HID Input 1 01 00 00 2C 00 00 00 00 00
383 0 35.060771625 HID Input 1 01 00 00 00 00 00 00 00 00
384 0 35.062021500 HID Input 1 01 00 00 17 00 00 00 00 00
385 0 35.105775000 HID Input 1 01 00 00 00 70 20 06 2C 00
386 0 35.195782250 HID Input 1 01 00 00 04 00 00 00 00 00
387 0 35.285790375 HID Input 1 01 00 00 00 00 00 00 00 00
388 0 35.330794375 HID Input 1 01 00 00 15 00 00 00 00 00
389 0 35.375792625 HID Input 1 01 00 00 00 00 00 00 00 00
390 0 35.465801500 HID Input 1 01 00 00 0A 00 00 00 00 00
391 0 35.555808750 HID Input 1 01 00 00 00 00 00 00 00 00
392 0 35.600812000 HID Input 1 01 00 00 08 00 00 00 00 00
393 0 35.645815375 HID Input 1 01 00 00 08 17 00 00 00 00
394 0 35.690818625 HID Input 1 01 00 00 17 00 00 00 00 00
395 0 35.735823875 HID Input 1 01 00 00 00 00 00 00 00 00
396 0 35.737074000 HID Input 1 01 00 00 2C 00 00 00 00 00
397 0 35.825830875 HID Input 1 01 00 00 00 00 00 00 00 00
398 0 35.870835125 HID Input 1 01 00 00 16 00 00 00 00 00
399 0 35.915839250 HID Input 1 01 00 00 00 00 00 00 00 00
400 0 35.960841500 HID Input 1 01 00 00 1C 00 00 00 00 00
401 0 36.005846000 HID Input 1 01 00 00 1C 16 00 00 00 00
402 0 36.050850500 HID Input 1 01 00 00 16 00 00 00 00 00
403 0 36.095853625 HID Input 1 01 00 00 00 00 00 00 00 00
404 0 36.140856625 HID Input 1 01 00 00 17 00 00 00 00 00
405 0 36.230864750 HID Input 1 01 00 00 17 08 00 00 00 00
406 0 36.232114750 HID Input 1 01 00 00 08 00 00 00 00 00
407 0 36.275867250 HID Input 1 01 00 00 08 10 00 00 00 00
408 0 36.320869875 HID Input 1 01 00 00 10 00 00 00 00 00
409 0 36.365874125 HID Input 1 01 00 00 10 2C 00 00 00 00
410 0 36.410877625 HID Input 1 01 00 00 2C 00 00 00 00 00
411 0 36.500885125 HID Input 1 01 00 00 00 00 00 00 00 00
412 0 36.502135125 HID Input 1 01 00 00 17 00 00 00 00 00
413 0 36.545889500 HID Input 1 01 00 00 00 00 00 00 00 00
414 0 36.590893875 HID Input 1 01 00 00 12 00 00 00 00 00
415 0 36.635894625 HID Input 1 01 00 00 12 2C 00 00 00 00
416 0 36.680895625 HID Input 1 01 00 00 2C 00 00 00 00 00
417 0 36.682145625 HID Input 1 01 00 00 2C 17 00 00 00 00
418 0 36.725899500 HID Input 1 01 00 00 17 00 00 00 00 00
419 0 36.770904625 HID Input 1 01 00 00 00 00 00 00 00 00
420 0 36.815908250 HID Input 1 01 00 00 0B 00 00 00 00 00
421 0 36.860910750 HID Input 1 01 00 00 0B 08 00 00 00 00
422 0 36.905914625 HID Input 1 01 00 00 08 00 00 00 00 00
423 0 36.907164500 HID Input 1 01 00 00 00 00 00 00 00 00
424 0 36.950917500 HID Input 1 01 00 00 2C 00 00 00 00 00
425 0 36.995921250 HID Input 1 01 00 00 2C 15 00 00 00 00
426 0 37.040924750 HID Input 1 01 00 00 2C 15 08 00 00 00
427 0 37.085929000 HID Input 1 01 00 00 08 15 00 00 00 00
428 0 37.087179000 HID Input 1 01 00 00 08 00 00 00 00 00
429 0 37.130933125 HID Input 1 01 00 00 00 00 00 00 00 00
430 0 37.220940750 HID Input 1 01 00 00 04 00 00 00 00 00
431 0 37.265944250 HID Input 1 01 00 00 00 00 00 00 00 00
432 0 37.310947000 HID Input 1 01 00 00 0F 00 00 00 00 00
433 0 37.355951750 HID Input 1 01 00 00 0F 2C 00 00 00 00
434 0 37.445958625 HID Input 1 01 00 00 0F 2C 16 00 00 00
435 0 37.447208625 HID Input 1 01 00 00 16 2C 00 00 00 00
436 0 37.490961375 HID Input 1 01 00 00 2C 00 00 00 00 00
437 0 37.535965375 HID Input 1 01 00 00 00 00 00 00 00 00
438 0 37.580968750 HID Input 1 01 00 00 08 00 00 00 00 00
439 0 37.625971750 HID Input 1 01 00 00 08 15 00 00 00 00
440 0 37.670975375 HID Input 1 01 00 00 15 00 00 00 00 00
441 0 37.672225500 HID Input 1 01 00 00 00 00 00 00 00 00
442 0 37.760984625 HID Input 1 01 00 00 19 00 00 00 00 00
443 0 37.805989000 HID Input 1 01 00 00 00 00 00 00 00 00
444 0 37.850992125 HID Input 1 01 00 00 08 00 00 00 00 00
445 0 37.940995250 HID Input 1 01 00 00 08 15 00 00 00 00
446 0 37.985997750 HID Input 1 01 00 00 15 00 00 00 00 00
447 0 37.987247625 HID Input 1 01 00 00 15 2C 00 00 00 00
448 0 38.031002125 HID Input 1 01 00 00 2C 00 00 00 00 00
449 0 38.121009750 HID Input 1 01 00 00 00 00 00 00 00 00
450 0 38.122259750 HID Input 1 01 00 00 07 00 00 00 00 00
451 0 38.166013250 HID Input 1 01 00 00 00 00 00 00 00 00
452 0 38.167263250 HID Input 1 01 00 00 18 00 00 00 00 00
453 0 38.256020625 HID Input 1 01 00 00 18 15 00 00 00 00
454 0 38.302274625 HID Input 1 01 00 00 15 00 00 00 00 00
455 0 38.346028500 HID Input 1 01 00 00 00 00 00 00 00 00
456 0 38.391031375 HID Input 1 01 00 00 0C 00 00 00 00 00
457 0 38.436035125 HID Input 1 01 00 00 0C 11 00 00 00 00
458 0 38.481040125 HID Input 1 01 00 00 0C 11 0A 00 00 00
459 0 38.482290125 HID Input 1 01 00 00 0C 11 0A 2C 00 00
460 0 38.526041625 HID Input 1 01 00 00 0C 11 2C 00 00 00
461 0 38.527291500 HID Input 1 01 00 00 2C 11 00 00 00 00
462 0 38.571045500 HID Input 1 01 00 00 2C 00 00 00 00 00
463 0 38.616049125 HID Input 1 01 00 00 2C 17 00 00 00 00
464 0 38.617299125 HID Input 1 01 00 00 17 00 00 00 00 00
465 0 38.661052375 HID Input 1 01 00 00 17 0B 00 00 00 00
466 0 38.706055375 HID Input 1 01 00 00 17 0B 08 00 00 00
467 0 38.707306500 HID Input 1 01 00 00 08 0B 00 00 00 00
468 0 38.751058750 HID Input 1 01 00 00 08 0B 2C 00 00 00
469 0 38.796062750 HID Input 1 01 00 00 08 2C 00 00 00 00
470 0 38.797312875 HID Input 1 01 00 00 2C 00 00 00 00 00
471 0 38.886069250 HID Input 1 01 00 00 00 00 00 00 00 00
472 0 38.931073625 HID Input 1 01 00 00 0C 00 00 00 00 00
473 0 38.976077250 HID Input 1 01 00 00 0C 11 00 00 00 00
474 0 39.066085000 HID Input 1 01 00 00 11 00 00 00 00 00
475 0 39.156092000 HID Input 1 01 00 00 11 0C 00 00 00 00
476 0 39.157342000 HID Input 1 01 00 00 0C 00 00 00 00 00
477 0 39.246096250 HID Input 1 01 00 00 0C 17 00 00 00 00
478 0 39.247346125 HID Input 1 01 00 00 17 00 00 00 00 00
479 0 39.291099375 HID Input 1 01 00 00 00 00 00 00 00 00
480 0 39.336103000 HID Input 1 01 00 00 0C 00 00 00 00 00
481 0 39.426111000 HID Input 1 01 00 00 0C 04 00 00 00 00
482 0 39.427361000 HID Input 1 01 00 00 04 00 00 00 00 00
483 0 39.516119250 HID Input 1 01 00 00 04 0F 00 00 00 00
484 0 39.517369250 HID Input 1 01 00 00 0F 00 00 00 00 00
485 0 39.606125250 HID Input 1 01 00 00 0F 2C 00 00 00 00
486 0 39.607375250 HID Input 1 01 00 00 2C 00 00 00 00 00
487 0 39.651128500 HID Input 1 01 00 00 00 00 00 00 00 00
488 0 39.741136750 HID Input 1 01 00 00 0B 00 00 00 00 00
489 0 39.831143875 HID Input 1 01 00 00 04 00 00 00 00 00
490 0 39.876147375 HID Input 1 01 00 00 00 00 00 00 00 00
491 0 39.921152375 HID Input 1 01 00 00 11 00 00 00 00 00
492 0 39.966155750 HID Input 1 01 00 00 11 07 00 00 00 00
493 0 40.056163750 HID Input 1 01 00 00 07 00 00 00 00 00
494 0 40.057413750 HID Input 1 01 00 00 00 00 00 00 00 00
495 0 40.146169625 HID Input 1 01 00 00 16 00 00 00 00 00
496 0 40.236177500 HID Input 1 01 00 00 16 0B 00 00 00 00
497 0 40.237427500 HID Input 1 01 00 00 0B 00 00 00 00 00
498 0 40.327434250 HID Input 1 01 00 00 04 00 00 00 00 00
499 0 40.461194250 HID Input 1 01 00 00 00 00 00 00 00 00
500 0 40.506195750 HID Input 1 01 00 00 0E 00 00 00 00 00
501 0 40.597453125 HID Input 1 01 00 00 0E 08 00 00 00 00
502 0 40.641202375 HID Input 1 01 00 00 08 00 00 00 00 00
503 0 40.731211125 HID Input 1 01 00 00 00 00 00 00 00 00
504 0 40.866222125 HID Input 1 01 00 00 36 00 00 00 00 00
505 0 40.956230125 HID Input 1 01 00 00 36 2C 00 00 00 00
506 0 41.001234000 HID Input 1 01 00 00 2C 00 00 00 00 00
507 0 41.091241000 HID Input 1 01 00 00 00 00 00 00 00 00
508 0 41.226251750 HID Input 1 01 00 00 0B 00 00 00 00 00
509 0 41.316260625 HID Input 1 01 00 00 0B 08 00 00 00 00
510 0 41.317510625 HID Input 1 01 00 00 08 00 00 00 00 00
511 0 41.361262875 HID Input 1 01 00 00 00 00 00 00 00 00
512 0 41.406265375 HID Input 1 01 00 00 2C 00 00 00 00 00
513 0 41.496272500 HID Input 1 01 00 00 2C 06 00 00 00 00
514 0 41.497522625 HID Input 1 01 00 00 06 00 00 00 00 00
515 0 41.541277000 HID Input 1 01 00 00 06 12 00 00 00 00
516 0 41.586280625 HID Input 1 01 00 00 06 12 18 00 00 00
517 0 41.587530750 HID Input 1 01 00 00 18 12 00 00 00 00
518 0 41.631283125 HID Input 1 01 00 00 18 00 00 00 00 00
519 0 41.721291500 HID Input 1 01 00 00 18 0F 00 00 00 00
520 0 41.722541500 HID Input 1 01 00 00 0F 00 00 00 00 00
521 0 41.766292625 HID Input 1 01 00 00 0F 07 00 00 00 00
522 0 41.811293250 HID Input 1 01 00 00 0F 07 2C 00 00 00
523 0 41.812543250 HID Input 1 01 00 00 0F 2C 00 00 00 00
524 0 41.856297750 HID Input 1 01 00 00 2C 00 00 00 00 00
525 0 41.946305125 HID Input 1 01 00 00 2C 06 00 00 00 00
526 0 41.947555125 HID Input 1 01 00 00 06 00 00 00 00 00
527 0 42.037562000 HID Input 1 01 00 00 12 00 00 00 00 00
528 0 42.081317000 HID Input 1 01 00 00 12 10 00 00 00 00
529 0 42.171324125 HID Input 1 01 00 00 10 00 00 00 00 00
530 0 42.216328625 HID Input 1 01 00 00 00 00 00 00 00 00
531 0 42.261330625 HID Input 1 01 00 00 13 00 00 00 00 00
532 0 42.351339750 HID Input 1 01 00 00 13 0F 00 00 00 00
533 0 42.396343375 HID Input 1 01 00 00 13 0F 08 00 00 00
534 0 42.441346125 HID Input 1 01 00 00 08 0F 00 00 00 00
535 0 42.486349500 HID Input 1 01 00 00 08 00 00 00 00 00
536 0 42.487599500 HID Input 1 01 00 00 08 17 00 00 00 00
537 0 42.531352875 HID Input 1 01 00 00 17 00 00 00 00 00
538 0 42.576356000 HID Input 1 01 00 00 17 08 00 00 00 00
539 0 42.621359000 HID Input 1 01 00 00 08 00 00 00 00 00
540 0 42.666363000 HID Input 1 01 00 00 08 2C 00 00 00 00
541 0 42.711367125 HID Input 1 01 00 00 2C 00 00 00 00 00
542 0 42.756371250 HID Input 1 01 00 00 00 00 00 00 00 00
543 0 42.757621250 HID Input 1 01 00 00 17 00 00 00 00 00
544 0 42.801376000 HID Input 1 01 00 00 17 0B 00 00 00 00
545 0 42.891383500 HID Input 1 01 00 00 0B 00 00 00 00 00
546 0 42.892633500 HID Input 1 01 00 00 0B 08 00 00 00 00
547 0 42.936384375 HID Input 1 01 00 00 08 00 00 00 00 00
548 0 42.937634250 HID Input 1 01 00 00 08 2C 00 00 00 00
549 0 42.981389000 HID Input 1 01 00 00 2C 00 00 00 00 00
550 0 43.071391375 HID Input 1 01 00 00 2C 13 00 00 00 00
551 0 43.072641375 HID Input 1 01 00 00 13 00 00 00 00 00
552 0 43.161397250 HID Input 1 01 00 00 13 15 00 00 00 00
553 0 43.162647250 HID Input 1 01 00 00 15 00 00 00 00 00
554 0 43.206403125 HID Input 1 01 00 00 00 00 00 00 00 00
555 0 43.251407000 HID Input 1 01 00 00 12 00 00 00 00 00
556 0 43.296409250 HID Input 1 01 00 00 12 06 00 00 00 00
557 0 43.386418125 HID Input 1 01 00 00 01 01 01 01 01 01
558 0 43.521429125 HID Input 1 01 00 00 00 00 00 00 00 00
559 0 43.522679000 HID Input 1 01 00 00 16 00 00 00 00 00
560 0 43.611434875 HID Input 1 01 00 00 00 00 00 00 00 00
561 0 43.701442750 HID Input 1 01 00 00 16 00 00 00 00 00
562 0 43.746447250 HID Input 1 01 00 00 16 2C 00 00 00 00
563 0 43.791449250 HID Input 1 01 00 00 2C 00 00 00 00 00
564 0 43.881458500 HID Input 1 01 00 00 00 00 00 00 00 00
565 0 43.926462125 HID Input 1 01 00 00 05 00 00 00 00 00
566 0 43.971464750 HID Input 1 01 00 00 00 00 00 00 00 00
567 0 43.972714875 HID Input 1 01 00 00 1C 00 00 00 00 00
568 0 44.061472625 HID Input 1 01 00 00 1C 2C 00 00 00 00
569 0 44.106478000 HID Input 1 01 00 00 2C 00 00 00 00 00
570 0 44.151481875 HID Input 1 01 00 00 2C 16 00 00 00 00
571 0 44.197735250 HID Input 1 01 00 00 16 00 00 00 00 00
572 0 44.241489250 HID Input 1 01 00 00 16 08 00 00 00 00
573 0 44.242739250 HID Input 1 01 00 00 08 00 00 00 00 00
574 0 44.286490000 HID Input 1 01 00 00 00 00 00 00 00 00
575 0 44.331490375 HID Input 1 01 00 00 11 00 00 00 00 00
576 0 44.376494750 HID Input 1 01 00 00 11 07 00 00 00 00
577 0 44.421498625 HID Input 1 01 00 00 07 00 00 00 00 00
578 0 44.466501000 HID Input 1 01 00 00 00 00 00 00 00 00
579 0 44.511505000 HID Input 1 01 00 00 0C 00 00 00 00 00
580 0 44.556509375 HID Input 1 01 00 00 0C 11 00 00 00 00
581 0 44.646516375 HID Input 1 01 00 00 11 00 00 00 00 00
582 0 44.691520375 HID Input 1 01 00 00 11 0A 00 00 00 00
583 0 44.692770500 HID Input 1 01 00 00 0A 00 00 00 00 00
584 0 44.736524875 HID Input 1 01 00 00 00 00 00 00 00 00
585 0 44.826532500 HID Input 1 01 00 00 2C 00 00 00 00 00
586 0 44.961543750 HID Input 1 01 00 00 2C 04 00 00 00 00
587 0 44.962793625 HID Input 1 01 00 00 04 00 00 00 00 00
588 0 45.096553625 HID Input 1 01 00 00 00 00 00 00 00 00
589 0 45.097803625 HID Input 1 01 00 00 11 00 00 00 00 00
590 0 45.186561250 HID Input 1 01 00 00 11 2C 00 00 00 00
591 0 45.231566000 HID Input 1 01 00 00 2C 00 00 00 00 00
592 0 45.232815875 HID Input 1 01 00 00 2C 04 00 00 00 00
593 0 45.276568500 HID Input 1 01 00 00 04 00 00 00 00 00
594 0 45.321572375 HID Input 1 01 00 00 00 00 00 00 00 00
595 0 45.411580125 HID Input 1 01 00 00 06 00 00 00 00 00
596 0 45.501587625 HID Input 1 01 00 00 06 0E 00 00 00 00
597 0 45.502837625 HID Input 1 01 00 00 0E 00 00 00 00 00
598 0 45.546591000 HID Input 1 01 00 00 00 00 00 00 00 00
599 0 45.681598375 HID Input 1 01 00 00 11 00 00 00 00 00
600 0 45.771605625 HID Input 1 01 00 00 11 12 00 00 00 00
601 0 45.816608750 HID Input 1 01 00 00 12 00 00 00 00 00
602 0 45.861612250 HID Input 1 01 00 00 1A 00 00 00 00 00
603 0 45.951621250 HID Input 1 01 00 00 00 00 00 00 00 00
604 0 45.996624125 HID Input 1 01 00 00 0F 00 00 00 00 00
605 0 46.041626750 HID Input 1 01 00 00 0F 08 00 00 00 00
606 0 46.086630500 HID Input 1 01 00 00 0F 00 00 00 00 00
607 0 46.131635875 HID Input 1 01 00 00 00 00 00 00 00 00
608 0 46.176639250 HID Input 1 01 00 00 07 00 00 00 00 00
609 0 46.266646625 HID Input 1 01 00 00 00 00 00 00 00 00
610 0 46.356654375 HID Input 1 01 00 00 0A 00 00 00 00 00
611 0 46.446661000 HID Input 1 01 00 00 0A 08 00 00 00 00
612 0 46.491665000 HID Input 1 01 00 00 08 00 00 00 00 00
613 0 46.536668125 HID Input 1 01 00 00 10 00 00 00 00 00
614 0 46.581671750 HID Input 1 01 00 00 00 00 00 00 00 00
615 0 46.626677000 HID Input 1 01 00 00 08 00 00 00 00 00
616 0 46.716683375 HID Input 1 01 00 00 08 11 00 00 00 00
617 0 46.717933375 HID Input 1 01 00 00 11 00 00 00 00 00
618 0 46.806691875 HID Input 1 01 00 00 11 17 00 00 00 00
619 0 46.807942000 HID Input 1 01 00 00 17 00 00 00 00 00
620 0 46.896693500 HID Input 1 01 00 00 00 00 00 00 00 00
621 0 46.941697625 HID Input 1 01 00 00 2C 00 00 00 00 00
622 0 47.031705000 HID Input 1 01 00 00 2C 13 00 00 00 00
623 0 47.032955125 HID Input 1 01 00 00 13 00 00 00 00 00
624 0 47.121712625 HID Input 1 01 00 00 13 04 00 00 00 00
625 0 47.211720625 HID Input 1 01 00 00 00 00 00 00 00 00
626 0 47.257972500 HID Input 1 01 00 00 06 00 00 00 00 00
627 0 47.346731500 HID Input 1 01 00 00 00 00 00 00 00 00
628 0 47.347981500 HID Input 1 01 00 00 0E 00 00 00 00 00
629 0 47.481743250 HID Input 1 01 00 00 00 00 00 00 00 00
630 0 47.482993250 HID Input 1 01 00 00 08 00 00 00 00 00
631 0 47.526745000 HID Input 1 01 00 00 08 17 00 00 00 00
632 0 47.571747750 HID Input 1 01 00 00 17 00 00 00 00 00
633 0 47.616752750 HID Input 1 01 00 00 00 00 00 00 00 00
634 0 47.618002625 HID Input 1 01 00 00 2C 00 00 00 00 00
635 0 47.751763625 HID Input 1 01 00 00 00 00 00 00 00 00
636 0 47.753013625 HID Input 1 01 02 00 00 00 00 00 00 00
637 0 47.841771250 HID Input 1 01 02 00 25 00 00 00 00 00
638 0 47.976783000 HID Input 1 01 02 00 00 00 00 00 00 00
639 0 48.246801750 HID Input 1 01 00 00 00 00 00 00 00 00
640 0 48.606832750 HID Input 1 01 00 00 2A 00 00 00 00 00
641 0 48.786848750 HID Input 1 01 00 00 00 00 00 00 00 00
642 0 48.876855500 HID Input 1 01 02 00 00 00 00 00 00 00
643 0 49.011866500 HID Input 1 01 02 00 26 00 00 00 00 00
644 0 49.146879125 HID Input 1 01 02 00 00 00 00 00 00 00
645 0 49.236886750 HID Input 1 01 00 00 00 00 00 00 00 00
646 0 49.371897125 HID Input 1 01 00 00 1A 00 00 00 00 00
647 0 49.461902125 HID Input 1 01 00 00 00 00 00 00 00 00
648 0 49.506905750 HID Input 1 01 00 00 0C 00 00 00 00 00
649 0 49.551908500 HID Input 1 01 00 00 00 00 00 00 00 00
650 0 49.596913250 HID Input 1 01 00 00 17 00 00 00 00 00
651 0 49.641917250 HID Input 1 01 00 00 00 00 00 00 00 00
652 0 49.686919375 HID Input 1 01 00 00 0B 00 00 00 00 00
653 0 49.731923125 HID Input 1 01 00 00 0B 2C 00 00 00 00
654 0 49.821930625 HID Input 1 01 00 00 2C 00 00 00 00 00
655 0 49.823180750 HID Input 1 01 00 00 2C 17 00 00 00 00
656 0 49.866936000 HID Input 1 01 00 00 17 00 00 00 00 00
657 0 49.911939750 HID Input 1 01 00 00 00 00 00 00 00 00
658 0 49.913189750 HID Input 1 01 00 00 0B 00 00 00 00 00
659 0 49.956941750 HID Input 1 01 00 00 0B 08 00 00 00 00
660 0 50.001945000 HID Input 1 01 00 00 0B 08 2C 00 00 00
661 0 50.003194750 HID Input 1 01 00 00 2C 08 00 00 00 00
662 0 50.046949875 HID Input 1 01 00 00 2C 00 00 00 00 00
663 0 50.136957125 HID Input 1 01 00 00 00 00 00 00 00 00
664 0 50.183211125 HID Input 1 01 00 00 06 00 00 00 00 00
665 0 50.226962625 HID Input 1 01 00 00 00 00 00 00 00 00
666 0 50.271965625 HID Input 1 01 00 00 12 00 00 00 00 00
667 0 50.361975125 HID Input 1 01 00 00 12 15 00 00 00 00
668 0 50.406978625 HID Input 1 01 00 00 00 00 00 00 00 00
669 0 50.541989125 HID Input 1 01 00 00 15 00 00 00 00 00
670 0 50.543239125 HID Input 1 01 00 00 00 00 00 00 00 00
671 0 50.631998250 HID Input 1 01 00 00 08 00 00 00 00 00
672 0 50.677001500 HID Input 1 01 00 00 00 00 00 00 00 00
673 0 50.767003000 HID Input 1 01 00 00 06 00 00 00 00 00
674 0 50.857010125 HID Input 1 01 00 00 00 00 00 00 00 00
675 0 50.948268375 HID Input 1 01 00 00 17 00 00 00 00 00
676 0 51.037021125 HID Input 1 01 00 00 00 00 00 00 00 00
677 0 51.038271125 HID Input 1 01 00 00 2C 00 00 00 00 00
678 0 51.172032125 HID Input 1 01 00 00 2C 16 00 00 00 00
679 0 51.217036750 HID Input 1 01 00 00 16 00 00 00 00 00
680 0 51.218286625 HID Input 1 01 00 00 16 08 00 00 00 00
681 0 51.262039000 HID Input 1 01 00 00 08 00 00 00 00 00
682 0 51.352046625 HID Input 1 01 00 00 00 00 00 00 00 00
683 0 51.397049375 HID Input 1 01 00 00 14 00 00 00 00 00
684 0 51.487058500 HID Input 1 01 00 00 00 00 00 00 00 00
685 0 51.532061875 HID Input 1 01 00 00 18 00 00 00 00 00
686 0 51.577066000 HID Input 1 01 00 00 18 08 00 00 00 00
687 0 51.622069125 HID Input 1 01 00 00 08 00 00 00 00 00
688 0 51.667073000 HID Input 1 01 00 00 00 00 00 00 00 00
689 0 51.712076250 HID Input 1 01 00 00 11 00 00 00 00 00
690 0 51.802084625 HID Input 1 01 00 00 11 06 00 00 00 00
691 0 51.847088000 HID Input 1 01 00 00 06 00 00 00 00 00
692 0 51.892091125 HID Input 1 01 00 00 06 08 00 00 00 00
693 0 51.893341250 HID Input 1 01 00 00 08 00 00 00 00 00
694 0 51.982098250 HID Input 1 01 00 00 00 00 00 00 00 00
695 0 51.983348375 HID Input 1 01 00 00 2C 00 00 00 00 00
696 0 52.072100750 HID Input 1 01 00 00 2C 11 00 00 00 00
697 0 52.117105250 HID Input 1 01 00 00 11 00 00 00 00 00
698 0 52.162109125 HID Input 1 01 00 00 11 18 00 00 00 00
699 0 52.207111750 HID Input 1 01 00 00 18 00 00 00 00 00
700 0 52.252116125 HID Input 1 01 00 00 00 00 00 00 00 00
701 0 52.342123375 HID Input 1 01 00 00 10 00 00 00 00 00
702 0 52.432130625 HID Input 1 01 00 00 10 05 00 00 00 00
703 0 52.477135375 HID Input 1 01 00 00 10 00 00 00 00 00
704 0 52.478385250 HID Input 1 01 00 00 00 00 00 00 00 00
705 0 52.567143250 HID Input 1 01 00 00 08 00 00 00 00 00
706 0 52.612147125 HID Input 1 01 00 00 08 15 00 00 00 00
707 0 52.657151250 HID Input 1 01 00 00 15 00 00 00 00 00
708 0 52.747158125 HID Input 1 01 00 00 00 00 00 00 00 00
709 0 52.837166000 HID Input 1 01 02 00 00 00 00 00 00 00
710 0 53.467215875 HID Input 1 01 02 00 26 00 00 00 00 00
711 0 53.468465875 HID Input 1 01 02 00 26 27 00 00 00 00
712 0 53.512220250 HID Input 1 01 02 00 26 00 00 00 00 00
713 0 53.557222375 HID Input 1 01 02 00 00 00 00 00 00 00
714 0 53.872250500 HID Input 1 01 00 00 00 00 00 00 00 00
715 0 54.007262250 HID Input 1 01 00 00 2A 00 00 00 00 00
716 0 54.142273375 HID Input 1 01 00 00 00 00 00 00 00 00
717 0 54.277285625 HID Input 1 01 02 00 00 00 00 00 00 00
718 0 54.457299750 HID Input 1 01 00 00 00 00 00 00 00 00
719 0 54.502303750 HID Input 1 01 00 00 2A 00 00 00 00 00
720 0 54.637311625 HID Input 1 01 02 00 2A 00 00 00 00 00
721 0 54.638561625 HID Input 1 01 02 00 00 00 00 00 00 00
722 0 54.773573375 HID Input 1 01 02 00 27 00 00 00 00 00
723 0 54.862331375 HID Input 1 01 02 00 00 00 00 00 00 00
724 0 55.042347000 HID Input 1 01 00 00 00 00 00 00 00 00
725 0 55.222360250 HID Input 1 01 00 00 36 00 00 00 00 00
726 0 55.312369125 HID Input 1 01 00 00 36 2C 00 00 00 00
727 0 55.402376500 HID Input 1 01 00 00 2C 00 00 00 00 00
728 0 55.492384125 HID Input 1 01 00 00 00 00 00 00 00 00
729 0 55.493634125 HID Input 1 01 00 00 04 00 00 00 00 00
730 0 55.582389375 HID Input 1 01 00 00 04 11 00 00 00 00
731 0 55.627393375 HID Input 1 01 00 00 11 00 00 00 00 00
732 0 55.672398250 HID Input 1 01 00 00 11 07 00 00 00 00
733 0 55.673648250 HID Input 1 01 00 00 07 00 00 00 00 00
734 0 55.762406250 HID Input 1 01 00 00 00 00 00 00 00 00
735 0 55.763656000 HID Input 1 01 00 00 2C 00 00 00 00 00
736 0 55.942415000 HID Input 1 01 00 00 00 00 00 00 00 00
737 0 55.943665000 HID Input 1 01 00 00 08 00 00 00 00 00
738 0 55.987417000 HID Input 1 01 00 00 00 00 00 00 00 00
739 0 56.077425250 HID Input 1 01 00 00 16 00 00 00 00 00
740 0 56.167432250 HID Input 1 01 00 00 00 00 00 00 00 00
741 0 56.302444625 HID Unknown
742 0 56.392451875 HID Input 1 01 00 00 00 00 00 00 00 00
743 0 56.437456375 HID Input 1 01 00 00 04 00 00 00 00 00
744 0 56.527463625 HID Input 1 01 00 00 00 00 00 00 00 00
745 0 56.662474625 HID Input 1 01 00 00 05 00 00 00 00 00
746 0 56.707480000 HID Input 1 01 00 00 00 00 00 00 00 00
747 0 56.708729875 HID Input 1 01 00 00 0F 00 00 00 00 00
748 0 56.797485375 HID Input 1 01 00 00 0F 0C 00 00 00 00
749 0 56.842489625 HID Input 1 01 00 00 0F 00 00 00 00 00
750 0 56.887493250 HID Input 1 01 00 00 0F 16 00 00 00 00
751 0 56.888743250 HID Input 1 01 00 00 16 00 00 00 00 00
752 0 56.977502000 HID Input 1 01 00 00 00 00 00 00 00 00
753 0 57.022503625 HID Input 1 01 00 00 0B 00 00 00 00 00
754 0 57.067507500 HID Input 1 01 00 00 0B 2C 00 00 00 00
755 0 57.112511500 HID Input 1 01 00 00 2C 00 00 00 00 00
756 0 57.157510875 HID Input 1 01 00 00 2C 04 00 00 00 00
757 0 57.158760750 HID Input 1 01 00 00 04 00 00 00 00 00
758 0 57.247519000 HID Input 1 01 00 00 00 00 00 00 00 00
759 0 57.292522125 HID Input 1 01 00 00 2C 00 00 00 00 00
760 0 57.382531000 HID Input 1 01 00 00 2C 06 00 00 00 00
761 0 57.517541500 HID Input 1 01 00 00 00 00 00 00 00 00
762 0 57.518791500 HID Input 1 01 00 00 12 00 00 00 00 00
763 0 57.607548750 HID Input 1 01 00 00 00 00 00 00 00 00
764 0 57.652552250 HID Input 1 01 00 00 11 00 00 00 00 00
765 0 57.742559750 HID Input 1 01 00 00 00 00 00 00 00 00
766 0 57.832567250 HID Input 1 01 00 00 11 00 00 00 00 00
767 0 57.877572375 HID Input 1 01 00 00 11 08 00 00 00 00
768 0 57.922575875 HID Input 1 01 00 00 11 00 00 00 00 00
769 0 57.967580250 HID Input 1 01 00 00 00 00 00 00 00 00
770 0 58.012583250 HID Input 1 01 00 00 06 00 00 00 00 00
771 0 58.102590750 HID Input 1 01 00 00 00 00 00 00 00 00
772 0 58.192599000 HID Input 1 01 00 00 17 00 00 00 00 00
773 0 58.282606625 HID Input 1 01 00 00 17 0C 00 00 00 00
774 0 58.327609125 HID Input 1 01 00 00 0C 00 00 00 00 00
775 0 58.372612500 HID Input 1 01 00 00 0C 12 00 00 00 00
776 0 58.373862500 HID Input 1 01 00 00 12 00 00 00 00 00
777 0 58.462618125 HID Input 1 01 00 00 12 11 00 00 00 00
778 0 58.507622375 HID Input 1 01 00 00 12 11 2C 00 00 00
779 0 58.508872375 HID Input 1 01 00 00 2C 11 00 00 00 00
780 0 58.552624250 HID Input 1 01 00 00 2C 00 00 00 00 00
781 0 58.597627500 HID Input 1 01 00 00 2C 04 00 00 00 00
782 0 58.642631250 HID Input 1 01 00 00 04 00 00 00 00 00
783 0 58.687634750 HID Input 1 01 00 00 04 13 00 00 00 00
784 0 58.688884625 HID Input 1 01 00 00 13 00 00 00 00 00
785 0 58.732638750 HID Input 1 01 00 00 00 00 00 00 00 00
786 0 58.822646125 HID Input 1 01 00 00 13 00 00 00 00 00
787 0 58.912654125 HID Input 1 01 00 00 13 08 00 00 00 00
788 0 59.002661500 HID Input 1 01 00 00 13 08 04 00 00 00
789 0 59.003911500 HID Input 1 01 00 00 13 04 00 00 00 00
790 0 59.047665000 HID Input 1 01 00 00 04 00 00 00 00 00
791 0 59.092668625 HID Input 1 01 00 00 00 00 00 00 00 00
792 0 59.137671250 HID Input 1 01 00 00 15 00 00 00 00 00
793 0 59.227679750 HID Input 1 01 00 00 00 00 00 00 00 00
794 0 59.272683500 HID Input 1 01 00 00 0C 00 00 00 00 00
795 0 59.407694500 HID Input 1 01 00 00 0C 11 0A 00 00 00
796 0 59.452698250 HID Input 1 01 00 00 0A 11 00 00 00 00
797 0 59.453948250 HID Input 1 01 00 00 0A 00 00 00 00 00
798 0 59.497703125 HID Input 1 01 00 00 00 00 00 00 00 00
799 0 59.498953125 HID Input 1 01 00 00 2C 00 00 00 00 00
800 0 59.632713000 HID Input 1 01 00 00 00 00 00 00 00 00
801 0 59.633963000 HID Input 1 01 00 00 17 00 00 00 00 00
802 0 59.722715250 HID Input 1 01 00 00 17 12 00 00 00 00
803 0 59.723965250 HID Input 1 01 00 00 12 00 00 00 00 00
804 0 59.767718375 HID Input 1 01 00 00 12 2C 00 00 00 00
805 0 59.857727375 HID Input 1 01 00 00 12 2C 05 00 00 00
806 0 59.902730250 HID Input 1 01 00 00 05 2C 00 00 00 00
807 0 59.903980250 HID Input 1 01 00 00 2C 00 00 00 00 00
808 0 59.947732125 HID Input 1 01 00 00 00 00 00 00 00 00
809 0 59.992735500 HID Input 1 01 00 00 08 00 00 00 00 00
810 0 60.037739000 HID Input 1 01 00 00 08 2C 00 00 00 00
811 0 60.082743625 HID Input 1 01 00 00 2C 00 00 00 00 00
812 0 60.172751000 HID Input 1 01 00 00 2C 09 00 00 00 00
813 0 60.174001000 HID Input 1 01 00 00 09 00 00 00 00 00
814 0 60.262759500 HID Input 1 01 00 00 00 00 00 00 00 00
815 0 60.307763625 HID Input 1 01 00 00 15 00 00 00 00 00
816 0 60.397771000 HID Input 1 01 00 00 15 12 00 00 00 00
817 0 60.399021000 HID Input 1 01 00 00 12 00 00 00 00 00
818 0 60.442772250 HID Input 1 01 00 00 12 10 00 00 00 00
819 0 60.487776000 HID Input 1 01 00 00 12 10 2C 00 00 00
820 0 60.577784000 HID Input 1 01 00 00 12 2C 00 00 00 00
821 0 60.579033875 HID Input 1 01 00 00 2C 00 00 00 00 00
822 0 60.622788500 HID Input 1 01 00 00 2C 17 00 00 00 00
823 0 60.624038625 HID Input 1 01 00 00 17 00 00 00 00 00
824 0 60.667791250 HID Input 1 01 00 00 00 00 00 00 00 00
825 0 60.712794375 HID Input 1 01 00 00 08 00 00 00 00 00
826 0 60.714044500 HID Input 1 01 00 00 08 0B 00 00 00 00
827 0 60.802801875 HID Input 1 01 00 00 08 0B 2C 00 00 00
828 0 60.804052000 HID Input 1 01 00 00 08 2C 00 00 00 00
829 0 60.847804000 HID Input 1 01 00 00 2C 00 00 00 00 00
830 0 60.937812125 HID Input 1 01 00 00 2C 17 00 00 00 00
831 0 60.939062375 HID Input 1 01 00 00 17 00 00 00 00 00
832 0 60.982813125 HID Input 1 01 00 00 00 00 00 00 00 00
833 0 61.072820000 HID Input 1 01 00 00 15 00 00 00 00 00
834 0 61.162828125 HID Input 1 01 00 00 00 00 00 00 00 00
835 0 61.207832375 HID Input 1 01 00 00 18 00 00 00 00 00
836 0 61.252834500 HID Input 1 01 00 00 18 16 00 00 00 00
837 0 61.344092625 HID Input 1 01 00 00 16 00 00 00 00 00
838 0 61.387843500 HID Input 1 01 00 00 00 00 00 00 00 00
839 0 61.432846875 HID Input 1 01 00 00 17 00 00 00 00 00
840 0 61.522854875 HID Input 1 01 00 00 00 00 00 00 00 00
841 0 61.567857750 HID Input 1 01 00 00 08 00 00 00 00 00
842 0 61.657865625 HID Input 1 01 00 00 00 00 00 00 00 00
843 0 61.702869375 HID Input 1 01 00 00 07 00 00 00 00 00
844 0 61.837880125 HID Input 1 01 00 00 00 00 00 00 00 00
845 0 62.332919500 HID Input 1 01 00 00 2C 00 00 00 00 00
846 0 62.422927500 HID Input 1 01 00 00 2C 10 00 00 00 00
847 0 62.424177500 HID Input 1 01 00 00 10 00 00 00 00 00
848 0 62.557937875 HID Input 1 01 00 00 10 04 00 00 00 00
849 0 62.602940875 HID Input 1 01 00 00 04 00 00 00 00 00
850 0 62.604190750 HID Input 1 01 00 00 00 00 00 00 00 00
851 0 62.692948750 HID Input 1 01 00 00 06 00 00 00 00 00
852 0 62.737952750 HID Input 1 01 00 00 06 0B 00 00 00 00
853 0 62.782957500 HID Input 1 01 00 00 0B 00 00 00 00 00
854 0 62.872964375 HID Input 1 01 00 00 00 00 00 00 00 00
855 0 62.874214250 HID Input 1 01 00 00 0C 00 00 00 00 00
856 0 62.962971250 HID Input 1 01 00 00 0C 11 00 00 00 00
857 0 63.007974750 HID Input 1 01 00 00 0C 11 08 00 00 00
858 0 63.052978125 HID Input 1 01 00 00 08 11 00 00 00 00
859 0 63.054228125 HID Input 1 01 00 00 08 00 00 00 00 00
860 0 63.097981750 HID Input 1 01 00 00 00 00 00 00 00 00
861 0 63.187990000 HID Input 1 01 00 00 37 00 00 00 00 00
862 0 63.323001250 HID Input 1 01 00 00 00 00 00 00 00 00
863 0 63.593020125 HID Input 1 01 00 00 28 00 00 00 00 00
864 0 63.683028125 HID Input 1 01 00 00 00 00 00 00 00 00
865 0 63.773035125 HID Input 1 01 00 00 28 00 00 00 00 00
866 0 63.818038625 HID Input 1 01 00 00 00 00 00 00 00 00

View File

@ -0,0 +1,67 @@
#!/usr/bin/python
# produce a sync word for a given LAP
lap = 0xffffff
pn = 0x83848D96BBCC54FC
# generator matrix for (64,30) linear block code
# based on polynomial 0260534236651
# (see gen_check_tables.py for automatic generation)
g = (
0x8000000000000001,
0x40000002c2b89ed4,
0x20000001615c4f6a,
0x10000000b0ae27b5,
0x080000029aef8d0e,
0x040000014d77c687,
0x0200000264037d97,
0x01000003f0b9201f,
0x008000033ae40edb,
0x004000035fca99b9,
0x002000036d5dd208,
0x00100001b6aee904,
0x00080000db577482,
0x000400006dabba41,
0x00020002f46d43f4,
0x000100017a36a1fa,
0x00008000bd1b50fd,
0x000040029c3536aa,
0x000020014e1a9b55,
0x0000100265b5d37e,
0x0000080132dae9bf,
0x000004025bd5ea0b,
0x00000203ef526bd1,
0x000001033511ab3c,
0x000000819a88d59e,
0x00000040cd446acf,
0x00000022a41aabb3,
0x0000001390b5cb0d,
0x0000000b0ae27b52,
0x0000000585713da9)
def encode(data):
assert data < 2**30
codeword = 0
for i in range(30):
if (data & (0x20000000 >> i)):
codeword ^= g[i]
return codeword
# append barker code
if (lap & 0x800000):
data = 0x13000000 | lap
else:
data = 0x2c000000 | lap
# scramble
data ^= (pn >> 34)
# encode
codeword = encode(data)
# scramble again
syncword = codeword ^ pn
print "0x%06x 0x%016x 0x%016x" % (lap, codeword, syncword)

View File

@ -0,0 +1,23 @@
#!/usr/bin/env python
# Reverse the binary of thesebarker codes for the host code
barkers = (0x0d, 0x72)
distances = []
corrections = []
def count_bits(x):
i = 0
while x:
i += 1
x &= x - 1
return i
for i in range(128):
diffs = [(count_bits(barkers[0] ^ i), barkers[0]),
(count_bits(barkers[1] ^ i), barkers[1])]
diffs.sort()
distances.append(diffs[0][0])
corrections.append(diffs[0][1])
print "Barker distance:", distances
print "Barker correct:", ["0x%x" % c for c in corrections]

View File

@ -0,0 +1,59 @@
#!/usr/bin/python
# (64,30) linear block code stuff
polynomial = 0260534236651
# produce generator matrix g
g = []
for i in range(30):
g.append(polynomial << i)
for j in range(i):
if g[i] & (1 << (33 + i - j)):
g[i] ^= g[i-j-1]
#print
#for i in range(29,-1,-1):
#print "0x%016x," % g[i]
#print
# produce check matrix h
h = []
for i in range(34):
h.append(0)
for j in range(30):
h[i] |= (g[29-j] >> i) & 0x1
h[i] <<= 1
h[i] <<= 33
h[i] |= (0x1 << i)
#print
#for i in range(34):
#print "0x%016x," % h[i]
#print
# reverse the order
g = g[::-1]
h = h[::-1]
def count_bits(n):
i = 0
while n != 0:
n &= n - 1
i += 1
return i
def gen_syndrome(c):
assert c < 2**64
s = 0
# look for a faster GF(2) matrix multiplication algorithm
for i in range(34):
s <<= 1
s |= (count_bits(c & h[i]) % 2)
return s
# optimized check table generation (sw_check_tables.h)
for shift in range(8):
for i in range(256):
print "0x%09x, " % gen_syndrome(i<<(shift*8)),
print

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
num_channels = 40
bits = []
channels = {}
reg = 0x57
while not (len(bits) and reg==0x57):
if reg & 0x3f < num_channels and reg & 0x40:
channels[reg & 0x3f] = len(bits)
bit = (reg & 1)
bits.append(bit)
reg >>= 1
reg |= (bit << 6)
reg ^= (bit << 2)
print bits
print "\nArray index:"
for k in sorted(channels.keys()):
print channels[k]

View File

@ -0,0 +1,36 @@
# Copyright 2011 Michael Ossmann, Dominic Spill
#
# This file is part of Project Ubertooth.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
CC ?= gcc
SOURCE_FILES = test_syndromes.c
LIBRARY_SOURCE = ../bluetooth_packet.c
BINARY_FILES = test_syndromes
HEADER_FILES = ../bluetooth_packet.h
CFLAGS += -DHASH_FUNCTION=HASH_FNV -DHASH_EMIT_KEYS=3
all: test_packet
test_packet:
$(CC) $(CFLAGS) $(CPPFLAGS) -O2 -Wall $(LIBRARY_SOURCE) $(SOURCE_FILES) -o $(BINARY_FILES)
clean:
rm -f $(BINARY_FILES)

View File

@ -0,0 +1,122 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2011 Dominic Spill, Michael Ossmann
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../bluetooth_packet.h"
#include <stdio.h>
int test_unfec23() {
char *optr;
int i, j, ret, err;
ret = 0;
printf("Testing unfec23\n");
printf("---------------\n");
char input[20][15] = {
/* No errors */
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1},
/* Errors */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}
};
char output[20][15] = {
/* No errors */
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
/* Errors */
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
};
for(i = 0; i < 20; i++) {
if (optr = unfec23(input[i], 1)) {
err = 0;
for(j = 0; j < 10; j++) {
if (optr[j] != output[i][j]) {
err = 1;
break;
}
}
if (err == 1) {
printf("E");
ret++;
}
else
printf(".");
} else {
printf("F");
ret++;
}
}
if (ret > 0)
printf("%d errors\n", ret);
printf("\n--------------------\n");
printf("Done testing unfec23\n");
return ret;
}
int main(int argc, char** argv) {
int ret = 0;
ret += test_unfec23();
exit(ret);
}

View File

@ -0,0 +1,118 @@
/* -*- c -*- */
/*
* Copyright 2012 Dominic Spill
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*
UAP Data HEC Header (octal)
----------------------------------
00 123 e1 770007 007070 000777
47 123 06 770007 007007 700000
00 124 32 007007 007007 007700
47 124 d5 007007 007070 707077
00 125 5a 707007 007007 077070
47 125 bd 707007 007070 777707
00 126 e2 077007 007007 000777
47 126 05 077007 007070 700000
00 127 8a 777007 007007 070007
47 127 6d 777007 007070 770770
00 11b 9e 770770 007007 777007
47 11b 79 770770 007070 077770
00 11c 4d 007770 007070 770070
47 11c aa 007770 007007 070707
00 11d 25 707770 007070 700700
47 11d c2 707770 007007 000077
00 11e 9d 077770 007070 777007
47 11e 7a 077770 007007 077770
00 11f f5 777770 007070 707777
47 11f 12 777770 007007 007000
*/
#include "../bluetooth_packet_tx.h"
#include <stdio.h>
int test_gen_packet_header() {
char *optr;
int i, j, ret, err;
ret = 0;
printf("Testing header\n");
printf("---------------\n");
/* lt_addr, type, flow, arqn, seqn, UAP, HEC */
uint8_t data[20][7] = {
{},
{},
{},
{},
{},
{},
{},
{},
{},
{}
UAP Data HE
-----------
00 123 e1
47 123 06
00 124 32
47 124 d5
00 125 5a
47 125 bd
00 126 e2
47 126 05
00 127 8a
47 127 6d
00 11b 9e
47 11b 79
00 11c 4d
47 11c aa
00 11d 25
47 11d c2
00 11e 9d
47 11e 7a
00 11f f5
47 11f 12
};
for(i = 0; i < 20; i++) {
gen_packet_header(uint8_t lt_addr, uint8_t type, uint8_t flow, uint8_t arqn, uint8_t seqn)
if (uap == 1) {
printf("E");
ret++;
}
else
printf(".");
}
if (ret > 0)
printf("%d errors\n", ret);
printf("\n--------------------\n");
printf("Done testing unfec23\n");
return ret;
}
int main(int argc, char** argv) {
int ret = 0;
ret += test_unfec23();
exit(ret);
}

View File

@ -0,0 +1,100 @@
/* -*- c -*- */
/*
* Copyright 2007 - 2011 Dominic Spill, Michael Ossmann
*
* This file is part of libbtbb
*
* 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, 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 libbtbb; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../bluetooth_packet.h"
#include <stdio.h>
int test_syndromes() {
int ret, i;
uint64_t syndrome, syncword;
ret = 0;
printf("Testing syndromes\n");
printf("-----------------\n");
uint64_t syndrome_input[2] = {
/* No errors */
0xcc7b7268ff614e1b,
/* Errors */
0xcc7d7268ff614e1b
};
uint64_t syndrome_output[2] = {
/* No errors */
0,
/* Errors */
0x0000000299c6f9b5
};
for(i = 0; i < 2; i++) {
syndrome = gen_syndrome(syndrome_input[i]);
if (syndrome == syndrome_output[i]) {
printf(".");
} else {
printf("F");
ret++;
}
}
uint64_t syncword_input[2] = {
/* No errors */
0xcc7b7268ff614e1b,
/* Errors */
0xcc7b7268ff514e1b
};
uint64_t syncword_output[2] = {
/* No errors */
0x4ffffffe44ad1ae7,
/* Errors */
0x4ffffffe44ad1ae7
};
gen_syndrome_map();
for(i = 0; i < 2; i++) {
syncword = decode_syncword(syncword_input[i] ^ pn);
if (syncword == syncword_output[i]) {
printf(".");
} else {
printf("F");
ret++;
}
}
if (ret > 0)
printf("%d errors\n", ret);
printf("\n-----------------\n");
printf("Done testing syndrome generation\n");
return ret;
}
int main(int argc, char** argv) {
int ret = 0;
ret += test_syndromes();
exit(ret);
}

View File

@ -0,0 +1,40 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Libbtbb - Bluetooth baseband library</title>
</head>
<body style="width:600px">
<h1>Libbtbb - Bluetooth baseband library</h1>
<p>Libbtbb is the Bluetooth baseband library used by the Ubertooth and
gr-bluetooth projects. It is freely available under the
<a href="http://www.gnu.org/licenses/gpl-2.0.html">GPL v2 license</a>.</p>
<h3>Getting libbtbb</h3>
<p>Libbtbb is built from source using either a released archive or the latest
code from our <a href="https://www.github.com/greatscottgadgets/libbtbb">git repository</a>.
To get started, do either of the following:</p>
<ul>
<li><a href="http://sourceforge.net/projects/libbtbb/files/latest/download?source=files">
Download the latest release</a></li>
<li>or clone the git repository using the following command:
<pre>git clone https://github.com/greatscottgadgets/libbtbb.git</pre></li>
<li style="list-style-type:none">If you prefer to use ssh and have a GitHub
account, you can use this command:
<pre>git clone git@github.com:greatscottgadgets/libbtbb.git</pre></li>
</ul>
<h3>Support</h3>
<p>Support for libbtbb is provided by
<a href="http://ubertooth.sourceforge.net/">project Ubertooth</a>, either using
the <a href="https://lists.sourceforge.net/lists/listinfo/ubertooth-general">
mailing list</a> or via IRC in #ubertooth on
<a href="http://freenode.net/irc_servers.shtml">chat.freenode.net</a></p>
<p>Bugs may be reported and tracked in the
<a href="https://github.com/greatscottgadgets/libbtbb/issues">ticketing system</a>.
Although it often helps to mention the bug report on the
<a href="https://lists.sourceforge.net/lists/listinfo/ubertooth-general">
Ubertooth mailing list</a> to be sure that it has been seen.</p>
</body>
</html>

View File

@ -0,0 +1,5 @@
Authors:
Allan M. Madsen <allan.m@madsen.dk>
Converted to plugin by:
Mike Ryan <mikeryan@lacklustre.net>

View File

@ -0,0 +1,88 @@
# CMakeLists.txt
#
# $Id: CMakeLists.txt 31995 2010-02-24 22:32:10Z jmayer $
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
project(btatt-wireshark-plugin C)
cmake_minimum_required(VERSION 2.6)
set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
IF ( NOT CMAKE_INSTALL_LIBDIR )
set(CMAKE_INSTALL_LIBDIR ~/.wireshark/plugins)
ENDIF ( NOT CMAKE_INSTALL_LIBDIR )
MESSAGE (STATUS "Plugin will be installed in: ${CMAKE_INSTALL_LIBDIR}")
INCLUDE(UseMakeDissectorReg)
set(GLIB2_MIN_VERSION 2.4.0)
find_package(GLIB2)
include_directories (${GLIB2_INCLUDE_DIRS})
find_package(Wireshark)
include_directories (${WIRESHARK_INCLUDE_DIRS})
set(LINK_MODE_LIB SHARED)
set(LINK_MODE_MODULE MODULE)
set(DISSECTOR_SRC
packet-btatt.c
)
set(PLUGIN_FILES
plugin.c
${DISSECTOR_SRC}
)
set(CLEAN_FILES
${PLUGIN_FILES}
)
if (WERROR)
set_source_files_properties(
${CLEAN_FILES}
PROPERTIES
COMPILE_FLAGS -Werror
)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
register_dissector_files(plugin.c
plugin
${DISSECTOR_SRC}
)
add_library(btatt ${LINK_MODE_MODULE}
${PLUGIN_FILES}
)
set_target_properties(btatt PROPERTIES PREFIX "")
set_target_properties(btatt PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
target_link_libraries(btatt wireshark)
install(TARGETS btatt
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ NAMELINK_SKIP
)

View File

@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
<signature of Ty Coon>, 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.

View File

@ -0,0 +1,125 @@
# Makefile.am
# Automake file for AgentX plugin
#
# $Id: Makefile.am 24488 2008-02-27 16:18:30Z stig $
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
INCLUDES = -I$(top_srcdir) -I$(includedir)
include Makefile.common
#if HAVE_WARNINGS_AS_ERRORS
#AM_CFLAGS = -Werror
#endif
plugindir = @plugindir@
plugin_LTLIBRARIES = btatt.la
btatt_la_SOURCES = \
plugin.c \
moduleinfo.h \
$(DISSECTOR_SRC) \
$(DISSECTOR_SUPPORT_SRC) \
$(DISSECTOR_INCLUDES)
btatt_la_LDFLAGS = -module -avoid-version
btatt_la_LIBADD = @PLUGIN_LIBS@
# Libs must be cleared, or else libtool won't create a shared module.
# If your module needs to be linked against any particular libraries,
# add them here.
LIBS =
#
# Build plugin.c, which contains the plugin version[] string, a
# function plugin_register() that calls the register routines for all
# protocols, and a function plugin_reg_handoff() that calls the handoff
# registration routines for all protocols.
#
# We do this by scanning sources. If that turns out to be too slow,
# maybe we could just require every .o file to have an register routine
# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
#
# Formatting conventions: The name of the proto_register_* routines an
# proto_reg_handoff_* routines must start in column zero, or must be
# preceded only by "void " starting in column zero, and must not be
# inside #if.
#
# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
#
# For some unknown reason, having a big "for" loop in the Makefile
# to scan all the files doesn't work with some "make"s; they seem to
# pass only the first few names in the list to the shell, for some
# reason.
#
# Therefore, we have a script to generate the plugin.c file.
# The shell script runs slowly, as multiple greps and seds are run
# for each input file; this is especially slow on Windows. Therefore,
# if Python is present (as indicated by PYTHON being defined), we run
# a faster Python script to do that work instead.
#
# The first argument is the directory in which the source files live.
# The second argument is "plugin", to indicate that we should build
# a plugin.c file for a plugin.
# All subsequent arguments are the files to scan.
#
plugin.c: $(DISSECTOR_SRC) $(top_srcdir)/tools/make-dissector-reg \
$(top_srcdir)/tools/make-dissector-reg.py
@if test -n "$(PYTHON)"; then \
echo Making plugin.c with python ; \
$(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
plugin $(DISSECTOR_SRC) ; \
else \
echo Making plugin.c with shell script ; \
$(top_srcdir)/tools/make-dissector-reg $(srcdir) \
$(plugin_src) plugin $(DISSECTOR_SRC) ; \
fi
#
# Currently plugin.c can be included in the distribution because
# we always build all protocol dissectors. We used to have to check
# whether or not to build the snmp dissector. If we again need to
# variably build something, making plugin.c non-portable, uncomment
# the dist-hook line below.
#
# Oh, yuk. We don't want to include "plugin.c" in the distribution, as
# its contents depend on the configuration, and therefore we want it
# to be built when the first "make" is done; however, Automake insists
# on putting *all* source into the distribution.
#
# We work around this by having a "dist-hook" rule that deletes
# "plugin.c", so that "dist" won't pick it up.
#
#dist-hook:
# @rm -f $(distdir)/plugin.c
CLEANFILES = \
btatt \
*~
MAINTAINERCLEANFILES = \
Makefile.in \
plugin.c
EXTRA_DIST = \
Makefile.common \
Makefile.nmake \
moduleinfo.nmake \
plugin.rc.in

View File

@ -0,0 +1,39 @@
# Makefile.common for AgentX plugin
# Contains the stuff from Makefile.am and Makefile.nmake that is
# a) common to both files and
# b) portable between both files
#
# $Id: Makefile.common 23848 2007-12-12 22:10:50Z jake $
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# the name of the plugin
PLUGIN_NAME = btatt
# the dissector sources (without any helpers)
DISSECTOR_SRC = \
packet-btatt.c
# corresponding headers
DISSECTOR_INCLUDES =
# Dissector helpers. They're included in the source files in this
# directory, but they're not dissectors themselves, i.e. they're not
# used to generate "plugin.c".
DISSECTOR_SUPPORT_SRC =

View File

@ -0,0 +1,100 @@
# Makefile.nmake
# nmake file for Wireshark plugin
#
# $Id: Makefile.nmake 24520 2008-03-01 12:31:01Z jake $
#
include ..\..\config.nmake
include moduleinfo.nmake
include Makefile.common
CFLAGS=/WX /DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) \
/I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS)
.c.obj::
$(CC) $(CFLAGS) -Fd.\ -c $<
LDFLAGS = $(PLUGIN_LDFLAGS)
!IFDEF ENABLE_LIBWIRESHARK
LINK_PLUGIN_WITH=..\..\epan\libwireshark.lib
CFLAGS=/DHAVE_WIN32_LIBWIRESHARK_LIB /D_NEED_VAR_IMPORT_ $(CFLAGS)
DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)
DISSECTOR_SUPPORT_OBJECTS = $(DISSECTOR_SUPPORT_SRC:.c=.obj)
OBJECTS = $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS) plugin.obj
RESOURCE=$(PLUGIN_NAME).res
all: $(PLUGIN_NAME).dll
$(PLUGIN_NAME).rc : moduleinfo.nmake
sed -e s/@PLUGIN_NAME@/$(PLUGIN_NAME)/ \
-e s/@RC_MODULE_VERSION@/$(RC_MODULE_VERSION)/ \
-e s/@RC_VERSION@/$(RC_VERSION)/ \
-e s/@MODULE_VERSION@/$(MODULE_VERSION)/ \
-e s/@PACKAGE@/$(PACKAGE)/ \
-e s/@VERSION@/$(VERSION)/ \
-e s/@MSVC_VARIANT@/$(MSVC_VARIANT)/ \
< plugin.rc.in > $@
$(PLUGIN_NAME).dll $(PLUGIN_NAME).exp $(PLUGIN_NAME).lib : $(OBJECTS) $(LINK_PLUGIN_WITH) $(RESOURCE)
link -dll /out:$(PLUGIN_NAME).dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \
$(GLIB_LIBS) $(RESOURCE)
#
# Build plugin.c, which contains the plugin version[] string, a
# function plugin_register() that calls the register routines for all
# protocols, and a function plugin_reg_handoff() that calls the handoff
# registration routines for all protocols.
#
# We do this by scanning sources. If that turns out to be too slow,
# maybe we could just require every .o file to have an register routine
# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
#
# Formatting conventions: The name of the proto_register_* routines an
# proto_reg_handoff_* routines must start in column zero, or must be
# preceded only by "void " starting in column zero, and must not be
# inside #if.
#
# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
#
# For some unknown reason, having a big "for" loop in the Makefile
# to scan all the files doesn't work with some "make"s; they seem to
# pass only the first few names in the list to the shell, for some
# reason.
#
# Therefore, we have a script to generate the plugin.c file.
# The shell script runs slowly, as multiple greps and seds are run
# for each input file; this is especially slow on Windows. Therefore,
# if Python is present (as indicated by PYTHON being defined), we run
# a faster Python script to do that work instead.
#
# The first argument is the directory in which the source files live.
# The second argument is "plugin", to indicate that we should build
# a plugin.c file for a plugin.
# All subsequent arguments are the files to scan.
#
!IFDEF PYTHON
plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg.py
@echo Making plugin.c (using python)
@$(PYTHON) "../../tools/make-dissector-reg.py" . plugin $(DISSECTOR_SRC)
!ELSE
plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg
@echo Making plugin.c (using sh)
@$(SH) ../../tools/make-dissector-reg . plugin $(DISSECTOR_SRC)
!ENDIF
!ENDIF
clean:
rm -f $(OBJECTS) $(RESOURCE) plugin.c *.pdb \
$(PLUGIN_NAME).dll $(PLUGIN_NAME).dll.manifest $(PLUGIN_NAME).lib \
$(PLUGIN_NAME).exp $(PLUGIN_NAME).rc
distclean: clean
maintainer-clean: distclean

View File

@ -0,0 +1,11 @@
Bluetooth ATT Protocol Dissector
================================
This is a plugin-ized version of the Bluetooth ATT protocol dissector
from the Wireshark trunk. I made the very minimal changes necessary to
get it to build as a plugin: defining a couple constants and changing an
include path.
This plugin is unneccessary if you are using Wireshark trunk. Only use
it if you are using a distro packaged Wireshark that does not have btatt
protocol support.

View File

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,27 @@
Copyright notice for the files copied from
http://www.opensync.org/browser/branches/3rd-party-cmake-modules/modules
$Id: COPYING-CMAKE-SCRIPTS 34248 2010-09-25 15:38:12Z jmayer $
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,238 @@
#
# $Id: FindGLIB2.cmake 34248 2010-09-25 15:38:12Z jmayer $
#
# - Try to find GLib2
# Once done this will define
#
# GLIB2_FOUND - system has GLib2
# GLIB2_INCLUDE_DIRS - the GLib2 include directory
# GLIB2_LIBRARIES - Link these to use GLib2
#
# HAVE_GLIB_GREGEX_H glib has gregex.h header and
# supports g_regex_match_simple
#
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
# Copyright (c) 2006 Philippe Bernery <philippe.bernery@gmail.com>
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
# Copyright (c) 2008 Michael Bell <michael.bell@web.de>
# Copyright (c) 2008-2009 Bjoern Ricks <bjoern.ricks@googlemail.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
# in cache already
SET(GLIB2_FOUND TRUE)
ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
INCLUDE(FindPkgConfig)
## Glib
IF ( GLIB2_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "REQUIRED" )
ELSE ( GLIB2_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "" )
ENDIF ( GLIB2_FIND_REQUIRED )
IF ( GLIB2_MIN_VERSION )
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} )
ELSE ( GLIB2_MIN_VERSION )
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 )
ENDIF ( GLIB2_MIN_VERSION )
IF ( PKG_CONFIG_FOUND )
IF ( GLIB2_FOUND )
SET ( GLIB2_CORE_FOUND TRUE )
ELSE ( GLIB2_FOUND )
SET ( GLIB2_CORE_FOUND FALSE )
ENDIF ( GLIB2_FOUND )
ENDIF ( PKG_CONFIG_FOUND )
# Look for glib2 include dir and libraries w/o pkgconfig
IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
FIND_PATH(
_glibconfig_include_DIR
NAMES
glibconfig.h
PATHS
/opt/gnome/lib64
/opt/gnome/lib
/opt/lib/
/opt/local/lib
/sw/lib/
/usr/lib64
/usr/lib
/usr/local/include
${CMAKE_LIBRARY_PATH}
PATH_SUFFIXES
glib-2.0/include
)
FIND_PATH(
_glib2_include_DIR
NAMES
glib.h
PATHS
/opt/gnome/include
/opt/local/include
/sw/include
/usr/include
/usr/local/include
PATH_SUFFIXES
glib-2.0
)
#MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}")
FIND_LIBRARY(
_glib2_link_DIR
NAMES
glib-2.0
glib
PATHS
/opt/gnome/lib
/opt/local/lib
/sw/lib
/usr/lib
/usr/local/lib
)
IF ( _glib2_include_DIR AND _glib2_link_DIR )
SET ( _glib2_FOUND TRUE )
ENDIF ( _glib2_include_DIR AND _glib2_link_DIR )
IF ( _glib2_FOUND )
SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} )
SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} )
SET ( GLIB2_CORE_FOUND TRUE )
ELSE ( _glib2_FOUND )
SET ( GLIB2_CORE_FOUND FALSE )
ENDIF ( _glib2_FOUND )
# Handle dependencies
# libintl
IF ( NOT LIBINTL_FOUND )
FIND_PATH(LIBINTL_INCLUDE_DIR
NAMES
libintl.h
PATHS
/opt/gnome/include
/opt/local/include
/sw/include
/usr/include
/usr/local/include
)
FIND_LIBRARY(LIBINTL_LIBRARY
NAMES
intl
PATHS
/opt/gnome/lib
/opt/local/lib
/sw/lib
/usr/local/lib
/usr/lib
)
IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
SET (LIBINTL_FOUND TRUE)
ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
ENDIF ( NOT LIBINTL_FOUND )
# libiconv
IF ( NOT LIBICONV_FOUND )
FIND_PATH(LIBICONV_INCLUDE_DIR
NAMES
iconv.h
PATHS
/opt/gnome/include
/opt/local/include
/opt/local/include
/sw/include
/sw/include
/usr/local/include
/usr/include
PATH_SUFFIXES
glib-2.0
)
FIND_LIBRARY(LIBICONV_LIBRARY
NAMES
iconv
PATHS
/opt/gnome/lib
/opt/local/lib
/sw/lib
/usr/lib
/usr/local/lib
)
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
SET (LIBICONV_FOUND TRUE)
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
ENDIF ( NOT LIBICONV_FOUND )
IF (LIBINTL_FOUND)
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
ENDIF (LIBINTL_FOUND)
IF (LIBICONV_FOUND)
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
ENDIF (LIBICONV_FOUND)
ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
##
IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
SET (GLIB2_FOUND TRUE)
ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
IF (GLIB2_FOUND)
IF (NOT GLIB2_FIND_QUIETLY)
MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}")
ENDIF (NOT GLIB2_FIND_QUIETLY)
ELSE (GLIB2_FOUND)
IF (GLIB2_FIND_REQUIRED)
MESSAGE (SEND_ERROR "Could not find GLib2")
ENDIF (GLIB2_FIND_REQUIRED)
ENDIF (GLIB2_FOUND)
# show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES)
MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS)
IF ( WIN32 )
# include libiconv for win32
IF ( NOT LIBICONV_FOUND )
FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h PATH_SUFFIXES glib-2.0)
FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv)
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
SET (LIBICONV_FOUND TRUE)
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
ENDIF ( NOT LIBICONV_FOUND )
IF (LIBICONV_FOUND)
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
ENDIF (LIBICONV_FOUND)
ENDIF ( WIN32 )
IF ( GLIB2_FOUND )
# Check if system has a newer version of glib
# which supports g_regex_match_simple
INCLUDE( CheckIncludeFiles )
SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} )
CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H )
CHECK_INCLUDE_FILES ( glib/gchecksum.h HAVE_GLIB_GCHECKSUM_H )
# Reset CMAKE_REQUIRED_INCLUDES
SET( CMAKE_REQUIRED_INCLUDES "" )
ENDIF( GLIB2_FOUND )

View File

@ -0,0 +1,28 @@
#
# Try to find the wireshark library and its includes
#
# This snippet sets the following variables:
# WIRESHARK_FOUND True if wireshark library got found
# WIRESHARK_INCLUDE_DIRS Location of the wireshark headers
# WIRESHARK_LIBRARIES List of libraries to use wireshark
#
# Copyright (c) 2011 Reinhold Kainhofer <reinhold@kainhofer.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
# wireshark does not install its library with pkg-config information,
# so we need to manually find the libraries and headers
FIND_PATH( WIRESHARK_INCLUDE_DIRS epan/packet.h PATH_SUFFIXES wireshark )
FIND_LIBRARY( WIRESHARK_LIBRARIES wireshark )
# Report results
IF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
SET( WIRESHARK_FOUND 1 )
ELSE ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
MESSAGE( SEND_ERROR "Could NOT find the wireshark library and headers" )
ENDIF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )

View File

@ -0,0 +1,33 @@
#
# $Id: UseMakeDissectorReg.cmake 33616 2010-07-22 12:18:36Z stig $
#
MACRO(REGISTER_DISSECTOR_FILES _outputfile _registertype )
# FIXME: Only the Python stuff has been implemented
# Make this into a MACRO, to avoid duplication with plugins/.../
#register.c: $(plugin_src) $(ALL_DISSECTORS_SRC) $(top_srcdir)/tools/make-dissector-reg \
# $(top_srcdir)/tools/make-dissector-reg.py
# @if test -n "$(PYTHON)"; then \
# echo Making register.c with python ; \
# $(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
# dissectors $(ALL_DISSECTORS_SRC) ; \
# else \
# echo Making register.c with shell script ; \
# $(top_srcdir)/tools/make-dissector-reg $(srcdir) \
# dissectors $(plugin_src) $(ALL_DISSECTORS_SRC) ; \
# fi
set( _sources ${ARGN} )
ADD_CUSTOM_COMMAND(
OUTPUT
${_outputfile}
COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
${CMAKE_CURRENT_SOURCE_DIR}
${_registertype}
${_sources}
DEPENDS
${_sources}
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
)
ENDMACRO(REGISTER_DISSECTOR_FILES)

View File

@ -0,0 +1,17 @@
/* Included *after* config.h, in order to re-define these macros */
#ifdef PACKAGE
#undef PACKAGE
#endif
/* Name of package */
#define PACKAGE "btle"
#ifdef VERSION
#undef VERSION
#endif
/* Version number of package */
#define VERSION "0.0.1"

View File

@ -0,0 +1,28 @@
#
# $Id: moduleinfo.nmake 20155 2006-12-19 22:22:34Z jake $
#
# The name
PACKAGE=btle
# The version
MODULE_VERSION_MAJOR=0
MODULE_VERSION_MINOR=0
MODULE_VERSION_MICRO=0
MODULE_VERSION_EXTRA=1
#
# The RC_VERSION should be comma-separated, not dot-separated,
# as per Graham Bloice's message in
#
# http://www.ethereal.com/lists/ethereal-dev/200303/msg00283.html
#
# "The RC_VERSION variable in config.nmake should be comma separated.
# This allows the resources to be built correctly and the version
# number to be correctly displayed in the explorer properties dialog
# for the executables, and XP's tooltip, rather than 0.0.0.0."
#
MODULE_VERSION=$(MODULE_VERSION_MAJOR).$(MODULE_VERSION_MINOR).$(MODULE_VERSION_MICRO).$(MODULE_VERSION_EXTRA)
RC_MODULE_VERSION=$(MODULE_VERSION_MAJOR),$(MODULE_VERSION_MINOR),$(MODULE_VERSION_MICRO),$(MODULE_VERSION_EXTRA)

View File

@ -0,0 +1,698 @@
/* packet-btatt.c
* Routines for Bluetooth Attribute Protocol dissection
*
* Copyright 2012, Allan M. Madsen <allan.m@madsen.dk>
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* 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 <epan/packet.h>
#include <epan/prefs.h>
#include <epan/expert.h>
#include <epan/dissectors/packet-btl2cap.h>
#define BTL2CAP_PSM_ATT 0x001f
#define BTL2CAP_FIXED_CID_ATT 0x0004
/* Initialize the protocol and registered fields */
static int proto_btatt = -1;
static int hf_btatt_opcode = -1;
static int hf_btatt_handle = -1;
static int hf_btatt_starting_handle = -1;
static int hf_btatt_ending_handle = -1;
static int hf_btatt_group_end_handle = -1;
static int hf_btatt_value = -1;
static int hf_btatt_req_opcode_in_error = -1;
static int hf_btatt_handle_in_error = -1;
static int hf_btatt_error_code = -1;
static int hf_btatt_uuid16 = -1;
static int hf_btatt_uuid128 = -1;
static int hf_btatt_client_rx_mtu = -1;
static int hf_btatt_server_rx_mtu = -1;
static int hf_btatt_uuid_format = -1;
static int hf_btatt_length = -1;
static int hf_btatt_offset = -1;
static int hf_btatt_flags = -1;
static int hf_btatt_sign_counter = -1;
static int hf_btatt_signature = -1;
/* Initialize the subtree pointers */
static gint ett_btatt = -1;
static gint ett_btatt_list = -1;
/* Opcodes */
static const value_string opcode_vals[] = {
{0x01, "Error Response"},
{0x02, "Exchange MTU Request"},
{0x03, "Exchange MTU Response"},
{0x04, "Find Information Request"},
{0x05, "Find Information Response"},
{0x06, "Find By Type Value Request"},
{0x07, "Find By Type Value Response"},
{0x08, "Read By Type Request"},
{0x09, "Read By Type Response"},
{0x0a, "Read Request"},
{0x0b, "Read Response"},
{0x0c, "Read Blob Request"},
{0x0d, "Read Blob Response"},
{0x0e, "Read Multiple Request"},
{0x0f, "Read Multiple Response"},
{0x10, "Read By Group Type Request"},
{0x11, "Read By Group Type Response"},
{0x12, "Write Request"},
{0x13, "Write Response"},
{0x16, "Prepare Write Request"},
{0x17, "Prepare Write Response"},
{0x18, "Execute Write Request"},
{0x19, "Execute Write Response"},
{0x1B, "Handle Value Notification"},
{0x1D, "Handle Value Indication"},
{0x1E, "Handle Value Confirmation"},
{0x52, "Write Command"},
{0xD2, "Signed Write Command"},
{0x0, NULL}
};
/* Error codes */
static const value_string error_vals[] = {
{0x01, "Invalid Handle"},
{0x02, "Read Not Permitted"},
{0x03, "Write Not Permitted"},
{0x04, "Invalid PDU"},
{0x05, "Insufficient Authentication"},
{0x06, "Request Not Supported"},
{0x07, "Invalid Offset"},
{0x08, "Insufficient Authorization"},
{0x09, "Prepare Queue Full"},
{0x0a, "Attribute Not Found"},
{0x0b, "Attribute Not Long"},
{0x0c, "Insufficient Encryption Key Size"},
{0x0d, "Invalid Attribute Value Length"},
{0x0e, "Unlikely Error"},
{0x0f, "Insufficient Encryption"},
{0x10, "Unsupported Group Type"},
{0x11, "Insufficient Resources"},
{0x80, "Application Error"},
{0xfd, "Improper Client Characteristic Configuration Descriptor"},
{0xfe, "Procedure Already In Progress"},
{0xff, "Out of Range"},
{0x0, NULL}
};
static const value_string uuid_vals[] = {
/* Services - http://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
{0x1800, "Generic Access"},
{0x1801, "Generic Attribute"},
{0x1802, "Immediate Alert"},
{0x1803, "Link Loss"},
{0x1804, "Tx Power"},
{0x1805, "Current Time Service"},
{0x1806, "Reference Time Update Service"},
{0x1807, "Next DST Change Service"},
{0x1808, "Glucose"},
{0x1809, "Health Thermometer"},
{0x180a, "Device Information"},
{0x180d, "Heart Rate"},
{0x180e, "Phone Alert Status Service"},
{0x180f, "Battery Service"},
{0x1810, "Blood Pressure"},
{0x1811, "Alert Notification Service"},
{0x1812, "Human Interface Device"},
{0x1813, "Scan Parameters"},
{0x1814, "Running Speed and Cadence"},
{0x1816, "Cycling Speed and Cadence"},
/* Declarations - http://developer.bluetooth.org/gatt/declarations/Pages/DeclarationsHome.aspx */
{0x2800, "GATT Primary Service Declaration"},
{0x2801, "GATT Secondary Service Declaration"},
{0x2802, "GATT Include Declaration"},
{0x2803, "GATT Characteristic Declaration"},
/* Descriptors - http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx */
{0x2900, "Characteristic Extended Properties"},
{0x2901, "Characteristic User Description"},
{0x2902, "Client Characteristic Configuration"},
{0x2903, "Server Characteristic Configuration"},
{0x2904, "Characteristic Presentation Format"},
{0x2905, "Characteristic Aggregate Format"},
{0x2906, "Valid Range"},
{0x2907, "External Report Reference"},
{0x2908, "Report Reference"},
/* Characteristics - http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx */
{0x2a00, "Device Name"},
{0x2a01, "Appearance"},
{0x2a02, "Peripheral Privacy Flag"},
{0x2a03, "Reconnection Address"},
{0x2a04, "Peripheral Preferred Connection Parameters"},
{0x2a05, "Service Changed"},
{0x2a06, "Alert Level"},
{0x2a07, "Tx Power Level"},
{0x2a08, "Date Time"},
{0x2a09, "Day of Week"},
{0x2a0a, "Day Date Time"},
{0x2a0c, "Exact Time 256"},
{0x2a0d, "DST Offset"},
{0x2a0e, "Time Zone"},
{0x2a0f, "Local Time Information"},
{0x2a11, "Time with DST"},
{0x2a12, "Time Accuracy"},
{0x2a13, "Time Source"},
{0x2a14, "Reference Time Information"},
{0x2a16, "Time Update Control Point"},
{0x2a17, "Time Update State"},
{0x2a18, "Glucose Measurement"},
{0x2a19, "Battery Level"},
{0x2a1c, "Temperature Measurement"},
{0x2a1d, "Temperature Type"},
{0x2a1e, "Intermediate Temperature"},
{0x2a21, "Measurement Interval"},
{0x2a22, "Boot Keyboard Input Report"},
{0x2a23, "System ID"},
{0x2a24, "Model Number String"},
{0x2a25, "Serial Number String"},
{0x2a26, "Firmware Revision String"},
{0x2a27, "Hardware Revision String"},
{0x2a28, "Software Revision String"},
{0x2a29, "Manufacturer Name String"},
{0x2a2a, "IEEE 11073-20601 Reg. Cert. Data List"},
{0x2a2b, "Current Time"},
{0x2a31, "Scan Refresh"},
{0x2a32, "Boot Keyboard Output Report"},
{0x2a33, "Boot Mouse Input Report"},
{0x2a34, "Glucose Measurement Context"},
{0x2a35, "Blood Pressure Measurement"},
{0x2a36, "Intermediate Cuff Pressure"},
{0x2a37, "Heart Rate Measurement"},
{0x2a38, "Body Sensor Location"},
{0x2a39, "Heart Rate Control Point"},
{0x2a3f, "Alert Status"},
{0x2a40, "Ringer Control Point"},
{0x2a41, "Ringer Setting"},
{0x2a42, "Alert Category ID Bit Mask"},
{0x2a43, "Alert Category ID"},
{0x2a44, "Alert Notification Control Point"},
{0x2a45, "Unread Alert Status"},
{0x2a46, "New Alert"},
{0x2a47, "Supported New Alert Category"},
{0x2a48, "Supported Unread Alert Category"},
{0x2a49, "Blood Pressure Feature"},
{0x2a4a, "HID Information"},
{0x2a4b, "Report Map"},
{0x2a4c, "HID Control Point"},
{0x2a4d, "Report"},
{0x2a4e, "Protocol Mode"},
{0x2a4f, "Scan Interval Window"},
{0x2a50, "PnP ID"},
{0x2a51, "Glucose Feature"},
{0x2a52, "Record Access Control Point"},
{0x2a53, "RSC Measurement"},
{0x2a54, "RSC Feature"},
{0x2a55, "SC Control Point"},
{0x2a5b, "CSC Measurement"},
{0x2a5c, "CSC Feature"},
{0x2a5d, "Sensor Location"},
{0x0, NULL}
};
static value_string_ext uuid_vals_ext = VALUE_STRING_EXT_INIT(uuid_vals);
static const value_string uuid_format_vals[] = {
{0x01, "16-bit UUIDs"},
{0x02, "128-bit UUIDs"},
{0x0, NULL}
};
static const value_string flags_vals[] = {
{0x00, "Cancel All"},
{0x01, "Immediately Write All"},
{0x0, NULL}
};
static void
dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
int offset = 0;
proto_item *ti, *item;
proto_tree *st, *ltree;
guint8 opcode;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATT");
switch (pinfo->p2p_dir) {
case P2P_DIR_SENT:
col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
break;
case P2P_DIR_RECV:
col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
break;
case P2P_DIR_UNKNOWN:
break;
default:
col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
pinfo->p2p_dir);
break;
}
if (tvb_length_remaining(tvb, 0) < 1)
return;
ti = proto_tree_add_item(tree, proto_btatt, tvb, 0, -1, ENC_NA);
st = proto_item_add_subtree(ti, ett_btatt);
item = proto_tree_add_item(st, hf_btatt_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN);
opcode = tvb_get_guint8(tvb, 0);
offset++;
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(opcode, opcode_vals, "<unknown>"));
switch (opcode) {
case 0x01: /* Error Response */
proto_tree_add_item(st, hf_btatt_req_opcode_in_error, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
proto_tree_add_item(st, hf_btatt_handle_in_error, tvb, offset, 2, ENC_LITTLE_ENDIAN);
col_append_fstr(pinfo->cinfo, COL_INFO, " - %s, Handle: 0x%04x",
val_to_str(tvb_get_guint8(tvb, offset+2), error_vals, "<unknown>"),
tvb_get_letohs(tvb, offset));
offset += 2;
proto_tree_add_item(st, hf_btatt_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
break;
case 0x02: /* Exchange MTU Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Client Rx MTU: %u", tvb_get_letohs(tvb, offset));
proto_tree_add_item(st, hf_btatt_client_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
break;
case 0x03: /* Exchange MTU Response */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Server Rx MTU: %u", tvb_get_letohs(tvb, offset));
proto_tree_add_item(st, hf_btatt_server_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
break;
case 0x04: /* Find Information Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handles: 0x%04x..0x%04x",
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
break;
case 0x05: /* Find Information Response */
{
guint8 format = tvb_get_guint8(tvb, offset);
item = proto_tree_add_item(st, hf_btatt_uuid_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
if( format == 1 ) {
while( tvb_length_remaining(tvb, offset) > 0) {
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
}
}
else if( format == 2 ) {
while( tvb_length_remaining(tvb, offset) > 0) {
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
offset += 16;
}
}
else {
expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "Unknown format");
}
}
break;
case 0x06: /* Find By Type Value Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x",
val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"),
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
if( tvb_length_remaining(tvb, offset) > 0)
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
break;
case 0x07: /* Find By Type Value Response */
while( tvb_length_remaining(tvb, offset) > 0 ) {
item = proto_tree_add_text(st, tvb, offset, 4,
"Handles Info, Handle: 0x%04x, Group End Handle: 0x%04x",
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
ltree = proto_item_add_subtree(item, ett_btatt_list);
proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
}
break;
case 0x08: /* Read By Type Request */
case 0x10: /* Read By Group Type Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x",
val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"),
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
if (tvb_length_remaining(tvb, offset) == 2) {
proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
}
else if (tvb_length_remaining(tvb, offset) == 16) {
item = proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA);
proto_item_append_text(item, " (%s)", val_to_str_ext_const(tvb_get_letohs(tvb, offset),
&uuid_vals_ext, "<unknown>"));
offset += 16;
}
break;
case 0x09: /* Read By Type Response */
{
guint8 length = tvb_get_guint8(tvb, offset);
proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
if(length > 0) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u",
tvb_length_remaining(tvb, offset)/length);
while (tvb_length_remaining(tvb, offset) >= length)
{
item = proto_tree_add_text(st, tvb, offset, length, "Attribute Data, Handle: 0x%04x",
tvb_get_letohs(tvb, offset));
ltree = proto_item_add_subtree(item, ett_btatt_list);
proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length-2, ENC_LITTLE_ENDIAN);
offset += (length-2);
}
}
}
break;
case 0x0a: /* Read Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
break;
case 0x0b: /* Read Response */
case 0x0d: /* Read Blob Response */
case 0x0f: /* Multiple Read Response */
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
break;
case 0x0c: /* Read Blob Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u",
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
break;
case 0x0e: /* Multiple Read Request */
if(tvb_length_remaining(tvb, offset) < 4) {
expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
"Too few handles, should be 2 or more");
break;
}
col_append_str(pinfo->cinfo, COL_INFO, ", Handles: ");
while (tvb_length_remaining(tvb, offset) >= 2) {
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
col_append_fstr(pinfo->cinfo, COL_INFO, "0x%04x ", tvb_get_letohs(tvb, offset));
offset += 2;
}
break;
case 0x11: /* Read By Group Type Response */
{
guint8 length = tvb_get_guint8(tvb, offset);
proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
if(length > 0) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u", tvb_length_remaining(tvb, offset)/length);
while (tvb_length_remaining(tvb, offset) >= length) {
item = proto_tree_add_text(st, tvb, offset, length,
"Attribute Data, Handle: 0x%04x, Group End Handle: 0x%04x",
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
ltree = proto_item_add_subtree(item, ett_btatt_list);
proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length-4, ENC_LITTLE_ENDIAN);
offset += (length-4);
}
}
}
break;
case 0x12: /* Write Request */
case 0x52: /* Write Command */
case 0x1b: /* Handle Value Notification */
case 0x1d: /* Handle Value Indication */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
break;
case 0x16: /* Prepare Write Request */
case 0x17: /* Prepare Write Response */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u",
tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2));
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA);
break;
case 0x18: /* Execute Write Request */
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
val_to_str(tvb_get_guint8(tvb, offset), flags_vals, "<unknown>"));
proto_tree_add_item(st, hf_btatt_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
break;
case 0xd2: /* Signed Write Command */
{
guint8 length;
col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset));
proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
length = tvb_length_remaining(tvb, offset);
if (length > 12) {
proto_tree_add_item(st, hf_btatt_value, tvb, offset, length-12, ENC_NA);
offset+=length-12;
}
proto_tree_add_item(st, hf_btatt_sign_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset+=4;
proto_tree_add_item(st, hf_btatt_signature, tvb, offset, 8, ENC_NA);
offset+=8;
break;
}
default:
break;
}
}
void
proto_register_btatt(void)
{
module_t *module;
static hf_register_info hf[] = {
{&hf_btatt_opcode,
{"Opcode", "btatt.opcode",
FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
NULL, HFILL}
},
{&hf_btatt_handle,
{"Handle", "btatt.handle",
FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_starting_handle,
{"Starting Handle", "btatt.starting_handle",
FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_ending_handle,
{"Ending Handle", "btatt.ending_handle",
FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_group_end_handle,
{"Group End Handle", "btatt.group_end_handle",
FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_value,
{"Value", "btatt.value",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_req_opcode_in_error,
{"Request Opcode in Error", "btatt.req_opcode_in_error",
FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
NULL, HFILL}
},
{&hf_btatt_handle_in_error,
{"Handle in Error", "btatt.handle_in_error",
FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_error_code,
{"Error Code", "btatt.error_code",
FT_UINT8, BASE_HEX, VALS(error_vals), 0x0,
NULL, HFILL}
},
{&hf_btatt_uuid16,
{"UUID", "btatt.uuid16",
FT_UINT16, BASE_HEX |BASE_EXT_STRING, &uuid_vals_ext, 0x0,
NULL, HFILL}
},
{&hf_btatt_uuid128,
{"UUID", "btatt.uuid128",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_client_rx_mtu,
{"Client Rx MTU", "btatt.client_rx_mtu",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_server_rx_mtu,
{"Server Rx MTU", "btatt.server_rx_mtu",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_uuid_format,
{"UUID Format", "btatt.uuid_format",
FT_UINT8, BASE_HEX, VALS(uuid_format_vals), 0x0,
NULL, HFILL}
},
{&hf_btatt_length,
{"Length", "btatt.length",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Length of Handle/Value Pair", HFILL}
},
{&hf_btatt_offset,
{"Offset", "btatt.offset",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_flags,
{"Flags", "btatt.flags",
FT_UINT8, BASE_HEX, VALS(flags_vals), 0x0,
NULL, HFILL}
},
{&hf_btatt_sign_counter,
{"Sign Counter", "btatt.sign_counter",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}
},
{&hf_btatt_signature,
{"Signature", "btatt.signature",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}
}
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_btatt,
&ett_btatt_list
};
/* Register the protocol name and description */
proto_btatt = proto_register_protocol("Bluetooth Attribute Protocol", "ATT", "btatt");
register_dissector("btatt", dissect_btatt, proto_btatt);
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_btatt, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
module = prefs_register_protocol(proto_btatt, NULL);
prefs_register_static_text_preference(module, "att.version",
"Bluetooth Protocol ATT version from Core 4.0",
"Version of protocol supported by this dissector.");
}
void
proto_reg_handoff_btatt(void)
{
dissector_handle_t btatt_handle;
btatt_handle = find_dissector("btatt");
dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_ATT, btatt_handle);
dissector_add_uint("btl2cap.cid", BTL2CAP_FIXED_CID_ATT, btatt_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:
*/

View File

@ -0,0 +1,34 @@
#include "winver.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION @RC_MODULE_VERSION@
PRODUCTVERSION @RC_VERSION@
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "The Wireshark developer community, http://www.wireshark.org/\0"
VALUE "FileDescription", "@PACKAGE@ dissector\0"
VALUE "FileVersion", "@MODULE_VERSION@\0"
VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0"
VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs <gerald@wireshark.org>, Gilbert Ramirez <gram@alumni.rice.edu> and others\0"
VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0"
VALUE "ProductName", "Wireshark\0"
VALUE "ProductVersion", "@VERSION@\0"
VALUE "Comments", "Build with @MSVC_VARIANT@\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@ -0,0 +1,186 @@
#! /bin/sh
#
# $Id: make-dissector-reg 21716 2007-05-07 17:55:42Z gal $
#
#
# The first argument is the directory in which the source files live.
#
srcdir="$1"
shift
#
# The second argument is either "plugin" or "dissectors"; if it's
# "plugin", we build a plugin.c for a plugin, and if it's
# "dissectors", we build a register.c for libwireshark.
#
registertype="$1"
shift
if [ "$registertype" = plugin ]
then
outfile="plugin.c"
elif [ "$registertype" = dissectors ]
then
outfile="register.c"
else
echo "Unknown output type '$registertype'" 1>&2
exit 1
fi
#
# All subsequent arguments are the files to scan.
#
rm -f ${outfile}-tmp
echo '/* Do not modify this file. */' >${outfile}-tmp
echo '/* It is created automatically by the Makefile. */'>>${outfile}-tmp
if [ "$registertype" = plugin ]
then
cat <<"EOF" >>${outfile}-tmp
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gmodule.h>
#include "moduleinfo.h"
#ifndef ENABLE_STATIC
G_MODULE_EXPORT const gchar version[] = VERSION;
/* Start the functions we need for the plugin stuff */
G_MODULE_EXPORT void
plugin_register (void)
{
EOF
#
# Build code to call all the protocol registration routines.
#
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
else
cat <<"EOF" >>${outfile}-tmp
#include "register.h"
void
register_all_protocols(register_cb cb, gpointer client_data)
{
EOF
#
# Build code to call all the protocol registration routines.
#
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
fi
echo '}' >>${outfile}-tmp
#
# Build code to call all the protocol handoff registration routines.
#
if [ "$registertype" = plugin ]
then
cat <<"EOF" >>${outfile}-tmp
G_MODULE_EXPORT void
plugin_reg_handoff(void)
{
EOF
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
else
cat <<"EOF" >>${outfile}-tmp
void
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
{
EOF
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
fi
echo '}' >>${outfile}-tmp
if [ "$registertype" = plugin ]
then
echo '#endif' >>${outfile}-tmp
else
cat <<"EOF" >>${outfile}-tmp
gulong register_count(void)
{
EOF
proto_regs=`grep RA_REGISTER ${outfile}-tmp | wc -l`
handoff_regs=`grep RA_HANDOFF ${outfile}-tmp | wc -l`
echo " return $proto_regs + $handoff_regs;" >>${outfile}-tmp
echo '}' >>${outfile}-tmp
fi
mv ${outfile}-tmp ${outfile}

View File

@ -0,0 +1,311 @@
#!/usr/bin/env python
#
# Looks for registration routines in the protocol dissectors,
# and assembles C code to call all the routines.
#
# This is a Python version of the make-reg-dotc shell script.
# Running the shell script on Win32 is very very slow because of
# all the process-launching that goes on --- multiple greps and
# seds for each input file. I wrote this python version so that
# less processes would have to be started.
#
# $Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $
import os
import sys
import re
import pickle
from stat import *
VERSION_KEY = '_VERSION'
CUR_VERSION = '$Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $'
#
# The first argument is the directory in which the source files live.
#
srcdir = sys.argv[1]
#
# The second argument is either "plugin" or "dissectors"; if it's
# "plugin", we build a plugin.c for a plugin, and if it's
# "dissectors", we build a register.c for libwireshark.
#
registertype = sys.argv[2]
if registertype == "plugin" or registertype == "plugin_wtap":
tmp_filename = "plugin.c-tmp"
final_filename = "plugin.c"
cache_filename = None
preamble = """\
/*
* Do not modify this file.
*
* It is created automatically by Makefile or Makefile.nmake.
*/
"""
elif registertype == "dissectors":
tmp_filename = "register.c-tmp"
final_filename = "register.c"
cache_filename = "register-cache.pkl"
preamble = """\
/*
* Do not modify this file.
*
* It is created automatically by the "register.c" target in
* epan/dissectors/Makefile or Makefile.nmake using information in
* epan/dissectors/register-cache.pkl.
*
* You can force this file to be regenerated completely by deleting
* it along with epan/dissectors/register-cache.pkl.
*/
"""
else:
print(("Unknown output type '%s'" % registertype))
sys.exit(1)
#
# All subsequent arguments are the files to scan.
#
files = sys.argv[3:]
# Create the proper list of filenames
filenames = []
for file in files:
if os.path.isfile(file):
filenames.append(file)
else:
filenames.append(os.path.join(srcdir, file))
if len(filenames) < 1:
print("No files found")
sys.exit(1)
# Look through all files, applying the regex to each line.
# If the pattern matches, save the "symbol" section to the
# appropriate array.
regs = {
'proto_reg': [],
'handoff_reg': [],
'wtap_register': [],
}
# For those that don't know Python, r"" indicates a raw string,
# devoid of Python escapes.
proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
wtap_reg_regex0 = r"^(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
wtap_reg_regex1 = r"void\s+(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
# This table drives the pattern-matching and symbol-harvesting
patterns = [
( 'proto_reg', re.compile(proto_regex0) ),
( 'proto_reg', re.compile(proto_regex1) ),
( 'handoff_reg', re.compile(handoff_regex0) ),
( 'handoff_reg', re.compile(handoff_regex1) ),
( 'wtap_register', re.compile(wtap_reg_regex0) ),
( 'wtap_register', re.compile(wtap_reg_regex1) ),
]
# Open our registration symbol cache
cache = None
if cache_filename:
try:
cache_file = open(cache_filename, 'rb')
cache = pickle.load(cache_file)
cache_file.close()
if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
cache = {VERSION_KEY: CUR_VERSION}
except:
cache = {VERSION_KEY: CUR_VERSION}
print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
# Grep
cache_hits = 0
cache_misses = 0
for filename in filenames:
file = open(filename)
cur_mtime = os.fstat(file.fileno())[ST_MTIME]
if cache and filename in cache:
cdict = cache[filename]
if cur_mtime == cdict['mtime']:
cache_hits += 1
# print "Pulling %s from cache" % (filename)
regs['proto_reg'].extend(cdict['proto_reg'])
regs['handoff_reg'].extend(cdict['handoff_reg'])
regs['wtap_register'].extend(cdict['wtap_register'])
file.close()
continue
# We don't have a cache entry
if cache is not None:
cache_misses += 1
cache[filename] = {
'mtime': cur_mtime,
'proto_reg': [],
'handoff_reg': [],
'wtap_register': [],
}
# print "Searching %s" % (filename)
for line in file.readlines():
for action in patterns:
regex = action[1]
match = regex.search(line)
if match:
symbol = match.group("symbol")
sym_type = action[0]
regs[sym_type].append(symbol)
if cache is not None:
# print "Caching %s for %s: %s" % (sym_type, filename, symbol)
cache[filename][sym_type].append(symbol)
file.close()
if cache is not None and cache_filename is not None:
cache_file = open(cache_filename, 'wb')
pickle.dump(cache, cache_file)
cache_file.close()
print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
# Make sure we actually processed something
if len(regs['proto_reg']) < 1:
print("No protocol registrations found")
sys.exit(1)
# Sort the lists to make them pretty
regs['proto_reg'].sort()
regs['handoff_reg'].sort()
regs['wtap_register'].sort()
reg_code = open(tmp_filename, "w")
reg_code.write(preamble)
# Make the routine to register all protocols
if registertype == "plugin" or registertype == "plugin_wtap":
reg_code.write("""
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gmodule.h>
#include "moduleinfo.h"
#ifndef ENABLE_STATIC
G_MODULE_EXPORT const gchar version[] = VERSION;
/* Start the functions we need for the plugin stuff */
G_MODULE_EXPORT void
plugin_register (void)
{
""");
else:
reg_code.write("""
#include "register.h"
void
register_all_protocols(register_cb cb, gpointer client_data)
{
""");
for symbol in regs['proto_reg']:
if registertype == "plugin" or registertype == "plugin_wtap":
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
else:
line = " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
reg_code.write(line)
reg_code.write("}\n")
# Make the routine to register all protocol handoffs
if registertype == "plugin" or registertype == "plugin_wtap":
reg_code.write("""
G_MODULE_EXPORT void
plugin_reg_handoff(void)
{
""");
else:
reg_code.write("""
void
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
{
""");
for symbol in regs['handoff_reg']:
if registertype == "plugin" or registertype == "plugin_wtap":
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
else:
line = " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
reg_code.write(line)
reg_code.write("}\n")
if registertype == "plugin":
reg_code.write("#endif\n");
elif registertype == "plugin_wtap":
reg_code.write("""
G_MODULE_EXPORT void
register_wtap_module(void)
{
""");
for symbol in regs['wtap_register']:
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
reg_code.write(line)
reg_code.write("}\n");
reg_code.write("#endif\n");
else:
reg_code.write("""
static gulong proto_reg_count(void)
{
""");
line = " return %d;\n" % len(regs['proto_reg'])
reg_code.write(line)
reg_code.write("""
}
""");
reg_code.write("""
static gulong handoff_reg_count(void)
{
""");
line = " return %d;\n" % len(regs['handoff_reg'])
reg_code.write(line)
reg_code.write("""
}
""");
reg_code.write("""
gulong register_count(void)
{
""");
line = " return proto_reg_count() + handoff_reg_count();"
reg_code.write(line)
reg_code.write("""
}\n
""");
# Close the file
reg_code.close()
# Remove the old final_file if it exists.
try:
os.stat(final_filename)
os.remove(final_filename)
except OSError:
pass
# Move from tmp file to final file
os.rename(tmp_filename, final_filename)

View File

@ -0,0 +1,2 @@
Authors:
Michael Ossmann <mike@ossmann.com>

View File

@ -0,0 +1,89 @@
# CMakeLists.txt
#
# $Id: CMakeLists.txt 31995 2010-02-24 22:32:10Z jmayer $
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
project(btbb-wireshark-plugin C)
cmake_minimum_required(VERSION 2.6)
set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
IF ( NOT CMAKE_INSTALL_LIBDIR )
set(CMAKE_INSTALL_LIBDIR ~/.wireshark/plugins)
ENDIF ( NOT CMAKE_INSTALL_LIBDIR )
MESSAGE (STATUS "Plugin will be installed in: ${CMAKE_INSTALL_LIBDIR}")
INCLUDE(UseMakeDissectorReg)
set(GLIB2_MIN_VERSION 2.4.0)
find_package(GLIB2)
include_directories (${GLIB2_INCLUDE_DIRS})
find_package(Wireshark)
include_directories (${WIRESHARK_INCLUDE_DIRS})
set(LINK_MODE_LIB SHARED)
set(LINK_MODE_MODULE MODULE)
set(DISSECTOR_SRC
packet-btbb.c
packet-btbrlmp.c
)
set(PLUGIN_FILES
plugin.c
${DISSECTOR_SRC}
)
set(CLEAN_FILES
${PLUGIN_FILES}
)
if (WERROR)
set_source_files_properties(
${CLEAN_FILES}
PROPERTIES
COMPILE_FLAGS -Werror
)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
register_dissector_files(plugin.c
plugin
${DISSECTOR_SRC}
)
add_library(btbb ${LINK_MODE_MODULE}
${PLUGIN_FILES}
)
set_target_properties(btbb PROPERTIES PREFIX "")
set_target_properties(btbb PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
target_link_libraries(btbb wireshark)
install(TARGETS btbb
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ NAMELINK_SKIP
)

View File

@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
<signature of Ty Coon>, 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.

View File

@ -0,0 +1,17 @@
BTBB Wireshark plugin
This is the Bluetooth baseband plugin for Wireshark, it also includes an LMP
level dissector.
To build this on Debian/Ubuntu/BackTrack linux distributions:
sudo apt-get install wireshark-dev wireshark
cd libbtbb/wireshark/plugins/btbb/
mkdir build
cd build
cmake ..
make
make install
This will install to the .wireshark/ in your home directory. To override this
set the DESTDIR environment variable when running cmake.

View File

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,27 @@
Copyright notice for the files copied from
http://www.opensync.org/browser/branches/3rd-party-cmake-modules/modules
$Id: COPYING-CMAKE-SCRIPTS 34248 2010-09-25 15:38:12Z jmayer $
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,238 @@
#
# $Id: FindGLIB2.cmake 34248 2010-09-25 15:38:12Z jmayer $
#
# - Try to find GLib2
# Once done this will define
#
# GLIB2_FOUND - system has GLib2
# GLIB2_INCLUDE_DIRS - the GLib2 include directory
# GLIB2_LIBRARIES - Link these to use GLib2
#
# HAVE_GLIB_GREGEX_H glib has gregex.h header and
# supports g_regex_match_simple
#
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
# Copyright (c) 2006 Philippe Bernery <philippe.bernery@gmail.com>
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
# Copyright (c) 2008 Michael Bell <michael.bell@web.de>
# Copyright (c) 2008-2009 Bjoern Ricks <bjoern.ricks@googlemail.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
# in cache already
SET(GLIB2_FOUND TRUE)
ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
INCLUDE(FindPkgConfig)
## Glib
IF ( GLIB2_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "REQUIRED" )
ELSE ( GLIB2_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "" )
ENDIF ( GLIB2_FIND_REQUIRED )
IF ( GLIB2_MIN_VERSION )
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} )
ELSE ( GLIB2_MIN_VERSION )
PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 )
ENDIF ( GLIB2_MIN_VERSION )
IF ( PKG_CONFIG_FOUND )
IF ( GLIB2_FOUND )
SET ( GLIB2_CORE_FOUND TRUE )
ELSE ( GLIB2_FOUND )
SET ( GLIB2_CORE_FOUND FALSE )
ENDIF ( GLIB2_FOUND )
ENDIF ( PKG_CONFIG_FOUND )
# Look for glib2 include dir and libraries w/o pkgconfig
IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
FIND_PATH(
_glibconfig_include_DIR
NAMES
glibconfig.h
PATHS
/opt/gnome/lib64
/opt/gnome/lib
/opt/lib/
/opt/local/lib
/sw/lib/
/usr/lib64
/usr/lib
/usr/local/include
${CMAKE_LIBRARY_PATH}
PATH_SUFFIXES
glib-2.0/include
)
FIND_PATH(
_glib2_include_DIR
NAMES
glib.h
PATHS
/opt/gnome/include
/opt/local/include
/sw/include
/usr/include
/usr/local/include
PATH_SUFFIXES
glib-2.0
)
#MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}")
FIND_LIBRARY(
_glib2_link_DIR
NAMES
glib-2.0
glib
PATHS
/opt/gnome/lib
/opt/local/lib
/sw/lib
/usr/lib
/usr/local/lib
)
IF ( _glib2_include_DIR AND _glib2_link_DIR )
SET ( _glib2_FOUND TRUE )
ENDIF ( _glib2_include_DIR AND _glib2_link_DIR )
IF ( _glib2_FOUND )
SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} )
SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} )
SET ( GLIB2_CORE_FOUND TRUE )
ELSE ( _glib2_FOUND )
SET ( GLIB2_CORE_FOUND FALSE )
ENDIF ( _glib2_FOUND )
# Handle dependencies
# libintl
IF ( NOT LIBINTL_FOUND )
FIND_PATH(LIBINTL_INCLUDE_DIR
NAMES
libintl.h
PATHS
/opt/gnome/include
/opt/local/include
/sw/include
/usr/include
/usr/local/include
)
FIND_LIBRARY(LIBINTL_LIBRARY
NAMES
intl
PATHS
/opt/gnome/lib
/opt/local/lib
/sw/lib
/usr/local/lib
/usr/lib
)
IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
SET (LIBINTL_FOUND TRUE)
ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
ENDIF ( NOT LIBINTL_FOUND )
# libiconv
IF ( NOT LIBICONV_FOUND )
FIND_PATH(LIBICONV_INCLUDE_DIR
NAMES
iconv.h
PATHS
/opt/gnome/include
/opt/local/include
/opt/local/include
/sw/include
/sw/include
/usr/local/include
/usr/include
PATH_SUFFIXES
glib-2.0
)
FIND_LIBRARY(LIBICONV_LIBRARY
NAMES
iconv
PATHS
/opt/gnome/lib
/opt/local/lib
/sw/lib
/usr/lib
/usr/local/lib
)
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
SET (LIBICONV_FOUND TRUE)
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
ENDIF ( NOT LIBICONV_FOUND )
IF (LIBINTL_FOUND)
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
ENDIF (LIBINTL_FOUND)
IF (LIBICONV_FOUND)
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
ENDIF (LIBICONV_FOUND)
ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
##
IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
SET (GLIB2_FOUND TRUE)
ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
IF (GLIB2_FOUND)
IF (NOT GLIB2_FIND_QUIETLY)
MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}")
ENDIF (NOT GLIB2_FIND_QUIETLY)
ELSE (GLIB2_FOUND)
IF (GLIB2_FIND_REQUIRED)
MESSAGE (SEND_ERROR "Could not find GLib2")
ENDIF (GLIB2_FIND_REQUIRED)
ENDIF (GLIB2_FOUND)
# show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES)
MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS)
IF ( WIN32 )
# include libiconv for win32
IF ( NOT LIBICONV_FOUND )
FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h PATH_SUFFIXES glib-2.0)
FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv)
IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
SET (LIBICONV_FOUND TRUE)
ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
ENDIF ( NOT LIBICONV_FOUND )
IF (LIBICONV_FOUND)
SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
ENDIF (LIBICONV_FOUND)
ENDIF ( WIN32 )
IF ( GLIB2_FOUND )
# Check if system has a newer version of glib
# which supports g_regex_match_simple
INCLUDE( CheckIncludeFiles )
SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} )
CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H )
CHECK_INCLUDE_FILES ( glib/gchecksum.h HAVE_GLIB_GCHECKSUM_H )
# Reset CMAKE_REQUIRED_INCLUDES
SET( CMAKE_REQUIRED_INCLUDES "" )
ENDIF( GLIB2_FOUND )

View File

@ -0,0 +1,28 @@
#
# Try to find the wireshark library and its includes
#
# This snippet sets the following variables:
# WIRESHARK_FOUND True if wireshark library got found
# WIRESHARK_INCLUDE_DIRS Location of the wireshark headers
# WIRESHARK_LIBRARIES List of libraries to use wireshark
#
# Copyright (c) 2011 Reinhold Kainhofer <reinhold@kainhofer.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
# wireshark does not install its library with pkg-config information,
# so we need to manually find the libraries and headers
FIND_PATH( WIRESHARK_INCLUDE_DIRS epan/packet.h PATH_SUFFIXES wireshark )
FIND_LIBRARY( WIRESHARK_LIBRARIES wireshark )
# Report results
IF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
SET( WIRESHARK_FOUND 1 )
ELSE ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )
MESSAGE( SEND_ERROR "Could NOT find the wireshark library and headers" )
ENDIF ( WIRESHARK_LIBRARIES AND WIRESHARK_INCLUDE_DIRS )

View File

@ -0,0 +1,33 @@
#
# $Id: UseMakeDissectorReg.cmake 33616 2010-07-22 12:18:36Z stig $
#
MACRO(REGISTER_DISSECTOR_FILES _outputfile _registertype )
# FIXME: Only the Python stuff has been implemented
# Make this into a MACRO, to avoid duplication with plugins/.../
#register.c: $(plugin_src) $(ALL_DISSECTORS_SRC) $(top_srcdir)/tools/make-dissector-reg \
# $(top_srcdir)/tools/make-dissector-reg.py
# @if test -n "$(PYTHON)"; then \
# echo Making register.c with python ; \
# $(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
# dissectors $(ALL_DISSECTORS_SRC) ; \
# else \
# echo Making register.c with shell script ; \
# $(top_srcdir)/tools/make-dissector-reg $(srcdir) \
# dissectors $(plugin_src) $(ALL_DISSECTORS_SRC) ; \
# fi
set( _sources ${ARGN} )
ADD_CUSTOM_COMMAND(
OUTPUT
${_outputfile}
COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
${CMAKE_CURRENT_SOURCE_DIR}
${_registertype}
${_sources}
DEPENDS
${_sources}
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg
${CMAKE_SOURCE_DIR}/tools/make-dissector-reg.py
)
ENDMACRO(REGISTER_DISSECTOR_FILES)

View File

@ -0,0 +1,17 @@
/* Included *after* config.h, in order to re-define these macros */
#ifdef PACKAGE
#undef PACKAGE
#endif
/* Name of package */
#define PACKAGE "btbb"
#ifdef VERSION
#undef VERSION
#endif
/* Version number of package */
#define VERSION "0.0.1"

View File

@ -0,0 +1,593 @@
/* packet-btbb.c
* Routines for Bluetooth baseband dissection
* Copyright 2009, Michael Ossmann <mike@ossmann.com>
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#else
#include <wireshark/config.h>
#endif
#include <epan/packet.h>
#include <epan/prefs.h>
/* function prototypes */
void proto_reg_handoff_btbb(void);
/* initialize the protocol and registered fields */
static int proto_btbb = -1;
static int hf_btbb_meta = -1;
static int hf_btbb_dir = -1;
static int hf_btbb_clk = -1;
static int hf_btbb_channel = -1;
static int hf_btbb_addrbits = -1;
static int hf_btbb_clkbits = -1;
static int hf_btbb_pkthdr = -1;
static int hf_btbb_ltaddr = -1;
static int hf_btbb_type = -1;
static int hf_btbb_flags = -1;
static int hf_btbb_flow = -1;
static int hf_btbb_arqn = -1;
static int hf_btbb_seqn = -1;
static int hf_btbb_hec = -1;
static int hf_btbb_payload = -1;
static int hf_btbb_pldhdr = -1;
static int hf_btbb_llid = -1;
static int hf_btbb_pldflow = -1;
static int hf_btbb_length = -1;
static int hf_btbb_pldbody = -1;
static int hf_btbb_crc = -1;
static int hf_btbb_fhs_parity = -1;
static int hf_btbb_fhs_lap = -1;
static int hf_btbb_fhs_eir = -1;
static int hf_btbb_fhs_sr = -1;
static int hf_btbb_fhs_uap = -1;
static int hf_btbb_fhs_nap = -1;
static int hf_btbb_fhs_class = -1;
static int hf_btbb_fhs_ltaddr = -1;
static int hf_btbb_fhs_clk = -1;
static int hf_btbb_fhs_psmode = -1;
/* field values */
static const true_false_string direction = {
"Slave to Master",
"Master to Slave"
};
static const true_false_string clock_bits = {
"27",
"6"
};
static const true_false_string address_bits = {
"48 (NAP known)",
"32 (NAP unknown)"
};
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 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 }
};
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 }
};
/* initialize the subtree pointers */
static gint ett_btbb = -1;
static gint ett_btbb_meta = -1;
static gint ett_btbb_pkthdr = -1;
static gint ett_btbb_flags = -1;
static gint ett_btbb_payload = -1;
static gint ett_btbb_pldhdr = -1;
/* subdissectors */
static dissector_handle_t btbrlmp_handle = NULL;
static dissector_handle_t btl2cap_handle = NULL;
/* packet header flags */
static const int *flag_fields[] = {
&hf_btbb_flow,
&hf_btbb_arqn,
&hf_btbb_seqn,
NULL
};
/* one byte payload header */
int
dissect_payload_header1(proto_tree *tree, tvbuff_t *tvb, int offset)
{
proto_item *hdr_item;
proto_tree *hdr_tree;
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 1);
hdr_item = proto_tree_add_item(tree, hf_btbb_pldhdr, tvb, offset, 1, ENC_NA);
hdr_tree = proto_item_add_subtree(hdr_item, ett_btbb_pldhdr);
proto_tree_add_item(hdr_tree, hf_btbb_llid, tvb, offset, 1, ENC_NA);
proto_tree_add_item(hdr_tree, hf_btbb_pldflow, tvb, offset, 1, ENC_NA);
proto_tree_add_item(hdr_tree, hf_btbb_length, tvb, offset, 1, ENC_NA);
/* payload length */
return tvb_get_guint8(tvb, offset) >> 3;
}
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;
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) == 20);
fhs_item = proto_tree_add_item(tree, hf_btbb_payload, tvb, offset, -1, ENC_NA);
fhs_tree = proto_item_add_subtree(fhs_item, ett_btbb_payload);
/* Use proto_tree_add_bits_item() to get around 32bit limit on bitmasks */
proto_tree_add_bits_item(fhs_tree, hf_btbb_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_btbb_fhs_lap, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 3;
proto_tree_add_item(fhs_tree, hf_btbb_fhs_eir, tvb, offset, 1, ENC_NA);
/* skipping 1 undefined bit */
proto_tree_add_item(fhs_tree, hf_btbb_fhs_sr, tvb, offset, 1, ENC_NA);
/* skipping 2 reserved bits */
offset += 1;
proto_tree_add_item(fhs_tree, hf_btbb_fhs_uap, tvb, offset, 1, ENC_NA);
offset += 1;
proto_tree_add_item(fhs_tree, hf_btbb_fhs_nap, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(fhs_tree, hf_btbb_fhs_class, tvb, offset, 3, ENC_LITTLE_ENDIAN);
offset += 3;
proto_tree_add_item(fhs_tree, hf_btbb_fhs_ltaddr, tvb, offset, 1, ENC_NA);
proto_tree_add_item(fhs_tree, hf_btbb_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_btbb_fhs_psmode, tvb, offset, 1, ENC_NA);
if (description)
proto_item_append_text(psmode_item, " (%s)", description);
offset += 1;
proto_tree_add_item(fhs_tree, hf_btbb_crc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
}
void
dissect_dm1(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset)
{
int len; /* payload length indicated by payload header */
int llid; /* logical link id */
int l2len; /* length indicated by l2cap header */
proto_item *dm1_item;
proto_tree *dm1_tree;
tvbuff_t *pld_tvb;
/*
* FIXME
* I'm probably doing a terrible, terrible thing here, but it gets my
* initial test cases working.
*/
guint16 fake_acl_data;
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) >= 3);
dm1_item = proto_tree_add_item(tree, hf_btbb_payload, tvb, offset, -1, ENC_NA);
dm1_tree = proto_item_add_subtree(dm1_item, ett_btbb_payload);
len = dissect_payload_header1(dm1_tree, tvb, offset);
llid = tvb_get_guint8(tvb, offset) & 0x3;
offset += 1;
DISSECTOR_ASSERT(tvb_length_remaining(tvb, offset) == len + 2);
if (llid == 3 && btbrlmp_handle) {
/* LMP */
pld_tvb = tvb_new_subset(tvb, offset, len, len);
call_dissector(btbrlmp_handle, pld_tvb, pinfo, dm1_tree);
} else if (llid == 2 && btl2cap_handle) {
/* unfragmented L2CAP or start of fragment */
l2len = tvb_get_letohs(tvb, offset);
if (l2len + 4 == len) {
/* unfragmented */
pinfo->private_data = &fake_acl_data;
pld_tvb = tvb_new_subset(tvb, offset, len, len);
call_dissector(btl2cap_handle, pld_tvb, pinfo, dm1_tree);
} else {
/* start of fragment */
proto_tree_add_item(dm1_tree, hf_btbb_pldbody, tvb, offset, len, ENC_NA);
}
} else {
proto_tree_add_item(dm1_tree, hf_btbb_pldbody, tvb, offset, len, ENC_NA);
}
offset += len;
proto_tree_add_item(dm1_tree, hf_btbb_crc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
}
/* dissect a packet */
static int
dissect_btbb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
proto_item *btbb_item, *meta_item, *pkthdr_item;
proto_tree *btbb_tree, *meta_tree, *pkthdr_tree;
int offset;
/* Avoid error: 'type' may be used uninitialized in this function */
guint8 type = 0xff;
const gchar *info;
/* sanity check: length */
if (tvb_length(tvb) > 0 && tvb_length(tvb) < 9)
/* bad length: look for a different dissector */
return 0;
/* maybe should verify HEC */
/* make entries in protocol column and info column on summary display */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bluetooth");
if (tvb_length(tvb) == 0) {
info = "ID";
} else {
type = (tvb_get_guint8(tvb, 6) >> 3) & 0x0f;
info = val_to_str(type, packet_types, "Unknown type: 0x%x");
}
col_clear(pinfo->cinfo, COL_INFO);
col_add_str(pinfo->cinfo, COL_INFO, info);
/* see if we are being asked for details */
if (tree) {
/* create display subtree for the protocol */
offset = 0;
btbb_item = proto_tree_add_item(tree, proto_btbb, tvb, offset, -1, ENC_NA);
btbb_tree = proto_item_add_subtree(btbb_item, ett_btbb);
/* ID packets have no header, no payload */
if (tvb_length(tvb) == 0)
return 1;
/* meta data */
meta_item = proto_tree_add_item(btbb_tree, hf_btbb_meta, tvb, offset, 3, ENC_NA);
meta_tree = proto_item_add_subtree(meta_item, ett_btbb_meta);
proto_tree_add_item(meta_tree, hf_btbb_dir, tvb, offset, 1, ENC_NA);
proto_tree_add_item(meta_tree, hf_btbb_clk, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
proto_tree_add_item(meta_tree, hf_btbb_channel, tvb, offset, 1, ENC_NA);
offset += 1;
proto_tree_add_item(meta_tree, hf_btbb_clkbits, tvb, offset, 1, ENC_NA);
proto_tree_add_item(meta_tree, hf_btbb_addrbits, tvb, offset, 1, ENC_NA);
offset += 1;
/* packet header */
pkthdr_item = proto_tree_add_item(btbb_tree, hf_btbb_pkthdr, tvb, offset, 3, ENC_NA);
pkthdr_tree = proto_item_add_subtree(pkthdr_item, ett_btbb_pkthdr);
proto_tree_add_item(pkthdr_tree, hf_btbb_ltaddr, tvb, offset, 1, ENC_NA);
proto_tree_add_item(pkthdr_tree, hf_btbb_type, tvb, offset, 1, ENC_NA);
offset += 1;
proto_tree_add_bitmask(pkthdr_tree, tvb, offset, hf_btbb_flags,
ett_btbb_flags, flag_fields, ENC_NA);
offset += 1;
proto_tree_add_item(pkthdr_tree, hf_btbb_hec, tvb, offset, 1, ENC_NA);
offset += 1;
/* payload */
switch (type) {
case 0x0: /* NULL */
case 0x1: /* POLL */
break;
case 0x2: /* FHS */
dissect_fhs(btbb_tree, tvb, offset);
break;
case 0x3: /* DM1 */
dissect_dm1(btbb_tree, tvb, pinfo, offset);
break;
case 0x4: /* DH1/2-DH1 */
dissect_dm1(btbb_tree, tvb, pinfo, offset);
break;
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 */
proto_tree_add_item(btbb_tree, hf_btbb_payload, tvb, offset, -1, ENC_NA);
break;
default:
break;
}
}
/* Return the amount of data this dissector was able to dissect */
return tvb_length(tvb);
}
/* register the protocol with Wireshark */
void
proto_register_btbb(void)
{
/* list of fields */
static hf_register_info hf[] = {
{ &hf_btbb_meta,
{ "Meta Data", "btbb.meta",
FT_NONE, BASE_NONE, NULL, 0x0,
"Meta Data About the Packet", HFILL }
},
{ &hf_btbb_dir,
{ "Direction", "btbb.dir",
FT_BOOLEAN, 8, TFS(&direction), 0x01,
"Direction of Transmission", HFILL }
},
{ &hf_btbb_clk,
{ "CLK", "btbb.clk",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Clock bits 1 through 27", HFILL }
},
{ &hf_btbb_channel,
{ "Channel", "btbb.channel",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Channel (0-78)", HFILL }
},
{ &hf_btbb_clkbits,
{ "Known Clock Bits", "btbb.clkbits",
FT_BOOLEAN, 8, TFS(&clock_bits), 0x01,
"Number of Known Master CLK Bits (6 or 27)", HFILL }
},
{ &hf_btbb_addrbits,
{ "Known Address Bits", "btbb.addrbits",
FT_BOOLEAN, 8, TFS(&address_bits), 0x02,
"Number of Known Bits of BD_ADDR (32 or 48)", HFILL }
},
{ &hf_btbb_pkthdr,
{ "Packet Header", "btbb.pkthdr",
FT_NONE, BASE_NONE, NULL, 0x0,
"Bluetooth Baseband Packet Header", HFILL }
},
{ &hf_btbb_ltaddr,
{ "LT_ADDR", "btbb.lt_addr",
FT_UINT8, BASE_HEX, NULL, 0x07,
"Logical Transport Address", HFILL }
},
{ &hf_btbb_type,
{ "TYPE", "btbb.type",
FT_UINT8, BASE_HEX, VALS(packet_types), 0x78,
"Packet Type", HFILL }
},
{ &hf_btbb_flags,
{ "Flags", "btbb.flags",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Packet Header Flags", HFILL }
},
{ &hf_btbb_flow,
{ "FLOW", "btbb.flow",
FT_BOOLEAN, 8, NULL, 0x01,
"Flow control indication", HFILL }
},
{ &hf_btbb_arqn,
{ "ARQN", "btbb.arqn",
FT_BOOLEAN, 8, NULL, 0x02,
"Acknowledgment indication", HFILL }
},
{ &hf_btbb_seqn,
{ "SEQN", "btbb.seqn",
FT_BOOLEAN, 8, NULL, 0x04,
"Sequence number", HFILL }
},
{ &hf_btbb_hec,
{ "HEC", "btbb.lt_addr",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Header Error Check", HFILL }
},
{ &hf_btbb_payload,
{ "Payload", "btbb.payload",
FT_NONE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_btbb_llid,
{ "LLID", "btbb.llid",
FT_UINT8, BASE_HEX, VALS(llid_codes), 0x03,
"Logical Link ID", HFILL }
},
{ &hf_btbb_pldflow,
{ "Flow", "btbb.flow",
FT_BOOLEAN, 8, NULL, 0x04,
"Payload Flow indication", HFILL }
},
{ &hf_btbb_length,
{ "Length", "btbb.length",
FT_UINT8, BASE_DEC, NULL, 0xf8,
"Payload Length", HFILL }
},
{ &hf_btbb_pldhdr,
{ "Payload Header", "btbb.pldhdr",
FT_NONE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_btbb_pldbody,
{ "Payload Body", "btbb.pldbody",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_btbb_crc,
{ "CRC", "btbb.crc",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Payload CRC", HFILL }
},
{ &hf_btbb_fhs_parity,
{ "Parity", "btbb.parity",
/* FIXME this doesn't work because bitmasks can only be 32 bits */
FT_UINT64, BASE_HEX, NULL, /*0x00000003ffffffffULL,*/ 0x0,
"LAP parity", HFILL }
},
{ &hf_btbb_fhs_lap,
{ "LAP", "btbb.lap",
FT_UINT24, BASE_HEX, NULL, 0x03fffffc,
"Lower Address Part", HFILL }
},
{ &hf_btbb_fhs_eir,
{ "EIR", "btbb.eir",
FT_BOOLEAN, 8, NULL, 0x04,
"Extended Inquiry Response packet may follow", HFILL }
},
{ &hf_btbb_fhs_sr,
{ "SR", "btbb.sr",
FT_UINT8, BASE_HEX, VALS(sr_modes), 0x30,
"Scan Repetition", HFILL }
},
{ &hf_btbb_fhs_uap,
{ "UAP", "btbb.uap",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Upper Address Part", HFILL }
},
{ &hf_btbb_fhs_nap,
{ "NAP", "btbb.nap",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Non-Significant Address Part", HFILL }
},
{ &hf_btbb_fhs_class, /* FIXME break out further */
{ "Class of Device", "btbb.class",
FT_UINT24, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
{ &hf_btbb_fhs_ltaddr,
{ "LT_ADDR", "btbb.lt_addr",
FT_UINT8, BASE_HEX, NULL, 0x07,
"Logical Transport Address", HFILL }
},
{ &hf_btbb_fhs_clk,
{ "CLK", "btbb.clk",
FT_UINT32, BASE_HEX, NULL, 0x1ffffff8,
"Clock bits 2 through 27", HFILL }
},
{ &hf_btbb_fhs_psmode,
{ "Page Scan Mode", "btbb.psmode",
FT_UINT8, BASE_HEX, NULL, 0xe0,
NULL, HFILL }
},
};
/* protocol subtree arrays */
static gint *ett[] = {
&ett_btbb,
&ett_btbb_meta,
&ett_btbb_pkthdr,
&ett_btbb_flags,
&ett_btbb_payload,
&ett_btbb_pldhdr,
};
/* register the protocol name and description */
proto_btbb = proto_register_protocol(
"Bluetooth Baseband", /* full name */
"BT Baseband", /* short name */
"btbb" /* abbreviation (e.g. for filters) */
);
/* register the header fields and subtrees used */
proto_register_field_array(proto_btbb, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_btbb(void)
{
dissector_handle_t btbb_handle;
btbb_handle = new_create_dissector_handle(dissect_btbb, proto_btbb);
/* hijacking this ethertype */
dissector_add_uint("ethertype", 0xFFF0, btbb_handle);
/* dissector_add_uint("wtap_encap", WTAP_ENCAP_BLUETOOTH_BASEBAND, btbb_handle); */
btbrlmp_handle = find_dissector("btbrlmp");
btl2cap_handle = find_dissector("btl2cap");
}
/*
* 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:
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
#include "winver.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION @RC_MODULE_VERSION@
PRODUCTVERSION @RC_VERSION@
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "The Wireshark developer community, http://www.wireshark.org/\0"
VALUE "FileDescription", "@PACKAGE@ dissector\0"
VALUE "FileVersion", "@MODULE_VERSION@\0"
VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0"
VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs <gerald@wireshark.org>, Gilbert Ramirez <gram@alumni.rice.edu> and others\0"
VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0"
VALUE "ProductName", "Wireshark\0"
VALUE "ProductVersion", "@VERSION@\0"
VALUE "Comments", "Build with @MSVC_VARIANT@\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@ -0,0 +1,186 @@
#! /bin/sh
#
# $Id: make-dissector-reg 21716 2007-05-07 17:55:42Z gal $
#
#
# The first argument is the directory in which the source files live.
#
srcdir="$1"
shift
#
# The second argument is either "plugin" or "dissectors"; if it's
# "plugin", we build a plugin.c for a plugin, and if it's
# "dissectors", we build a register.c for libwireshark.
#
registertype="$1"
shift
if [ "$registertype" = plugin ]
then
outfile="plugin.c"
elif [ "$registertype" = dissectors ]
then
outfile="register.c"
else
echo "Unknown output type '$registertype'" 1>&2
exit 1
fi
#
# All subsequent arguments are the files to scan.
#
rm -f ${outfile}-tmp
echo '/* Do not modify this file. */' >${outfile}-tmp
echo '/* It is created automatically by the Makefile. */'>>${outfile}-tmp
if [ "$registertype" = plugin ]
then
cat <<"EOF" >>${outfile}-tmp
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gmodule.h>
#include "moduleinfo.h"
#ifndef ENABLE_STATIC
G_MODULE_EXPORT const gchar version[] = VERSION;
/* Start the functions we need for the plugin stuff */
G_MODULE_EXPORT void
plugin_register (void)
{
EOF
#
# Build code to call all the protocol registration routines.
#
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
else
cat <<"EOF" >>${outfile}-tmp
#include "register.h"
void
register_all_protocols(register_cb cb, gpointer client_data)
{
EOF
#
# Build code to call all the protocol registration routines.
#
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
fi
echo '}' >>${outfile}-tmp
#
# Build code to call all the protocol handoff registration routines.
#
if [ "$registertype" = plugin ]
then
cat <<"EOF" >>${outfile}-tmp
G_MODULE_EXPORT void
plugin_reg_handoff(void)
{
EOF
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
else
cat <<"EOF" >>${outfile}-tmp
void
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
{
EOF
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
for f in "$@"
do
if [ -f $f ]
then
srcfile=$f
else
srcfile=$srcdir/$f
fi
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
fi
echo '}' >>${outfile}-tmp
if [ "$registertype" = plugin ]
then
echo '#endif' >>${outfile}-tmp
else
cat <<"EOF" >>${outfile}-tmp
gulong register_count(void)
{
EOF
proto_regs=`grep RA_REGISTER ${outfile}-tmp | wc -l`
handoff_regs=`grep RA_HANDOFF ${outfile}-tmp | wc -l`
echo " return $proto_regs + $handoff_regs;" >>${outfile}-tmp
echo '}' >>${outfile}-tmp
fi
mv ${outfile}-tmp ${outfile}

View File

@ -0,0 +1,311 @@
#!/usr/bin/env python
#
# Looks for registration routines in the protocol dissectors,
# and assembles C code to call all the routines.
#
# This is a Python version of the make-reg-dotc shell script.
# Running the shell script on Win32 is very very slow because of
# all the process-launching that goes on --- multiple greps and
# seds for each input file. I wrote this python version so that
# less processes would have to be started.
#
# $Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $
import os
import sys
import re
import pickle
from stat import *
VERSION_KEY = '_VERSION'
CUR_VERSION = '$Id: make-dissector-reg.py 40736 2012-01-26 21:38:53Z gerald $'
#
# The first argument is the directory in which the source files live.
#
srcdir = sys.argv[1]
#
# The second argument is either "plugin" or "dissectors"; if it's
# "plugin", we build a plugin.c for a plugin, and if it's
# "dissectors", we build a register.c for libwireshark.
#
registertype = sys.argv[2]
if registertype == "plugin" or registertype == "plugin_wtap":
tmp_filename = "plugin.c-tmp"
final_filename = "plugin.c"
cache_filename = None
preamble = """\
/*
* Do not modify this file.
*
* It is created automatically by Makefile or Makefile.nmake.
*/
"""
elif registertype == "dissectors":
tmp_filename = "register.c-tmp"
final_filename = "register.c"
cache_filename = "register-cache.pkl"
preamble = """\
/*
* Do not modify this file.
*
* It is created automatically by the "register.c" target in
* epan/dissectors/Makefile or Makefile.nmake using information in
* epan/dissectors/register-cache.pkl.
*
* You can force this file to be regenerated completely by deleting
* it along with epan/dissectors/register-cache.pkl.
*/
"""
else:
print(("Unknown output type '%s'" % registertype))
sys.exit(1)
#
# All subsequent arguments are the files to scan.
#
files = sys.argv[3:]
# Create the proper list of filenames
filenames = []
for file in files:
if os.path.isfile(file):
filenames.append(file)
else:
filenames.append(os.path.join(srcdir, file))
if len(filenames) < 1:
print("No files found")
sys.exit(1)
# Look through all files, applying the regex to each line.
# If the pattern matches, save the "symbol" section to the
# appropriate array.
regs = {
'proto_reg': [],
'handoff_reg': [],
'wtap_register': [],
}
# For those that don't know Python, r"" indicates a raw string,
# devoid of Python escapes.
proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
wtap_reg_regex0 = r"^(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
wtap_reg_regex1 = r"void\s+(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$"
# This table drives the pattern-matching and symbol-harvesting
patterns = [
( 'proto_reg', re.compile(proto_regex0) ),
( 'proto_reg', re.compile(proto_regex1) ),
( 'handoff_reg', re.compile(handoff_regex0) ),
( 'handoff_reg', re.compile(handoff_regex1) ),
( 'wtap_register', re.compile(wtap_reg_regex0) ),
( 'wtap_register', re.compile(wtap_reg_regex1) ),
]
# Open our registration symbol cache
cache = None
if cache_filename:
try:
cache_file = open(cache_filename, 'rb')
cache = pickle.load(cache_file)
cache_file.close()
if VERSION_KEY not in cache or cache[VERSION_KEY] != CUR_VERSION:
cache = {VERSION_KEY: CUR_VERSION}
except:
cache = {VERSION_KEY: CUR_VERSION}
print(("Registering %d files, %d cached" % (len(filenames), len(list(cache.keys()))-1)))
# Grep
cache_hits = 0
cache_misses = 0
for filename in filenames:
file = open(filename)
cur_mtime = os.fstat(file.fileno())[ST_MTIME]
if cache and filename in cache:
cdict = cache[filename]
if cur_mtime == cdict['mtime']:
cache_hits += 1
# print "Pulling %s from cache" % (filename)
regs['proto_reg'].extend(cdict['proto_reg'])
regs['handoff_reg'].extend(cdict['handoff_reg'])
regs['wtap_register'].extend(cdict['wtap_register'])
file.close()
continue
# We don't have a cache entry
if cache is not None:
cache_misses += 1
cache[filename] = {
'mtime': cur_mtime,
'proto_reg': [],
'handoff_reg': [],
'wtap_register': [],
}
# print "Searching %s" % (filename)
for line in file.readlines():
for action in patterns:
regex = action[1]
match = regex.search(line)
if match:
symbol = match.group("symbol")
sym_type = action[0]
regs[sym_type].append(symbol)
if cache is not None:
# print "Caching %s for %s: %s" % (sym_type, filename, symbol)
cache[filename][sym_type].append(symbol)
file.close()
if cache is not None and cache_filename is not None:
cache_file = open(cache_filename, 'wb')
pickle.dump(cache, cache_file)
cache_file.close()
print(("Cache hits: %d, misses: %d" % (cache_hits, cache_misses)))
# Make sure we actually processed something
if len(regs['proto_reg']) < 1:
print("No protocol registrations found")
sys.exit(1)
# Sort the lists to make them pretty
regs['proto_reg'].sort()
regs['handoff_reg'].sort()
regs['wtap_register'].sort()
reg_code = open(tmp_filename, "w")
reg_code.write(preamble)
# Make the routine to register all protocols
if registertype == "plugin" or registertype == "plugin_wtap":
reg_code.write("""
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gmodule.h>
#include "moduleinfo.h"
#ifndef ENABLE_STATIC
G_MODULE_EXPORT const gchar version[] = VERSION;
/* Start the functions we need for the plugin stuff */
G_MODULE_EXPORT void
plugin_register (void)
{
""");
else:
reg_code.write("""
#include "register.h"
void
register_all_protocols(register_cb cb, gpointer client_data)
{
""");
for symbol in regs['proto_reg']:
if registertype == "plugin" or registertype == "plugin_wtap":
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
else:
line = " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
reg_code.write(line)
reg_code.write("}\n")
# Make the routine to register all protocol handoffs
if registertype == "plugin" or registertype == "plugin_wtap":
reg_code.write("""
G_MODULE_EXPORT void
plugin_reg_handoff(void)
{
""");
else:
reg_code.write("""
void
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
{
""");
for symbol in regs['handoff_reg']:
if registertype == "plugin" or registertype == "plugin_wtap":
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
else:
line = " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol)
reg_code.write(line)
reg_code.write("}\n")
if registertype == "plugin":
reg_code.write("#endif\n");
elif registertype == "plugin_wtap":
reg_code.write("""
G_MODULE_EXPORT void
register_wtap_module(void)
{
""");
for symbol in regs['wtap_register']:
line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
reg_code.write(line)
reg_code.write("}\n");
reg_code.write("#endif\n");
else:
reg_code.write("""
static gulong proto_reg_count(void)
{
""");
line = " return %d;\n" % len(regs['proto_reg'])
reg_code.write(line)
reg_code.write("""
}
""");
reg_code.write("""
static gulong handoff_reg_count(void)
{
""");
line = " return %d;\n" % len(regs['handoff_reg'])
reg_code.write(line)
reg_code.write("""
}
""");
reg_code.write("""
gulong register_count(void)
{
""");
line = " return proto_reg_count() + handoff_reg_count();"
reg_code.write(line)
reg_code.write("""
}\n
""");
# Close the file
reg_code.close()
# Remove the old final_file if it exists.
try:
os.stat(final_filename)
os.remove(final_filename)
except OSError:
pass
# Move from tmp file to final file
os.rename(tmp_filename, final_filename)

View File

@ -0,0 +1,3 @@
Authors:
Michael Ossmann <mike@ossmann.com>
Dominic Spill <dominicgs@gmail.com>

View File

@ -0,0 +1,86 @@
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
project(btbredr-wireshark-plugin C)
cmake_minimum_required(VERSION 2.6)
set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
IF ( NOT CMAKE_INSTALL_LIBDIR )
set(CMAKE_INSTALL_LIBDIR ~/.wireshark/plugins)
ENDIF ( NOT CMAKE_INSTALL_LIBDIR )
MESSAGE (STATUS "Plugin will be installed in: ${CMAKE_INSTALL_LIBDIR}")
INCLUDE(UseMakeDissectorReg)
set(GLIB2_MIN_VERSION 2.4.0)
find_package(GLIB2)
include_directories (${GLIB2_INCLUDE_DIRS})
find_package(Wireshark)
include_directories (${WIRESHARK_INCLUDE_DIRS})
set(LINK_MODE_LIB SHARED)
set(LINK_MODE_MODULE MODULE)
set(DISSECTOR_SRC
packet-btbredr.c
packet-btlmp.c
)
set(PLUGIN_FILES
plugin.c
${DISSECTOR_SRC}
)
set(CLEAN_FILES
${PLUGIN_FILES}
)
if (WERROR)
set_source_files_properties(
${CLEAN_FILES}
PROPERTIES
COMPILE_FLAGS -Werror
)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
register_dissector_files(plugin.c
plugin
${DISSECTOR_SRC}
)
add_library(btbredr ${LINK_MODE_MODULE}
${PLUGIN_FILES}
)
set_target_properties(btbredr PROPERTIES PREFIX "")
set_target_properties(btbredr PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
target_link_libraries(btbredr wireshark)
install(TARGETS btbredr
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ NAMELINK_SKIP
)

View File

@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
<signature of Ty Coon>, 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.

View File

@ -0,0 +1,16 @@
BTBB Basic and Enhanced Data Rate Wireshark plugin
This is the Bluetooth baseband plugin for Wireshark, it also includes an LMP
level dissector.
To build this on Debian/Ubuntu/BackTrack linux distributions:
sudo apt-get install wireshark-dev wireshark
cd libbtbb/wireshark/plugins/btbredr/
mkdir build
cd build
cmake ..
make
make install
This will install to the .wireshark/ in your home directory. To override this
set the DESTDIR environment variable when running cmake.

View File

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,27 @@
Copyright notice for the files copied from
http://www.opensync.org/browser/branches/3rd-party-cmake-modules/modules
$Id: COPYING-CMAKE-SCRIPTS 34248 2010-09-25 15:38:12Z jmayer $
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Some files were not shown because too many files have changed in this diff Show More