diff options
Diffstat (limited to 'src/tinyb_hci')
-rw-r--r-- | src/tinyb_hci/BTDataTypes.cpp | 354 | ||||
-rw-r--r-- | src/tinyb_hci/BasicTypes.cpp | 151 | ||||
-rw-r--r-- | src/tinyb_hci/CMakeLists.txt | 45 | ||||
-rw-r--r-- | src/tinyb_hci/HCIAdapter.cpp | 417 | ||||
-rw-r--r-- | src/tinyb_hci/HCIDevice.cpp | 163 | ||||
-rw-r--r-- | src/tinyb_hci/UUID.cpp | 156 | ||||
-rw-r--r-- | src/tinyb_hci/tinyb_hci.pc.cmake | 11 |
7 files changed, 0 insertions, 1297 deletions
diff --git a/src/tinyb_hci/BTDataTypes.cpp b/src/tinyb_hci/BTDataTypes.cpp deleted file mode 100644 index f17aa9da..00000000 --- a/src/tinyb_hci/BTDataTypes.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Author: Sven Gothel <[email protected]> - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include <cstring> -#include <string> -#include <memory> -#include <cstdint> -#include <vector> -#include <cstdio> - -#include <algorithm> - -#include "BTDataTypes.hpp" - -/** - * TODO libbluetooth replacement: - * - bt_compidtostr - */ - -#define VERBOSE_ON 1 - -#ifdef VERBOSE_ON - #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) -#else - #define DBG_PRINT(...) -#endif - - -using namespace tinyb_hci; - -static inline const int8_t * const_uint8_to_const_int8_ptr(const uint8_t* p) { - return static_cast<const int8_t *>( static_cast<void *>( const_cast<uint8_t*>( p ) ) ); -} - -static std::string bt_compidtostr(const uint16_t companyid) { - return std::to_string(companyid); -} - -std::string EUI48::toString() const { - char cstr[17+1]; - - const int count = sprintf(cstr, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - b[5], b[4], b[3], b[2], b[1], b[0]); - - if( 17 != count ) { - std::string msg("EUI48 string not of length 17 but "); - msg.append(std::to_string(count)); - throw InternalError(msg, E_FILE_LINE); - } - return std::string(cstr); -} - -EUI48::EUI48(const std::string str) { - if( 17 != str.length() ) { - std::string msg("EUI48 string not of length 17 but "); - msg.append(std::to_string(str.length())); - msg.append(": "+str); - throw IllegalArgumentException(msg, E_FILE_LINE); - } - if ( sscanf(str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - &b[5], &b[4], &b[3], &b[2], &b[1], &b[0]) != 6 ) - { - std::string msg("EUI48 string not in format '00:00:00:00:00:00' but "+str); - throw IllegalArgumentException(msg, E_FILE_LINE); - } - - // sscanf provided host data type, in which we store the values, - // hence no endian conversion -} - -const EUI48 EUI48_ANY_DEVICE; // default ctor is zero bytes! - -// ************************************************* -// ************************************************* -// ************************************************* - -ManufactureSpecificData::ManufactureSpecificData(uint16_t const company, uint8_t const * const data, int const data_len) -: company(company), companyName(std::string(bt_compidtostr(company))), data_len(data_len), data(new uint8_t[data_len]) { - memcpy(this->data.get(), data, data_len); -} - -std::string ManufactureSpecificData::toString() const { - std::string out("MSD["); - out.append(std::to_string(company)+" "+companyName); - out.append(", data "+std::to_string(data_len)+" bytes]"); - return out; -} - -// ************************************************* -// ************************************************* -// ************************************************* - -std::string EInfoReport::getSourceString() const { - switch (source) { - case Source::NA: return "N/A"; - case Source::AD: return "AD"; - case Source::EIR: return "EIR"; - } - return "N/A"; -} - -void EInfoReport::setName(const uint8_t *buffer, int buffer_len) { - name = get_string(buffer, buffer_len, 30); - set(Element::NAME); -} - -void EInfoReport::setShortName(const uint8_t *buffer, int buffer_len) { - name_short = get_string(buffer, buffer_len, 30); - set(Element::NAME_SHORT); -} - -void EInfoReport::addService(std::shared_ptr<UUID> const &uuid) -{ - auto begin = services.begin(); - auto it = std::find_if(begin, services.end(), [&](std::shared_ptr<UUID> const& p) { - return *p == *uuid; - }); - if ( it == std::end(services) ) { - services.push_back(uuid); - } -} - -std::string EInfoReport::dataSetToString(const uint32_t data_set) { - std::string out("["); - if( isSet(data_set, Element::EVT_TYPE) ) { - out.append("EVT_TYPE, "); - } - if( isSet(data_set, Element::BDADDR) ) { - out.append("BDADDR, "); - } - if( isSet(data_set, Element::NAME) ) { - out.append("NAME, "); - } - if( isSet(data_set, Element::NAME_SHORT) ) { - out.append("NAME_SHORT, "); - } - if( isSet(data_set, Element::RSSI) ) { - out.append("RSSI, "); - } - if( isSet(data_set, Element::TX_POWER) ) { - out.append("TX_POWER, "); - } - if( isSet(data_set, Element::MANUF_DATA) ) { - out.append("MANUF_DATA, "); - } - out.append("]"); - return out; -} -std::string EInfoReport::dataSetToString() const { - return std::string("DataSet"+dataSetToString(data_set)); -} -std::string EInfoReport::toString() const { - std::string msdstr = nullptr != msd ? msd->toString() : "MSD[null]"; - std::string out("EInfoReport::"+getSourceString()+"["+getAddressString()+", "+name+"/"+name_short+", "+dataSetToString()+ - ", evt-type "+std::to_string(evt_type)+", rssi "+std::to_string(rssi)+ - ", tx-power "+std::to_string(tx_power)+", "+msdstr+"]"); - if(services.size() > 0 ) { - out.append("\n"); - for(auto it = services.begin(); it != services.end(); it++) { - std::shared_ptr<UUID> p = *it; - out.append(" ").append(p->toUUID128String()).append(", ").append(std::to_string(static_cast<int>(p->type))).append(" bytes\n"); - } - } - return out; -} - -// ************************************************* -// ************************************************* -// ************************************************* - -int EInfoReport::next_data_elem(uint8_t *eir_elem_len, uint8_t *eir_elem_type, uint8_t const **eir_elem_data, - uint8_t const * data, int offset, int const size) -{ - if (offset < size) { - uint8_t len = data[offset]; // covers: type + data, less len field itself - - if (len == 0) { - return 0; // end of significant part - } - - if (len + offset > size) { - return -ENOENT; - } - - *eir_elem_type = data[offset + 1]; - *eir_elem_data = data + offset + 2; // net data ptr - *eir_elem_len = len - 1; // less type -> net data length - - return offset + 1 + len; // next ad_struct offset: + len + type + data - } - return -ENOENT; -} - -int EInfoReport::read_data(uint8_t const * data, uint8_t const data_length) { - int count = 0; - int offset = 0; - uint8_t elem_len, elem_type; - uint8_t const *elem_data; - - while( 0 < ( offset = next_data_elem( &elem_len, &elem_type, &elem_data, data, offset, data_length ) ) ) - { - DBG_PRINT("%s-Element[%d] @ [%d/%d]: type 0x%.2X with %d bytes net\n", - getSourceString().c_str(), count, offset, data_length, elem_type, elem_len); - count++; - - // Guaranteed: eir_elem_len >= 0! - switch ( elem_type ) { - case GAP_T::FLAGS: - // FIXME - break; - case GAP_T::UUID16_INCOMPLETE: - case GAP_T::UUID16_COMPLETE: - for(int j=0; j<elem_len/2; j++) { - const std::shared_ptr<UUID> uuid(new UUID16(elem_data, j*2, true)); - addService(std::move(uuid)); - } - break; - case GAP_T::UUID32_INCOMPLETE: - case GAP_T::UUID32_COMPLETE: - for(int j=0; j<elem_len/4; j++) { - const std::shared_ptr<UUID> uuid(new UUID32(elem_data, j*4, true)); - addService(std::move(uuid)); - } - break; - case GAP_T::UUID128_INCOMPLETE: - case GAP_T::UUID128_COMPLETE: - for(int j=0; j<elem_len/16; j++) { - const std::shared_ptr<UUID> uuid(new UUID128(elem_data, j*16, true)); - addService(std::move(uuid)); - } - break; - case GAP_T::NAME_LOCAL_SHORT: - case GAP_T::NAME_LOCAL_COMPLETE: { - if( GAP_T::NAME_LOCAL_COMPLETE == elem_type ) { - setName(elem_data, elem_len); - } else { - setShortName(elem_data, elem_len); - } - } break; - case GAP_T::TX_POWER_LEVEL: - setTxPower(*const_uint8_to_const_int8_ptr(elem_data)); - break; - - case GAP_T::SSP_CLASS_OF_DEVICE: - case GAP_T::DEVICE_ID: - case GAP_T::SOLICIT_UUID16: - case GAP_T::SOLICIT_UUID128: - case GAP_T::SVC_DATA_UUID16: - case GAP_T::PUB_TRGT_ADDR: - case GAP_T::RND_TRGT_ADDR: - case GAP_T::GAP_APPEARANCE: - case GAP_T::SOLICIT_UUID32: - case GAP_T::SVC_DATA_UUID32: - case GAP_T::SVC_DATA_UUID128: - break; - - case GAP_T::MANUFACTURE_SPECIFIC: { - uint16_t company = get_uint16(elem_data, 0, true /* littleEndian */); - setManufactureSpecificData(company, elem_data+2, elem_len-2); - } break; - - default: { - // FIXME: Use a data blob!!!! - fprintf(stderr, "%s-Element @ [%d/%d]: Warning: Unhandled type 0x%.2X with %d bytes net\n", - getSourceString().c_str(), offset, data_length, elem_type, elem_len); - } break; - } - } - return count; -} - -std::vector<std::shared_ptr<EInfoReport>> EInfoReport::read_ad_reports(uint8_t const * data, uint8_t const data_length) { - int const num_reports = (int) data[0]; - std::vector<std::shared_ptr<EInfoReport>> ad_reports; - - if( 0 >= num_reports || num_reports > 0x19 ) { - DBG_PRINT("AD-Reports: Invalid reports count: %d\n", num_reports); - return ad_reports; - } - uint8_t const *limes = data + data_length; - uint8_t const *i_octets = data + 1; - uint8_t ad_data_len[0x19]; - const int segment_count = 6; - int read_segments = 0; - int i; - - for(i = 0; i < num_reports && i_octets < limes; i++) { - ad_reports.push_back(std::shared_ptr<EInfoReport>(new EInfoReport())); - ad_reports[i]->setSource(Source::AD); - ad_reports[i]->setTimestamp(getCurrentMilliseconds()); - ad_reports[i]->setEvtType(*i_octets++); - read_segments++; - } - for(i = 0; i < num_reports && i_octets < limes; i++) { - ad_reports[i]->setAddressType(*i_octets++); - read_segments++; - } - for(i = 0; i < num_reports && i_octets + 5 < limes; i++) { - ad_reports[i]->setAddress( *((EUI48 const *)i_octets) ); - i_octets += 6; - read_segments++; - } - for(i = 0; i < num_reports && i_octets < limes; i++) { - ad_data_len[i] = *i_octets++; - read_segments++; - } - for(i = 0; i < num_reports && i_octets + ad_data_len[i] < limes; i++) { - ad_reports[i]->read_data(i_octets, ad_data_len[i]); - i_octets += ad_data_len[i]; - read_segments++; - } - for(i = 0; i < num_reports && i_octets < limes; i++) { - ad_reports[i]->setRSSI(*const_uint8_to_const_int8_ptr(i_octets)); - i_octets++; - read_segments++; - } - const int bytes_left = limes - i_octets; - - if( segment_count != read_segments ) { - fprintf(stderr, "AD-Reports: Warning: Incomplete %d reports within %d bytes: Segment read %d < %d, data-ptr %d bytes to limes\n", - num_reports, data_length, read_segments, segment_count, bytes_left); - } else { - DBG_PRINT("AD-Reports: Completed %d reports within %d bytes: Segment read %d == %d, data-ptr %d bytes to limes\n", - num_reports, data_length, read_segments, segment_count, bytes_left); - } - return ad_reports; -} - -// ************************************************* -// ************************************************* -// ************************************************* - diff --git a/src/tinyb_hci/BasicTypes.cpp b/src/tinyb_hci/BasicTypes.cpp deleted file mode 100644 index 97ef1cfc..00000000 --- a/src/tinyb_hci/BasicTypes.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Author: Sven Gothel <[email protected]> - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "BasicTypes.hpp" - -// #define _USE_BACKTRACE_ 1 - -#if _USE_BACKTRACE_ -extern "C" { - #include <execinfo.h> -} -#endif - -using namespace tinyb_hci; - -static const int64_t NanoPerMilli = 1000000L; -static const int64_t MilliPerOne = 1000L; - -/** - * See <http://man7.org/linux/man-pages/man2/clock_gettime.2.html> - * <p> - * Regarding avoiding kernel via VDSO, - * see <http://man7.org/linux/man-pages/man7/vdso.7.html>, - * clock_gettime seems to be well supported at least on kernel >= 4.4. - * Only bfin and sh are missing, while ia64 seems to be complicated. - */ -int64_t tinyb_hci::getCurrentMilliseconds() { - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - return t.tv_sec * MilliPerOne + t.tv_nsec / NanoPerMilli; -} - -const char* RuntimeException::what() const noexcept { -#if _USE_BACKTRACE_ - std::string out(msg); - void *buffers[10]; - size_t nptrs = backtrace(buffers, 10); - char **symbols = backtrace_symbols(buffers, nptrs); - if( NULL != symbols ) { - out.append("\nBacktrace:\n"); - for(int i=0; i<nptrs; i++) { - out.append(symbols[i]).append("\n"); - } - free(symbols); - } - return out.c_str(); -#else - return msg.c_str(); -#endif -} - -std::string tinyb_hci::get_string(const uint8_t *buffer, int const buffer_len, int const max_len) { - const int cstr_len = std::min(buffer_len, max_len); - char cstr[max_len+1]; // EOS - memcpy(cstr, buffer, cstr_len); - cstr[cstr_len] = 0; // EOS - return std::string(cstr); -} - -uint128_t tinyb_hci::merge_uint128(uint128_t const & base_uuid, uint16_t const uuid16, int const uuid16_le_octet_index) -{ - if( 0 > uuid16_le_octet_index || uuid16_le_octet_index > 14 ) { - std::string msg("uuid16_le_octet_index "); - msg.append(std::to_string(uuid16_le_octet_index)); - msg.append(", not within [0..14]"); - throw IllegalArgumentException(msg, E_FILE_LINE); - } - uint128_t dest = base_uuid; - - // base_uuid: 00000000-0000-1000-8000-00805F9B34FB - // uuid16: DCBA - // uuid16_le_octet_index: 12 - // result: 0000DCBA-0000-1000-8000-00805F9B34FB - // - // LE: low-mem - FB349B5F8000-0080-0010-0000-ABCD0000 - high-mem - // ^ index 12 - // LE: uuid16 -> value.data[12+13] - // - // BE: low-mem - 0000DCBA-0000-1000-8000-00805F9B34FB - high-mem - // ^ index 2 - // BE: uuid16 -> value.data[2+3] - // -#if __BYTE_ORDER == __BIG_ENDIAN - int offset = 15 - 1 - uuid16_le_octet_index; -#elif __BYTE_ORDER == __LITTLE_ENDIAN - int offset = uuid16_le_octet_index; -#else -#error "Unexpected __BYTE_ORDER" -#endif - uint16_t * destu16 = (uint16_t*)(dest.data + offset); - *destu16 += uuid16; - return dest; -} - -uint128_t tinyb_hci::merge_uint128(uint128_t const & base_uuid, uint32_t const uuid32, int const uuid32_le_octet_index) -{ - if( 0 > uuid32_le_octet_index || uuid32_le_octet_index > 12 ) { - std::string msg("uuid32_le_octet_index "); - msg.append(std::to_string(uuid32_le_octet_index)); - msg.append(", not within [0..12]"); - throw IllegalArgumentException(msg, E_FILE_LINE); - } - uint128_t dest = base_uuid; - - // base_uuid: 00000000-0000-1000-8000-00805F9B34FB - // uuid32: 87654321 - // uuid32_le_octet_index: 12 - // result: 87654321-0000-1000-8000-00805F9B34FB - // - // LE: low-mem - FB349B5F8000-0080-0010-0000-12345678 - high-mem - // ^ index 12 - // LE: uuid32 -> value.data[12..15] - // - // BE: low-mem - 87654321-0000-1000-8000-00805F9B34FB - high-mem - // ^ index 0 - // BE: uuid32 -> value.data[0..3] - // -#if __BYTE_ORDER == __BIG_ENDIAN - int offset = 15 - 3 - uuid32_le_octet_index; -#elif __BYTE_ORDER == __LITTLE_ENDIAN - int offset = uuid32_le_octet_index; -#else -#error "Unexpected __BYTE_ORDER" -#endif - uint32_t * destu32 = (uint32_t*)(dest.data + offset); - *destu32 += uuid32; - return dest; -} - diff --git a/src/tinyb_hci/CMakeLists.txt b/src/tinyb_hci/CMakeLists.txt deleted file mode 100644 index d50d40c6..00000000 --- a/src/tinyb_hci/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -set (tinyb_hci_LIB_INCLUDE_DIRS - ${PROJECT_SOURCE_DIR}/api - ${PROJECT_SOURCE_DIR}/api/tinyb_hci - ${PROJECT_SOURCE_DIR}/include -) - -include_directories( - ${tinyb_hci_LIB_INCLUDE_DIRS} - ${CMAKE_CURRENT_BINARY_DIR} -) - -set (tinyb_hci_LIB_SRCS - ${PROJECT_SOURCE_DIR}/src/tinyb_hci/BasicTypes.cpp - ${PROJECT_SOURCE_DIR}/src/tinyb_hci/UUID.cpp - ${PROJECT_SOURCE_DIR}/src/tinyb_hci/BTDataTypes.cpp - ${PROJECT_SOURCE_DIR}/src/tinyb_hci/HCIAdapter.cpp - ${PROJECT_SOURCE_DIR}/src/tinyb_hci/HCIDevice.cpp -# autogenerated files - ${CMAKE_CURRENT_BINARY_DIR}/../version.c -) - -add_library (tinyb_hci SHARED ${tinyb_hci_LIB_SRCS}) -target_link_libraries ( - tinyb_hci - ${CMAKE_THREAD_LIBS_INIT} - bluetooth -) - -set_target_properties( - tinyb_hci - PROPERTIES - SOVERSION ${tinyb_VERSION_MAJOR} - VERSION ${tinyb_VERSION_STRING} - CXX_STANDARD 11 -) -install (DIRECTORY ${PROJECT_SOURCE_DIR}/api/tinyb_hci/ DESTINATION include/tinyb_hci) - -macro (tinyb_CREATE_INSTALL_PKGCONFIG generated_file install_location) - configure_file (${generated_file}.cmake ${CMAKE_CURRENT_BINARY_DIR}/${generated_file} @ONLY) - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${generated_file} DESTINATION ${install_location}) -endmacro (tinyb_CREATE_INSTALL_PKGCONFIG) -tinyb_create_install_pkgconfig (tinyb_hci.pc lib${LIB_SUFFIX}/pkgconfig) - -install(TARGETS tinyb_hci LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - diff --git a/src/tinyb_hci/HCIAdapter.cpp b/src/tinyb_hci/HCIAdapter.cpp deleted file mode 100644 index 38e28cd4..00000000 --- a/src/tinyb_hci/HCIAdapter.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Author: Sven Gothel <[email protected]> - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include <cstring> -#include <string> -#include <memory> -#include <cstdint> -#include <vector> -#include <cstdio> - -#include <algorithm> - -#include <inttypes.h> -#include <unistd.h> -#include <poll.h> - -extern "C" { - #include <bluetooth/bluetooth.h> - #include <bluetooth/hci.h> - #include <bluetooth/hci_lib.h> -} - -#include "HCITypes.hpp" - -#define VERBOSE_ON 1 - -#ifdef VERBOSE_ON - #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) -#else - #define DBG_PRINT(...) -#endif - -using namespace tinyb_hci; - -static inline bdaddr_t* eui48_to_bdaddr_ptr(EUI48 *p) { - return static_cast<bdaddr_t *>( static_cast<void *>( p ) ); -} - - -// ************************************************* -// ************************************************* -// ************************************************* - -std::atomic_int HCISession::name_counter(0); - -bool HCISession::close() -{ - if( 0 > _dd ) { - return false; - } - hci_close_dev(_dd); - _dd = -1; - adapter.sessionClosed(*this); - return true; -} - -// ************************************************* -// ************************************************* -// ************************************************* - -int HCIAdapter::getDefaultDevId() { - return hci_get_route(NULL); -} -int HCIAdapter::getDevId(EUI48 &mac) { - return hci_get_route( eui48_to_bdaddr_ptr( &mac ) ); -} -int HCIAdapter::getDevId(const std::string &hcidev) { - return hci_devid(hcidev.c_str()); -} - -bool HCIAdapter::validateDevInfo() { - if( 0 > dev_id ) { - return false; - } - struct hci_dev_info dev_info; - bzero(&dev_info, sizeof(dev_info)); - if( 0 > hci_devinfo(dev_id, &dev_info) ) { - return false; - } - memcpy(&mac, &dev_info.bdaddr, sizeof(mac)); - name = std::string(dev_info.name); - return true; -} - -void HCIAdapter::sessionClosed(HCISession& s) -{ - auto it = std::find_if(sessions.begin(), sessions.end(), [&](std::shared_ptr<HCISession> const& p) { - return *p == s; - }); - if ( it != std::end(sessions) ) { - sessions.erase(it); - } -} - -HCIAdapter::HCIAdapter() -: dev_id(getDefaultDevId()) -{ - valid = validateDevInfo(); -} - -HCIAdapter::HCIAdapter(EUI48 &mac) -: dev_id(getDevId(mac)) -{ - valid = validateDevInfo(); -} - -HCIAdapter::HCIAdapter(const std::string &hcidev) -: dev_id(getDevId(hcidev)) -{ - valid = validateDevInfo(); -} - -HCIAdapter::HCIAdapter(const int dev_id) -: dev_id(dev_id) -{ - valid = validateDevInfo(); -} - -HCIAdapter::~HCIAdapter() { - scannedDevices.clear(); - discoveredDevices.clear(); - sessions.clear(); -} - -std::shared_ptr<HCISession> HCIAdapter::open() -{ - if( !valid ) { - return nullptr; - } - int dd = hci_open_dev(dev_id); - if( 0 > dd ) { - perror("Could not open device"); - return nullptr; - } - std::shared_ptr<HCISession> s(new HCISession(*this, dd)); - sessions.push_back(s); - return s; -} - -std::shared_ptr<HCIDeviceDiscoveryListener> HCIAdapter::setDeviceDiscoveryListener(std::shared_ptr<HCIDeviceDiscoveryListener> l) -{ - std::shared_ptr<HCIDeviceDiscoveryListener> o = deviceDiscoveryListener; - deviceDiscoveryListener = l; - return o; -} - -bool HCIAdapter::startDiscovery(HCISession &s, - uint16_t interval, uint16_t window, - uint8_t own_mac_type) -{ - const uint8_t scan_type = 0x01; - const uint8_t filter_type = 0; - const uint8_t filter_policy = 0x00; - const uint8_t filter_dup = 0x01; - - if( !s.isOpen() ) { - fprintf(stderr, "Session not open\n"); - return false; - } - int err = hci_le_set_scan_parameters(s.dd(), scan_type, - cpu_to_le(interval), cpu_to_le(window), - own_mac_type, filter_policy, to_send_req_poll_ms); - if (err < 0) { - perror("Set scan parameters failed"); - return false; - } - - err = hci_le_set_scan_enable(s.dd(), 0x01, filter_dup, to_send_req_poll_ms); - if (err < 0) { - perror("Start scan failed"); - return false; - } - return true; -} - -bool HCIAdapter::stopDiscovery(HCISession& session) { - const uint8_t filter_dup = 0x01; - - if( !session.isOpen() ) { - fprintf(stderr, "Session not open\n"); - return false; - } - bool res; - if( 0 > hci_le_set_scan_enable(session.dd(), 0x00, filter_dup, to_send_req_poll_ms) ) { - perror("Stop scan failed"); - res = false; - } else { - res = true; - } - return res; -} - -int HCIAdapter::findDevice(std::vector<std::shared_ptr<HCIDevice>> const & devices, EUI48 const & mac) { - auto begin = devices.begin(); - auto it = std::find_if(begin, devices.end(), [&](std::shared_ptr<HCIDevice> const& p) { - return p->mac == mac; - }); - if ( it == std::end(devices) ) { - return -1; - } else { - return std::distance(begin, it); - } -} - -bool HCIAdapter::addScannedDevice(std::shared_ptr<HCIDevice> const &device) { - if( 0 > findDevice(scannedDevices, device->mac) ) { - scannedDevices.push_back(device); - return true; - } - return false; -} - -bool HCIAdapter::addDiscoveredDevice(std::shared_ptr<HCIDevice> const &device) { - if( 0 > findDiscoveredDevice(device->mac) ) { - discoveredDevices.push_back(device); - return true; - } - return false; -} - -int HCIAdapter::findDiscoveredDevice(EUI48 const & mac) const { - return findDevice(discoveredDevices, mac); -} - -void HCIAdapter::removeDiscoveredDevices() { - // also need to flush scannedDevices, old data - scannedDevices.clear(); - discoveredDevices.clear(); -} - -std::string HCIAdapter::toString() const { - std::string out("Adapter["+getAddressString()+", '"+getName()+"', id="+std::to_string(dev_id)+"]"); - if(discoveredDevices.size() > 0 ) { - out.append("\n"); - for(auto it = discoveredDevices.begin(); it != discoveredDevices.end(); it++) { - std::shared_ptr<HCIDevice> p = *it; - out.append(" ").append(p->toString()).append("\n"); - } - } - return out; -} - -// ************************************************* - -int HCIAdapter::discoverDevices(HCISession& session, - const int waitForDeviceCount, - const EUI48 &waitForDevice, - const int timeoutMS, - const uint32_t ad_type_req) -{ - uint8_t buf[HCI_MAX_EVENT_SIZE]; - struct hci_filter nf, of; - socklen_t olen; - int bytes_left = -1; - const int64_t t0 = getCurrentMilliseconds(); - - if( !session.isOpen() ) { - fprintf(stderr, "Session not open\n"); - return false; - } - - olen = sizeof(of); - if (getsockopt(session.dd(), SOL_HCI, HCI_FILTER, &of, &olen) < 0) { - fprintf(stderr, "Could not get socket options\n"); - return false; - } - - hci_filter_clear(&nf); - hci_filter_set_ptype(HCI_EVENT_PKT, &nf); - hci_filter_set_event(EVT_LE_META_EVENT, &nf); - - if (setsockopt(session.dd(), SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { - fprintf(stderr, "Could not set socket options\n"); - return false; - } - - const uint32_t ad_req = static_cast<uint32_t>(EInfoReport::Element::BDADDR) | - static_cast<uint32_t>(EInfoReport::Element::RSSI) | - ad_type_req; - bool done = false; - int64_t t1; - int matchedDeviceCount = 0, loop=0; - - while ( !done && ( ( t1 = getCurrentMilliseconds() ) - t0 ) < timeoutMS ) { - uint8_t hci_type; - hci_event_hdr *ehdr; - evt_le_meta_event *meta; - loop++; - - if( timeoutMS ) { - struct pollfd p; - int n; - - p.fd = session.dd(); p.events = POLLIN; - while ((n = poll(&p, 1, timeoutMS)) < 0) { - if (errno == EAGAIN || errno == EINTR ) { - // cont temp unavail or interruption - continue; - } - goto errout; - } - if (!n) { - goto done; // timeout: exit but no error - } - } - - while ((bytes_left = read(session.dd(), buf, sizeof(buf))) < 0) { - if (errno == EAGAIN || errno == EINTR ) { - // cont temp unavail or interruption - continue; - } - goto errout; - } - - if( bytes_left < HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE + EVT_LE_META_EVENT_SIZE ) { - // not enough data .. - continue; - } - hci_type = buf[0]; // sizeof HCI_TYPE_LEN - - ehdr = (hci_event_hdr*)(void*) ( buf + HCI_TYPE_LEN ); // sizeof HCI_EVENT_HDR_SIZE - - bytes_left -= (HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE); - meta = (evt_le_meta_event*)(void *) ( buf + ( HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE ) ); // sizeof EVT_LE_META_EVENT_SIZE - - if( bytes_left < ehdr->plen ) { - // not enough data .. - fprintf(stderr, "HCIAdapter::discovery[%d]: Warning: Incomplete type 0x%.2X, event 0x%.2X, subevent 0x%.2X, remaining %d bytes < plen %d!\n", - loop-1, hci_type, ehdr->evt, meta->subevent, bytes_left, ehdr->plen); - continue; - } else { - DBG_PRINT("HCIAdapter::discovery[%d]: Complete type 0x%.2X, event 0x%.2X, subevent 0x%.2X, remaining %d bytes >= plen %d\n", - loop-1, hci_type, ehdr->evt, meta->subevent, bytes_left, ehdr->plen); - } - - // HCI_LE_Advertising_Report == 0x3E == EVT_LE_META_EVENT - // 0x3E 0x02 - if ( HCI_Event_Types::LE_Advertising_Report != ehdr->evt || meta->subevent != EVT_LE_ADVERTISING_REPORT ) { - continue; // next .. - } - bytes_left -= EVT_LE_META_EVENT_SIZE; - - std::vector<std::shared_ptr<EInfoReport>> ad_reports = EInfoReport::read_ad_reports(meta->data, bytes_left); - const int num_reports = ad_reports.size(); - - for(int i = 0; i < num_reports && i < 0x19; i++) { - std::shared_ptr<EInfoReport> ad_report = ad_reports.at(i); - const bool matches = ( ad_req == ( ad_req & ad_report->getDataSet() ) ) && - ( EUI48_ANY_DEVICE == waitForDevice || ad_report->getAddress() == waitForDevice ); - if( matches ) { - matchedDeviceCount++; - if( 0 < waitForDeviceCount && waitForDeviceCount <= matchedDeviceCount ) { - done = true; - } - } - DBG_PRINT("HCIAdapter::discovery[%d] %d/%d: matches %d, waitForDevice %s, ad_req %s, matchCount %d/%d, done %d\n", - loop-1, i, num_reports, matches, waitForDevice.toString().c_str(), EInfoReport::dataSetToString(ad_req).c_str(), - matchedDeviceCount, waitForDeviceCount, done); - DBG_PRINT("HCIAdapter::discovery[%d] %d/%d: %s\n", loop-1, i, num_reports, ad_report->toString().c_str()); - - int idx = findDevice(scannedDevices, ad_report->getAddress()); - std::shared_ptr<HCIDevice> dev; - if( 0 > idx ) { - // new device - dev = std::shared_ptr<HCIDevice>(new HCIDevice(*this, *ad_report)); - addScannedDevice(dev); - } else { - // existing device - dev = scannedDevices.at(idx); - dev->update(*ad_report); - } - if( matches ) { - if( addDiscoveredDevice(dev) ) { - // new matching - if( nullptr != deviceDiscoveryListener ) { - deviceDiscoveryListener->deviceAdded(*this, dev); - } - } else { - // update - if( nullptr != deviceDiscoveryListener ) { - deviceDiscoveryListener->deviceUpdated(*this, dev); - } - } - } - } - - } -done: - setsockopt(session.dd(), SOL_HCI, HCI_FILTER, &of, sizeof(of)); - return matchedDeviceCount; - -errout: - setsockopt(session.dd(), SOL_HCI, HCI_FILTER, &of, sizeof(of)); - return -1; -} diff --git a/src/tinyb_hci/HCIDevice.cpp b/src/tinyb_hci/HCIDevice.cpp deleted file mode 100644 index c674cf75..00000000 --- a/src/tinyb_hci/HCIDevice.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Author: Sven Gothel <[email protected]> - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include <cstring> -#include <string> -#include <memory> -#include <cstdint> -#include <vector> -#include <cstdio> - -#include <algorithm> - -extern "C" { - #include <bluetooth/bluetooth.h> - #include <bluetooth/hci.h> - #include <bluetooth/hci_lib.h> -} - -#include "HCITypes.hpp" - -using namespace tinyb_hci; - -static inline const bdaddr_t* const_eui48_to_const_bdaddr_ptr(const EUI48 *p) { - return static_cast<const bdaddr_t *>( static_cast<void *>( const_cast<EUI48 *>( p ) ) ); -} - -// ************************************************* -// ************************************************* -// ************************************************* - -HCIDevice::HCIDevice(HCIAdapter const & a, EInfoReport const & r) -: adapter(a), ts_creation(r.getTimestamp()), mac(r.getAddress()) -{ - if( !r.isSet(EInfoReport::Element::BDADDR) ) { - throw IllegalArgumentException("HCIDevice ctor: Address not set: "+r.toString(), E_FILE_LINE); - } - update(r); -} - -void HCIDevice::addService(std::shared_ptr<UUID> const &uuid) -{ - if( 0 > findService(uuid) ) { - services.push_back(uuid); - } -} -void HCIDevice::addServices(std::vector<std::shared_ptr<UUID>> const & services) -{ - for(int j=0; j<services.size(); j++) { - const std::shared_ptr<UUID> uuid = services.at(j); - addService(uuid); - } -} - -int HCIDevice::findService(std::shared_ptr<UUID> const &uuid) const -{ - auto begin = services.begin(); - auto it = std::find_if(begin, services.end(), [&](std::shared_ptr<UUID> const& p) { - return *p == *uuid; - }); - if ( it == std::end(services) ) { - return -1; - } else { - return std::distance(begin, it); - } -} - -std::string HCIDevice::toString() const { - const uint64_t t0 = getCurrentMilliseconds(); - std::string msdstr = nullptr != msd ? msd->toString() : "MSD[null]"; - std::string out("Device["+getAddressString()+", '"+getName()+ - "', age "+std::to_string(t0-ts_creation)+" ms, lup "+std::to_string(t0-ts_update)+" ms, rssi "+std::to_string(getRSSI())+ - ", tx-power "+std::to_string(tx_power)+", "+msdstr+"]"); - if(services.size() > 0 ) { - out.append("\n"); - for(auto it = services.begin(); it != services.end(); it++) { - std::shared_ptr<UUID> p = *it; - out.append(" ").append(p->toUUID128String()).append(", ").append(std::to_string(static_cast<int>(p->type))).append(" bytes\n"); - } - } - return out; -} - -void HCIDevice::update(EInfoReport const & data) { - ts_update = data.getTimestamp(); - if( data.isSet(EInfoReport::Element::NAME) ) { - if( !name.length() || data.getName().length() > name.length() ) { - name = data.getName(); - } - } - if( data.isSet(EInfoReport::Element::NAME_SHORT) ) { - if( !name.length() ) { - name = data.getShortName(); - } - } - if( data.isSet(EInfoReport::Element::RSSI) ) { - rssi = data.getRSSI(); - } - if( data.isSet(EInfoReport::Element::TX_POWER) ) { - tx_power = data.getTxPower(); - } - if( data.isSet(EInfoReport::Element::MANUF_DATA) ) { - msd = data.getManufactureSpecificData(); - } - addServices(data.getServices()); -} - -uint16_t HCIDevice::le_connect(HCISession &s, - uint16_t interval, uint16_t window, - uint16_t min_interval, uint16_t max_interval, - uint16_t latency, uint16_t supervision_timeout, - uint16_t min_ce_length, uint16_t max_ce_length, - uint8_t initiator_filter, - uint8_t peer_mac_type, - uint8_t own_mac_type ) -{ - if( !s.isOpen() ) { - fprintf(stderr, "Session not open\n"); - return 0; - } - uint16_t handle = 0; - bdaddr_t bdmac; - memcpy(&bdmac, const_eui48_to_const_bdaddr_ptr(&mac), sizeof(bdaddr_t)); - - int err = hci_le_create_conn(s.dd(), - cpu_to_le(interval), cpu_to_le(window), - initiator_filter, peer_mac_type, bdmac, own_mac_type, - cpu_to_le(min_interval), cpu_to_le(max_interval), - cpu_to_le(latency), cpu_to_le(supervision_timeout), - cpu_to_le(min_ce_length), cpu_to_le(max_ce_length), - &handle, to_connect_ms); - if (err < 0) { - perror("Could not create connection"); - return 0; - } - return handle; -} - -// ************************************************* -// ************************************************* -// ************************************************* - diff --git a/src/tinyb_hci/UUID.cpp b/src/tinyb_hci/UUID.cpp deleted file mode 100644 index 88b28323..00000000 --- a/src/tinyb_hci/UUID.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Author: Sven Gothel <[email protected]> - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "UUID.hpp" - -using namespace tinyb_hci; - -// BASE_UUID '00000000-0000-1000-8000-00805F9B34FB' -static uint8_t bt_base_uuid_be[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; -UUID128 tinyb_hci::BT_BASE_UUID = UUID128( bt_base_uuid_be, 0, false ); - -UUID128::UUID128(UUID128 const & base_uuid, UUID16 const & uuid16, int const uuid16_le_octet_index) -: UUID(Type::UUID128), value(merge_uint128(base_uuid.value, uuid16.value, uuid16_le_octet_index)) {} - -UUID128::UUID128(UUID128 const & base_uuid, UUID32 const & uuid32, int const uuid32_le_octet_index) -: UUID(Type::UUID128), value(merge_uint128(base_uuid.value, uuid32.value, uuid32_le_octet_index)) {} - -std::string UUID16::toString() const { - char buffer[4+1]; - const int count = snprintf(buffer, sizeof(buffer), "%.4X", value); - if( 4 != count ) { - std::string msg("UUID16 string not of length 4 but "); - msg.append(std::to_string(count)); - throw InternalError(msg, E_FILE_LINE); - } - return std::string(buffer); -} - -std::string UUID16::toUUID128String(UUID128 const & base_uuid, int const le_octet_index) const -{ - UUID128 u128(base_uuid, *this, le_octet_index); - return u128.toString(); -} - -std::string UUID32::toString() const { - char buffer[8+1]; - int count = snprintf(buffer, sizeof(buffer), "%.8X", value); - if( 8 != count ) { - std::string msg("UUID32 string not of length 8 but "); - msg.append(std::to_string(count)); - throw InternalError(msg, E_FILE_LINE); - } - return std::string(buffer); -} - -std::string UUID32::toUUID128String(UUID128 const & base_uuid, int const le_octet_index) const -{ - UUID128 u128(base_uuid, *this, le_octet_index); - return u128.toString(); -} - -std::string UUID128::toString() const { - // 87654321-0000-1000-8000-00805F9B34FB - // 0 1 2 3 4 5 - // LE: low-mem - FB349B5F0800-0080-0010-0000-12345678 - high-mem - // 5 4 3 2 1 0 - // - // BE: low-mem - 87654321-0000-1000-8000-00805F9B34FB - high-mem - // 0 1 2 3 4 5 - // - char buffer[36+1]; - uint32_t part0, part4; - uint16_t part1, part2, part3, part5; - - // snprintf uses host data type, in which values are stored, - // hence no endian conversion -#if __BYTE_ORDER == __BIG_ENDIAN - part0 = get_uint32(value.data, 0); - part1 = get_uint16(value.data, 4); - part2 = get_uint16(value.data, 6); - part3 = get_uint16(value.data, 8); - part4 = get_uint32(value.data, 10); - part5 = get_uint16(value.data, 14); -#elif __BYTE_ORDER == __LITTLE_ENDIAN - part5 = get_uint16(value.data, 0); - part4 = get_uint32(value.data, 2); - part3 = get_uint16(value.data, 6); - part2 = get_uint16(value.data, 8); - part1 = get_uint16(value.data, 10); - part0 = get_uint32(value.data, 12); -#else -#error "Unexpected __BYTE_ORDER" -#endif - int count = snprintf(buffer, sizeof(buffer), "%.8X-%.4X-%.4X-%.4X-%.8X%.4X", - part0, part1, part2, part3, part4, part5); - if( 36 != count ) { - std::string msg("UUID128 string not of length 36 but "); - msg.append(std::to_string(count)); - throw InternalError(msg, E_FILE_LINE); - } - return std::string(buffer); -} - -UUID128::UUID128(const std::string str) -: UUID(Type::UUID128) -{ - uint32_t part0, part4; - uint16_t part1, part2, part3, part5; - - if( 36 != str.length() ) { - std::string msg("UUID128 string not of length 36 but "); - msg.append(std::to_string(str.length())); - msg.append(": "+str); - throw IllegalArgumentException(msg, E_FILE_LINE); - } - if ( sscanf(str.c_str(), "%08x-%04hx-%04hx-%04hx-%08x%04hx", - &part0, &part1, &part2, &part3, &part4, &part5) != 6 ) - { - std::string msg("UUID128 string not in format '00000000-0000-1000-8000-00805F9B34FB' but "+str); - throw IllegalArgumentException(msg, E_FILE_LINE); - } - uint128_t value; - - // sscanf provided host data type, in which we store the values, - // hence no endian conversion -#if __BYTE_ORDER == __BIG_ENDIAN - put_uint32(value.data, 0, part0); - put_uint16(value.data, 4, part1); - put_uint16(value.data, 6, part2); - put_uint16(value.data, 8, part3); - put_uint32(value.data, 10, part4); - put_uint16(value.data, 14, part5); -#elif __BYTE_ORDER == __LITTLE_ENDIAN - put_uint16(value.data, 0, part5); - put_uint32(value.data, 2, part4); - put_uint16(value.data, 6, part3); - put_uint16(value.data, 8, part2); - put_uint16(value.data, 10, part1); - put_uint32(value.data, 12, part0); -#else -#error "Unexpected __BYTE_ORDER" -#endif -} diff --git a/src/tinyb_hci/tinyb_hci.pc.cmake b/src/tinyb_hci/tinyb_hci.pc.cmake deleted file mode 100644 index 8a18a64e..00000000 --- a/src/tinyb_hci/tinyb_hci.pc.cmake +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib@LIB_SUFFIX@ -includedir=${prefix}/include/tinyb_hci - -Name: tinyb_hci -Description: Tiny BLE HCI library -Version: @tinyb_VERSION_STRING@ - -Libs: -L${libdir} -ltinyb -Cflags: -I${includedir} |