aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trial/direct_bt/dbt_client00.hpp705
-rw-r--r--trial/direct_bt/dbt_client01.hpp49
-rw-r--r--trial/direct_bt/dbt_client_server1x.hpp9
-rw-r--r--trial/direct_bt/dbt_server00.hpp774
-rw-r--r--trial/direct_bt/dbt_server01.hpp11
-rw-r--r--trial/direct_bt/test_client_server00.cpp5
-rw-r--r--trial/direct_bt/test_provoke_client_server_i470.cpp5
-rw-r--r--trial/java/trial/org/direct_bt/DBTClient00.java717
-rw-r--r--trial/java/trial/org/direct_bt/DBTClient01.java28
-rw-r--r--trial/java/trial/org/direct_bt/DBTClientServer1x.java4
-rw-r--r--trial/java/trial/org/direct_bt/DBTServer00.java814
-rw-r--r--trial/java/trial/org/direct_bt/TestDBTClientServer00.java2
12 files changed, 77 insertions, 3046 deletions
diff --git a/trial/direct_bt/dbt_client00.hpp b/trial/direct_bt/dbt_client00.hpp
deleted file mode 100644
index 903ed477..00000000
--- a/trial/direct_bt/dbt_client00.hpp
+++ /dev/null
@@ -1,705 +0,0 @@
-/**
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2022 Gothel Software e.K.
- *
- * 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.
- */
-
-#ifndef DBT_CLIENT00_HPP_
-#define DBT_CLIENT00_HPP_
-
-#include "dbt_constants.hpp"
-
-#include "dbt_client_test.hpp"
-
-class DBTClient00;
-typedef std::shared_ptr<DBTClient00> DBTClient00Ref;
-
-using namespace jau;
-using namespace jau::fractions_i64_literals;
-
-/**
- * This central BTRole::Master participant works with DBTServer00.
- */
-class DBTClient00 : public DBTClientTest {
- private:
- bool KEEP_CONNECTED = false;
-
- bool REMOVE_DEVICE = false;
-
- DiscoveryPolicy discoveryPolicy = DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_READY; // default value
-
- static const bool GATT_VERBOSE = false;
- static const bool SHOW_UPDATE_EVENTS = false;
-
- jau::sc_atomic_int deviceReadyCount = 0;
-
- jau::sc_atomic_int disconnectCount = 0;
- jau::sc_atomic_int notificationsReceived = 0;
- jau::sc_atomic_int indicationsReceived = 0;
- jau::sc_atomic_int completedGATTCommands = 0;
- jau::sc_atomic_int completedMeasurementsTotal = 0;
- jau::sc_atomic_int completedMeasurementsSuccess = 0;
- jau::sc_atomic_int measurementsLeft = 0;
-
- const uint64_t timestamp_t0 = getCurrentMilliseconds();
- // const fraction_i64 timestamp_t0 = jau::getMonotonicMicroseconds();
-
- const uint8_t cmd_arg = 0x44;
-
- class MyAdapterStatusListener : public AdapterStatusListener {
- public:
- DBTClient00& parent;
-
- MyAdapterStatusListener(DBTClient00& p) : parent(p) {}
-
- void adapterSettingsChanged(BTAdapter &a, const AdapterSetting oldmask, const AdapterSetting newmask,
- const AdapterSetting changedmask, const uint64_t timestamp) override {
- const bool initialSetting = AdapterSetting::NONE == oldmask;
- if( initialSetting ) {
- fprintf_td(stderr, "****** Client SETTINGS_INITIAL: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
- to_string(newmask).c_str(), to_string(changedmask).c_str());
- } else {
- fprintf_td(stderr, "****** Client SETTINGS_CHANGED: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
- to_string(newmask).c_str(), to_string(changedmask).c_str());
- }
- fprintf_td(stderr, "Client Status BTAdapter:\n");
- fprintf_td(stderr, "%s\n", a.toString().c_str());
- (void)timestamp;
- }
-
- void discoveringChanged(BTAdapter &a, const ScanType currentMeta, const ScanType changedType, const bool changedEnabled, const DiscoveryPolicy policy, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Client DISCOVERING: meta %s, changed[%s, enabled %d, policy %s]: %s\n",
- to_string(currentMeta).c_str(), to_string(changedType).c_str(), changedEnabled, to_string(policy).c_str(), a.toString().c_str());
- (void)timestamp;
- }
-
- bool deviceFound(BTDeviceRef device, const uint64_t timestamp) override {
- (void)timestamp;
- if( !BTDeviceRegistry::isDeviceProcessing( device->getAddressAndType() ) &&
- ( !BTDeviceRegistry::isWaitingForAnyDevice() ||
- ( BTDeviceRegistry::isWaitingForDevice(device->getAddressAndType().address, device->getName()) &&
- ( 0 < parent.measurementsLeft || !BTDeviceRegistry::isDeviceProcessed(device->getAddressAndType()) )
- )
- )
- )
- {
- fprintf_td(stderr, "****** Client FOUND__-0: Connecting %s\n", device->toString(true).c_str());
- {
- const uint64_t td = jau::getCurrentMilliseconds() - parent.timestamp_t0; // adapter-init -> now
- fprintf_td(stderr, "PERF: adapter-init -> FOUND__-0 %" PRIu64 " ms\n", td);
- }
- std::thread dc(&DBTClient00::connectDiscoveredDevice, &parent, device); // @suppress("Invalid arguments")
- dc.detach();
- return true;
- } else {
- fprintf_td(stderr, "****** Client FOUND__-1: NOP %s\n", device->toString(true).c_str());
- return false;
- }
- }
-
- void deviceUpdated(BTDeviceRef device, const EIRDataType updateMask, const uint64_t timestamp) override {
- (void)device;
- (void)updateMask;
- (void)timestamp;
- }
-
- void deviceConnected(BTDeviceRef device, const bool discovered, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Client CONNECTED (discovered %d): %s\n", discovered, device->toString(true).c_str());
- (void)discovered;
- (void)timestamp;
- }
-
- void devicePairingState(BTDeviceRef device, const SMPPairingState state, const PairingMode mode, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Client PAIRING STATE: state %s, mode %s, %s\n",
- to_string(state).c_str(), to_string(mode).c_str(), device->toString().c_str());
- (void)timestamp;
- switch( state ) {
- case SMPPairingState::NONE:
- // next: deviceReady(..)
- break;
- case SMPPairingState::FAILED: {
- const bool res = SMPKeyBin::remove(DBTConstants::CLIENT_KEY_PATH, *device);
- fprintf_td(stderr, "****** PAIRING_STATE: state %s; Remove key file %s, res %d\n",
- to_string(state).c_str(), SMPKeyBin::getFilename(DBTConstants::CLIENT_KEY_PATH, *device).c_str(), res);
- // next: deviceReady() or deviceDisconnected(..)
- } break;
- case SMPPairingState::REQUESTED_BY_RESPONDER:
- // next: FEATURE_EXCHANGE_STARTED
- break;
- case SMPPairingState::FEATURE_EXCHANGE_STARTED:
- // next: FEATURE_EXCHANGE_COMPLETED
- break;
- case SMPPairingState::FEATURE_EXCHANGE_COMPLETED:
- // next: PASSKEY_EXPECTED... or KEY_DISTRIBUTION
- break;
- case SMPPairingState::PASSKEY_EXPECTED: {
- const BTSecurityRegistry::Entry* sec = BTSecurityRegistry::getStartOf(device->getAddressAndType().address, device->getName());
- if( nullptr != sec && sec->getPairingPasskey() != BTSecurityRegistry::Entry::NO_PASSKEY ) {
- std::thread dc(&BTDevice::setPairingPasskey, device, static_cast<uint32_t>( sec->getPairingPasskey() ));
- dc.detach();
- } else {
- std::thread dc(&BTDevice::setPairingPasskey, device, 0);
- // 3s disconnect: std::thread dc(&BTDevice::setPairingPasskeyNegative, device);
- dc.detach();
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case SMPPairingState::NUMERIC_COMPARE_EXPECTED: {
- const BTSecurityRegistry::Entry* sec = BTSecurityRegistry::getStartOf(device->getAddressAndType().address, device->getName());
- if( nullptr != sec ) {
- std::thread dc(&BTDevice::setPairingNumericComparison, device, sec->getPairingNumericComparison());
- dc.detach();
- } else {
- std::thread dc(&BTDevice::setPairingNumericComparison, device, false);
- dc.detach();
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case SMPPairingState::OOB_EXPECTED:
- // FIXME: ABORT
- break;
- case SMPPairingState::KEY_DISTRIBUTION:
- // next: COMPLETED or FAILED
- break;
- case SMPPairingState::COMPLETED:
- // next: deviceReady(..)
- break;
- default: // nop
- break;
- }
- }
-
- void deviceReady(BTDeviceRef device, const uint64_t timestamp) override {
- (void)timestamp;
- if( !BTDeviceRegistry::isDeviceProcessing( device->getAddressAndType() ) &&
- ( !BTDeviceRegistry::isWaitingForAnyDevice() ||
- ( BTDeviceRegistry::isWaitingForDevice(device->getAddressAndType().address, device->getName()) &&
- ( 0 < parent.measurementsLeft || !BTDeviceRegistry::isDeviceProcessed(device->getAddressAndType()) )
- )
- )
- )
- {
- parent.deviceReadyCount++;
- fprintf_td(stderr, "****** Client READY-0: Processing[%d] %s\n", parent.deviceReadyCount.load(), device->toString(true).c_str());
- BTDeviceRegistry::addToProcessingDevices(device->getAddressAndType(), device->getName());
-
- // Be nice to Test* case, allowing to reach its own listener.deviceReady() added later
- std::thread dc(&DBTClient00::processReadyDevice, &parent, device);
- dc.detach();
- // processReadyDevice(device); // AdapterStatusListener::deviceReady() explicitly allows prolonged and complex code execution!
- } else {
- fprintf_td(stderr, "****** Client READY-1: NOP %s\n", device->toString(true).c_str());
- }
- }
-
- void deviceDisconnected(BTDeviceRef device, const HCIStatusCode reason, const uint16_t handle, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Client DISCONNECTED: Reason 0x%X (%s), old handle %s: %s\n",
- static_cast<uint8_t>(reason), to_string(reason).c_str(),
- to_hexstring(handle).c_str(), device->toString(true).c_str());
- (void)timestamp;
-
- parent.disconnectCount++;
-
- std::thread dc(&DBTClient00::removeDevice, &parent, device); // @suppress("Invalid arguments")
- dc.detach();
- }
-
- std::string toString() const noexcept override {
- return "Client MyAdapterStatusListener[this "+to_hexstring(this)+"]";
- }
-
- };
-
- class MyGATTEventListener : public BTGattCharListener {
- private:
- DBTClient00& parent;
-
- public:
- MyGATTEventListener(DBTClient00& p) : parent(p) {}
-
- void notificationReceived(BTGattCharRef charDecl, const TROOctets& char_value, const uint64_t timestamp) override {
- if( GATT_VERBOSE ) {
- const uint64_t tR = jau::getCurrentMilliseconds();
- fprintf_td(stderr, "** Characteristic-Notify: UUID %s, td %" PRIu64 " ******\n",
- charDecl->value_type->toUUID128String().c_str(), (tR-timestamp));
- fprintf_td(stderr, "** Characteristic: %s ******\n", charDecl->toString().c_str());
- fprintf_td(stderr, "** Value R: %s ******\n", char_value.toString().c_str());
- fprintf_td(stderr, "** Value S: %s ******\n", jau::dfa_utf8_decode(char_value.get_ptr(), char_value.size()).c_str());
- }
- parent.notificationsReceived++;
- }
-
- void indicationReceived(BTGattCharRef charDecl,
- const TROOctets& char_value, const uint64_t timestamp,
- const bool confirmationSent) override
- {
- if( GATT_VERBOSE ) {
- const uint64_t tR = jau::getCurrentMilliseconds();
- fprintf_td(stderr, "** Characteristic-Indication: UUID %s, td %" PRIu64 ", confirmed %d ******\n",
- charDecl->value_type->toUUID128String().c_str(), (tR-timestamp), confirmationSent);
- fprintf_td(stderr, "** Characteristic: %s ******\n", charDecl->toString().c_str());
- fprintf_td(stderr, "** Value R: %s ******\n", char_value.toString().c_str());
- fprintf_td(stderr, "** Value S: %s ******\n", jau::dfa_utf8_decode(char_value.get_ptr(), char_value.size()).c_str());
- }
- parent.indicationsReceived++;
- }
- };
-
- const std::string adapterShortName = "TDev2Clt";
- std::string adapterName = "TestDev2_Clt";
- EUI48 useAdapter = EUI48::ALL_DEVICE;
- BTMode btMode = BTMode::DUAL;
- BTAdapterRef clientAdapter = nullptr;
- std::shared_ptr<AdapterStatusListener> myAdapterStatusListener = std::make_shared<MyAdapterStatusListener>(*this);
-
- public:
- DBTClient00(const std::string& adapterName_, const EUI48 useAdapter_, const BTMode btMode_) {
- this->adapterName = adapterName_;
- this->useAdapter = useAdapter_;
- this->btMode = btMode_;
- }
-
- std::string getName() override { return adapterName; }
-
- void setAdapter(BTAdapterRef clientAdapter_) override {
- this->clientAdapter = clientAdapter_;
- }
-
- BTAdapterRef getAdapter() override { return clientAdapter; }
-
- void setProtocolSessionsLeft(const int v) override {
- measurementsLeft = v;
- }
- int getProtocolSessionsLeft() override {
- return measurementsLeft;
- }
- int getProtocolSessionsDoneTotal() override {
- return completedMeasurementsTotal;
- }
- int getProtocolSessionsDoneSuccess() override {
- return completedMeasurementsSuccess;
- }
- int getDisconnectCount() override {
- return disconnectCount;
- }
-
- void setDiscoveryPolicy(const DiscoveryPolicy v) override {
- discoveryPolicy = v;
- }
- void setKeepConnected(const bool v) override {
- KEEP_CONNECTED = v;
- }
- void setRemoveDevice(const bool v) override {
- REMOVE_DEVICE = v;
- }
-
- private:
- void resetLastProcessingStats() {
- completedGATTCommands = 0;
- notificationsReceived = 0;
- indicationsReceived = 0;
- }
-
- void connectDiscoveredDevice(BTDeviceRef device) {
- fprintf_td(stderr, "****** Client Connecting Device: Start %s\n", device->toString().c_str());
-
- resetLastProcessingStats();
-
- const BTSecurityRegistry::Entry* sec = BTSecurityRegistry::getStartOf(device->getAddressAndType().address, device->getName());
- if( nullptr != sec ) {
- fprintf_td(stderr, "****** Client Connecting Device: Found SecurityDetail %s for %s\n", sec->toString().c_str(), device->toString().c_str());
- } else {
- fprintf_td(stderr, "****** Client Connecting Device: No SecurityDetail for %s\n", device->toString().c_str());
- }
- const BTSecurityLevel req_sec_level = nullptr != sec ? sec->getSecLevel() : BTSecurityLevel::UNSET;
- HCIStatusCode res = device->uploadKeys(DBTConstants::CLIENT_KEY_PATH, req_sec_level, true /* verbose_ */);
- fprintf_td(stderr, "****** Client Connecting Device: BTDevice::uploadKeys(...) result %s\n", to_string(res).c_str());
- if( HCIStatusCode::SUCCESS != res ) {
- if( nullptr != sec ) {
- if( sec->isSecurityAutoEnabled() ) {
- bool r = device->setConnSecurityAuto( sec->getSecurityAutoIOCap() );
- fprintf_td(stderr, "****** Client Connecting Device: Using SecurityDetail.SEC AUTO %s, set OK %d\n", sec->toString().c_str(), r);
- } else if( sec->isSecLevelOrIOCapSet() ) {
- bool r = device->setConnSecurity( sec->getSecLevel(), sec->getIOCap() );
- fprintf_td(stderr, "****** Client Connecting Device: Using SecurityDetail.Level+IOCap %s, set OK %d\n", sec->toString().c_str(), r);
- } else {
- bool r = device->setConnSecurityAuto( SMPIOCapability::KEYBOARD_ONLY );
- fprintf_td(stderr, "****** Client Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY (%s) -> set OK %d\n", sec->toString().c_str(), r);
- }
- } else {
- bool r = device->setConnSecurityAuto( SMPIOCapability::KEYBOARD_ONLY );
- fprintf_td(stderr, "****** Client Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY -> set OK %d\n", r);
- }
- }
- std::shared_ptr<const EInfoReport> eir = device->getEIR();
- fprintf_td(stderr, "Client EIR-1 %s\n", device->getEIRInd()->toString().c_str());
- fprintf_td(stderr, "Client EIR-2 %s\n", device->getEIRScanRsp()->toString().c_str());
- fprintf_td(stderr, "Client EIR-+ %s\n", eir->toString().c_str());
-
- uint16_t conn_interval_min = (uint16_t)8; // 10ms
- uint16_t conn_interval_max = (uint16_t)12; // 15ms
- const uint16_t conn_latency = (uint16_t)0;
- if( eir->isSet(EIRDataType::CONN_IVAL) ) {
- eir->getConnInterval(conn_interval_min, conn_interval_max);
- }
- const uint16_t supervision_timeout = (uint16_t) getHCIConnSupervisorTimeout(conn_latency, (int) ( conn_interval_max * 1.25 ) /* ms */);
- res = device->connectLE(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, supervision_timeout);
- fprintf_td(stderr, "****** Client Connecting Device: End result %s of %s\n", to_string(res).c_str(), device->toString().c_str());
- }
-
- void processReadyDevice(BTDeviceRef device) {
- fprintf_td(stderr, "****** Client Processing Ready Device: Start %s\n", device->toString().c_str());
-
- const uint64_t t1 = jau::getCurrentMilliseconds();
-
- SMPKeyBin::createAndWrite(*device, DBTConstants::CLIENT_KEY_PATH, true /* verbose */);
-
- const uint64_t t2 = jau::getCurrentMilliseconds();
-
- bool success = false;
-
- {
- LE_PHYs resTx, resRx;
- HCIStatusCode res = device->getConnectedLE_PHY(resTx, resRx);
- fprintf_td(stderr, "****** Client Got Connected LE PHY: status %s: Tx %s, Rx %s\n",
- to_string(res).c_str(), to_string(resTx).c_str(), to_string(resRx).c_str());
- }
-
- const uint64_t t3 = jau::getCurrentMilliseconds();
-
- //
- // GATT Service Processing
- //
- try {
- jau::darray<BTGattServiceRef> primServices = device->getGattServices();
- if( 0 == primServices.size() ) {
- fprintf_td(stderr, "****** Clinet Processing Ready Device: getServices() failed %s\n", device->toString().c_str());
- goto exit;
- }
-
- const uint64_t t5 = jau::getCurrentMilliseconds();
- {
- const uint64_t td00 = device->getLastDiscoveryTimestamp() - timestamp_t0; // adapter-init to discovered
- const uint64_t td01 = t1 - timestamp_t0; // adapter-init to processing-start
- const uint64_t td05 = t5 - timestamp_t0; // adapter-init -> gatt-complete
- const uint64_t tdc1 = t1 - device->getLastDiscoveryTimestamp(); // discovered to processing-start
- const uint64_t tdc5 = t5 - device->getLastDiscoveryTimestamp(); // discovered to gatt-complete
- const uint64_t td12 = t2 - t1; // SMPKeyBin
- const uint64_t td23 = t3 - t2; // LE_PHY
- const uint64_t td13 = t3 - t1; // SMPKeyBin + LE_PHY
- const uint64_t td35 = t5 - t3; // get-gatt-services
- fprintf_td(stderr, "\n\n\n");
- fprintf_td(stderr, "PERF: GATT primary-services completed\n"
- "PERF: adapter-init to discovered %" PRIu64 " ms,\n"
- "PERF: adapter-init to processing-start %" PRIu64 " ms,\n"
- "PERF: adapter-init to gatt-complete %" PRIu64 " ms\n"
- "PERF: discovered to processing-start %" PRIu64 " ms,\n"
- "PERF: discovered to gatt-complete %" PRIu64 " ms,\n"
- "PERF: SMPKeyBin + LE_PHY %" PRIu64 " ms (SMPKeyBin %" PRIu64 " ms, LE_PHY %" PRIu64 " ms),\n"
- "PERF: get-gatt-services %" PRIu64 " ms,\n\n",
- td00, td01, td05,
- tdc1, tdc5,
- td13, td12, td23, td35);
- }
-
- {
- BTGattCmd cmd = BTGattCmd(*device, "TestCmd", DBTConstants::CommandUUID, DBTConstants::ResponseUUID, 256);
- cmd.setVerbose(true);
- const bool cmd_resolved = cmd.isResolved();
- fprintf_td(stderr, "Command test: %s, resolved %d\n", cmd.toString().c_str(), cmd_resolved);
- POctets cmd_data(1, endian::little);
- cmd_data.put_uint8_nc(0, cmd_arg);
- const HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3_s);
- if( HCIStatusCode::SUCCESS == cmd_res ) {
- const jau::TROOctets& resp = cmd.getResponse();
- if( 1 == resp.size() && resp.get_uint8_nc(0) == cmd_arg ) {
- fprintf_td(stderr, "Client Success: %s -> %s (echo response)\n", cmd.toString().c_str(), resp.toString().c_str());
- completedGATTCommands++;
- } else {
- fprintf_td(stderr, "Client Failure: %s -> %s (different response)\n", cmd.toString().c_str(), resp.toString().c_str());
- }
- } else {
- fprintf_td(stderr, "Client Failure: %s -> %s\n", cmd.toString().c_str(), to_string(cmd_res).c_str());
- }
- // cmd.close(); // done via dtor
- }
-
- bool gattListenerError = false;
- std::vector<BTGattCharListenerRef> gattListener;
- int loop = 0;
- do {
- for(size_t i=0; i<primServices.size(); i++) {
- BTGattService & primService = *primServices.at(i);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, " [%2.2d] Service UUID %s (%s)\n", i,
- primService.type->toUUID128String().c_str(),
- primService.type->getTypeSizeString().c_str());
- fprintf_td(stderr, " [%2.2d] %s\n", i, primService.toString().c_str());
- }
- jau::darray<BTGattCharRef> & serviceCharacteristics = primService.characteristicList;
- for(size_t j=0; j<serviceCharacteristics.size(); j++) {
- BTGattCharRef & serviceChar = serviceCharacteristics.at(j);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic: UUID %s (%s)\n", i, j,
- serviceChar->value_type->toUUID128String().c_str(),
- serviceChar->value_type->getTypeSizeString().c_str());
- fprintf_td(stderr, " [%2.2d.%2.2d] %s\n", i, j, serviceChar->toString().c_str());
- }
- if( serviceChar->hasProperties(BTGattChar::PropertyBitVal::Read) ) {
- POctets value(BTGattHandler::number(BTGattHandler::Defaults::MAX_ATT_MTU), 0, jau::endian::little);
- if( serviceChar->readValue(value) ) {
- std::string sval = dfa_utf8_decode(value.get_ptr(), value.size());
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, " [%2.2d.%2.2d] value: %s ('%s')\n", (int)i, (int)j, value.toString().c_str(), sval.c_str());
- }
- }
- }
- jau::darray<BTGattDescRef> & charDescList = serviceChar->descriptorList;
- for(size_t k=0; k<charDescList.size(); k++) {
- BTGattDesc & charDesc = *charDescList.at(k);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] Descriptor: UUID %s (%s)\n", i, j, k,
- charDesc.type->toUUID128String().c_str(),
- charDesc.type->getTypeSizeString().c_str());
- fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] %s\n", i, j, k, charDesc.toString().c_str());
- }
- }
- if( 0 == loop ) {
- bool cccdEnableResult[2];
- if( serviceChar->enableNotificationOrIndication( cccdEnableResult ) ) {
- // ClientCharConfigDescriptor (CCD) is available
- std::shared_ptr<BTGattCharListener> gattEventListener = std::make_shared<MyGATTEventListener>(*this);
- bool clAdded = serviceChar->addCharListener( gattEventListener );
- if( clAdded ) {
- gattListener.push_back(gattEventListener);
- } else {
- gattListenerError = true;
- fprintf_td(stderr, "Client Error: Failed to add GattListener: %s @ %s, gattListener %zu\n",
- gattEventListener->toString().c_str(), serviceChar->toString().c_str(), gattListener.size());
- }
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic-Listener: Notification(%d), Indication(%d): Added %d\n",
- (int)i, (int)j, cccdEnableResult[0], cccdEnableResult[1], clAdded);
- fprintf_td(stderr, "\n");
- }
- }
- }
- }
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "\n");
- }
- }
- success = notificationsReceived >= 2 || indicationsReceived >= 2;
- ++loop;
- } while( !success && device->getConnected() && !gattListenerError );
-
- if( gattListenerError ) {
- success = false;
- }
- {
- int i = 0;
- for(BTGattCharListenerRef gcl : gattListener) {
- if( !device->removeCharListener(gcl) ) {
- fprintf_td(stderr, "Client: Failed to remove GattListener[%d/%zu]: %s @ %s\n",
- i, gattListener.size(), gcl->toString().c_str(), device->toString().c_str());
- success = false;
- }
- ++i;
- }
- }
-
- if( device->getConnected() ) {
- // Tell server we have successfully completed the test.
- BTGattCmd cmd = BTGattCmd(*device, "FinalHandshake", DBTConstants::CommandUUID, DBTConstants::ResponseUUID, 256);
- cmd.setVerbose(true);
- const bool cmd_resolved = cmd.isResolved();
- fprintf_td(stderr, "FinalCommand test: %s, resolved %d\n", cmd.toString().c_str(), cmd_resolved);
- const int data_sz = DBTConstants::FailHandshakeCommandData.size();
- POctets cmd_data(data_sz, endian::little);
- if( success ) {
- cmd_data.put_bytes_nc(0, DBTConstants::SuccessHandshakeCommandData.data(), data_sz);
- } else {
- cmd_data.put_bytes_nc(0, DBTConstants::FailHandshakeCommandData.data(), data_sz);
- }
- const HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3_s);
- if( HCIStatusCode::SUCCESS == cmd_res ) {
- const jau::TROOctets& resp = cmd.getResponse();
-
- if( cmd_data.size() == resp.size() &&
- 0 == ::memcmp(cmd_data.get_ptr(), resp.get_ptr(), resp.size()) )
- {
- fprintf_td(stderr, "Client Success: %s -> %s (echo response)\n", cmd.toString().c_str(), resp.toString().c_str());
- } else {
- fprintf_td(stderr, "Client Failure: %s -> %s (different response)\n", cmd.toString().c_str(), resp.toString().c_str());
- }
- } else {
- fprintf_td(stderr, "Client Failure: %s -> %s\n", cmd.toString().c_str(), to_string(cmd_res).c_str());
- }
- // cmd.close(); // done via dtor
- }
- } catch ( std::exception & e ) {
- fprintf_td(stderr, "****** Client Processing Ready Device: Exception.2 caught for %s: %s\n", device->toString().c_str(), e.what());
- }
-
- exit:
- fprintf_td(stderr, "****** Client Processing Ready Device: End-1: Success %d on %s; devInProc %zu\n",
- success, device->toString().c_str(), BTDeviceRegistry::getProcessingDeviceCount());
-
- BTDeviceRegistry::removeFromProcessingDevices(device->getAddressAndType());
-
- if( DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_DISCONNECTED == discoveryPolicy ) {
- device->getAdapter().removeDevicePausingDiscovery(*device);
- }
-
- fprintf_td(stderr, "****** Client Processing Ready Device: End-2: Success %d on %s; devInProc %zu\n",
- success, device->toString().c_str(), BTDeviceRegistry::getProcessingDeviceCount());
-
- if( success ) {
- BTDeviceRegistry::addToProcessedDevices(device->getAddressAndType(), device->getName());
- }
- device->removeAllCharListener();
-
- if( !KEEP_CONNECTED ) {
- if( REMOVE_DEVICE ) {
- device->remove();
- } else {
- device->disconnect();
- }
- }
-
- completedMeasurementsTotal++;
- if( success ) {
- completedMeasurementsSuccess++;
- }
- if( 0 < measurementsLeft ) {
- measurementsLeft--;
- }
- fprintf_td(stderr, "****** Client Processing Ready Device: Success %d; Measurements completed %d"
- ", left %d; Received notitifications %d, indications %d"
- "; Completed GATT commands %d: %s\n",
- success, completedMeasurementsSuccess.load(),
- measurementsLeft.load(), notificationsReceived.load(), indicationsReceived.load(),
- completedGATTCommands.load(), device->getAddressAndType().toString().c_str());
- }
-
- void removeDevice(BTDeviceRef device) {
- fprintf_td(stderr, "****** Client Remove Device: removing: %s\n", device->getAddressAndType().toString().c_str());
-
- BTDeviceRegistry::removeFromProcessingDevices(device->getAddressAndType());
-
- if( REMOVE_DEVICE ) {
- device->remove();
- }
- }
-
- static const bool le_scan_active = true; // default value
- static const uint16_t le_scan_interval = 24; // default value
- static const uint16_t le_scan_window = 24; // default value
- static const uint8_t filter_policy = 0; // default value
- static const bool filter_dup = true; // default value
-
- public:
-
- HCIStatusCode startDiscovery(const std::string& msg) override {
- HCIStatusCode status = clientAdapter->startDiscovery( discoveryPolicy, le_scan_active, le_scan_interval, le_scan_window, filter_policy, filter_dup );
- fprintf_td(stderr, "****** Client Start discovery (%s) result: %s: %s\n", msg.c_str(), to_string(status).c_str(), clientAdapter->toString().c_str());
- return status;
- }
-
- HCIStatusCode stopDiscovery(const std::string& msg) override {
- HCIStatusCode status = clientAdapter->stopDiscovery();
- fprintf_td(stderr, "****** Client Stop discovery (%s) result: %s\n", msg.c_str(), to_string(status).c_str());
- return status;
- }
-
- void close(const std::string& msg) override {
- fprintf_td(stderr, "****** Client Close: %s\n", msg.c_str());
- clientAdapter->stopDiscovery();
- clientAdapter->removeStatusListener( myAdapterStatusListener );
- }
-
- bool initAdapter(BTAdapterRef adapter) override {
- if( useAdapter != EUI48::ALL_DEVICE && useAdapter != adapter->getAddressAndType().address ) {
- fprintf_td(stderr, "initClientAdapter: Adapter not selected: %s\n", adapter->toString().c_str());
- return false;
- }
- adapterName = adapterName + "-" + adapter->getAddressAndType().address.toString();
- {
- auto it = std::remove( adapterName.begin(), adapterName.end(), ':');
- adapterName.erase(it, adapterName.end());
- }
-
- // Initialize with defaults and power-on
- if( !adapter->isInitialized() ) {
- HCIStatusCode status = adapter->initialize( btMode );
- if( HCIStatusCode::SUCCESS != status ) {
- fprintf_td(stderr, "initClientAdapter: Adapter initialization failed: %s: %s\n",
- to_string(status).c_str(), adapter->toString().c_str());
- return false;
- }
- } else if( !adapter->setPowered( true ) ) {
- fprintf_td(stderr, "initClientAdapter: Already initialized adapter power-on failed:: %s\n", adapter->toString().c_str());
- return false;
- }
- // adapter is powered-on
- fprintf_td(stderr, "initClientAdapter.1: %s\n", adapter->toString().c_str());
- {
- const LE_Features le_feats = adapter->getLEFeatures();
- fprintf_td(stderr, "initClientAdapter: LE_Features %s\n", to_string(le_feats).c_str());
- }
-
- if( adapter->setPowered(false) ) {
- HCIStatusCode status = adapter->setName(adapterName, adapterShortName);
- if( HCIStatusCode::SUCCESS == status ) {
- fprintf_td(stderr, "initClientAdapter: setLocalName OK: %s\n", adapter->toString().c_str());
- } else {
- fprintf_td(stderr, "initClientAdapter: setLocalName failed: %s\n", adapter->toString().c_str());
- return false;
- }
-
- if( !adapter->setPowered( true ) ) {
- fprintf_td(stderr, "initClientAdapter: setPower.2 on failed: %s\n", adapter->toString().c_str());
- return false;
- }
- } else {
- fprintf_td(stderr, "initClientAdapter: setPowered.2 off failed: %s\n", adapter->toString().c_str());
- return false;
- }
- // adapter is powered-on
- fprintf_td(stderr, "initClientAdapter.2: %s\n", adapter->toString().c_str());
-
- {
- const LE_Features le_feats = adapter->getLEFeatures();
- fprintf_td(stderr, "initClientAdapter: LE_Features %s\n", to_string(le_feats).c_str());
- }
- if( adapter->getBTMajorVersion() > 4 ) {
- LE_PHYs Tx { LE_PHYs::LE_2M }, Rx { LE_PHYs::LE_2M };
- HCIStatusCode res = adapter->setDefaultLE_PHY(Tx, Rx);
- fprintf_td(stderr, "initClientAdapter: Set Default LE PHY: status %s: Tx %s, Rx %s\n",
- to_string(res).c_str(), to_string(Tx).c_str(), to_string(Rx).c_str());
- }
- adapter->addStatusListener( myAdapterStatusListener );
-
- return true;
- }
-};
-
-#endif /* DBT_CLIENT00_HPP_ */
diff --git a/trial/direct_bt/dbt_client01.hpp b/trial/direct_bt/dbt_client01.hpp
index faf128e1..9d6dcdce 100644
--- a/trial/direct_bt/dbt_client01.hpp
+++ b/trial/direct_bt/dbt_client01.hpp
@@ -39,22 +39,9 @@ using namespace jau::fractions_i64_literals;
* This central BTRole::Master participant works with DBTServer00.
*/
class DBTClient01 : public DBTClientTest {
- public:
- /**
- * Disconnect after processing.
- *
- * Default is `false`.
- */
+ private:
bool KEEP_CONNECTED = false;
- /**
- * Remove device when disconnecting.
- *
- * This removes the device from all instances within adapter
- * and hence all potential side-effects of the current instance.
- *
- * Default is `false`, since it is good to test whether such side-effects exists.
- */
bool REMOVE_DEVICE = false;
DiscoveryPolicy discoveryPolicy = DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_READY; // default value
@@ -67,16 +54,18 @@ class DBTClient01 : public DBTClientTest {
jau::sc_atomic_int disconnectCount = 0;
jau::sc_atomic_int notificationsReceived = 0;
jau::sc_atomic_int indicationsReceived = 0;
+ jau::sc_atomic_int completedGATTCommands = 0;
jau::sc_atomic_int completedMeasurementsTotal = 0;
jau::sc_atomic_int completedMeasurementsSuccess = 0;
jau::sc_atomic_int measurementsLeft = 0;
bool do_disconnect = false;
- private:
const uint64_t timestamp_t0 = getCurrentMilliseconds();
// const fraction_i64 timestamp_t0 = jau::getMonotonicMicroseconds();
+ const uint8_t cmd_arg = 0x44;
+
class MyAdapterStatusListener : public AdapterStatusListener {
public:
DBTClient01& parent;
@@ -335,6 +324,7 @@ class DBTClient01 : public DBTClientTest {
private:
void resetLastProcessingStats() {
+ completedGATTCommands = 0;
notificationsReceived = 0;
indicationsReceived = 0;
}
@@ -441,6 +431,28 @@ class DBTClient01 : public DBTClientTest {
td13, td12, td23, td35);
}
+ {
+ BTGattCmd cmd = BTGattCmd(*device, "TestCmd", DBTConstants::CommandUUID, DBTConstants::ResponseUUID, 256);
+ cmd.setVerbose(true);
+ const bool cmd_resolved = cmd.isResolved();
+ fprintf_td(stderr, "Command test: %s, resolved %d\n", cmd.toString().c_str(), cmd_resolved);
+ POctets cmd_data(1, endian::little);
+ cmd_data.put_uint8_nc(0, cmd_arg);
+ const HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3_s);
+ if( HCIStatusCode::SUCCESS == cmd_res ) {
+ const jau::TROOctets& resp = cmd.getResponse();
+ if( 1 == resp.size() && resp.get_uint8_nc(0) == cmd_arg ) {
+ fprintf_td(stderr, "Client Success: %s -> %s (echo response)\n", cmd.toString().c_str(), resp.toString().c_str());
+ completedGATTCommands++;
+ } else {
+ fprintf_td(stderr, "Client Failure: %s -> %s (different response)\n", cmd.toString().c_str(), resp.toString().c_str());
+ }
+ } else {
+ fprintf_td(stderr, "Client Failure: %s -> %s\n", cmd.toString().c_str(), to_string(cmd_res).c_str());
+ }
+ // cmd.close(); // done via dtor
+ }
+
bool gattListenerError = false;
std::vector<BTGattCharListenerRef> gattListener;
int loop = 0;
@@ -510,6 +522,8 @@ class DBTClient01 : public DBTClientTest {
++loop;
} while( !success && device->getConnected() && !gattListenerError );
+ success = success && completedGATTCommands >= 1;
+
if( gattListenerError ) {
success = false;
}
@@ -587,10 +601,11 @@ class DBTClient01 : public DBTClientTest {
}
}
fprintf_td(stderr, "****** Client Processing Ready Device: Success %d; Measurements completed %d"
- ", left %d; Received notitifications %d, indications %d: %s\n",
+ ", left %d; Received notitifications %d, indications %d"
+ "; Completed GATT commands %d: %s\n",
success, completedMeasurementsSuccess.load(),
measurementsLeft.load(), notificationsReceived.load(), indicationsReceived.load(),
- device->getAddressAndType().toString().c_str());
+ completedGATTCommands.load(), device->getAddressAndType().toString().c_str());
}
void removeDevice(BTDeviceRef device) {
diff --git a/trial/direct_bt/dbt_client_server1x.hpp b/trial/direct_bt/dbt_client_server1x.hpp
index dbaa620e..faee48a8 100644
--- a/trial/direct_bt/dbt_client_server1x.hpp
+++ b/trial/direct_bt/dbt_client_server1x.hpp
@@ -29,8 +29,8 @@
#include "dbt_base_client_server.hpp"
-#include "dbt_server00.hpp"
-#include "dbt_client00.hpp"
+#include "dbt_server01.hpp"
+#include "dbt_client01.hpp"
using namespace direct_bt;
@@ -63,8 +63,9 @@ class DBTClientServer1x {
const bool serverSC, const BTSecurityLevel secLevelServer, const ExpectedPairing serverExpPairing,
const BTSecurityLevel secLevelClient, const ExpectedPairing clientExpPairing)
{
- std::shared_ptr<DBTServer00> server = std::make_shared<DBTServer00>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer);
- std::shared_ptr<DBTClient00> client = std::make_shared<DBTClient00>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL);
+ std::shared_ptr<DBTServer01> server = std::make_shared<DBTServer01>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL,
+ serverSC, secLevelServer, false /* do_disconnect_ */);
+ std::shared_ptr<DBTClient01> client = std::make_shared<DBTClient01>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, false /* do_disconnect_ */);
test8x_fullCycle(suffix,
protocolSessionCount, DBTConstants::max_connections_per_session, true /* expSuccess */,
server_client_order,
diff --git a/trial/direct_bt/dbt_server00.hpp b/trial/direct_bt/dbt_server00.hpp
deleted file mode 100644
index 27231d8c..00000000
--- a/trial/direct_bt/dbt_server00.hpp
+++ /dev/null
@@ -1,774 +0,0 @@
-/**
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2022 Gothel Software e.K.
- *
- * 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.
- */
-
-#ifndef DBT_SERVER00_HPP_
-#define DBT_SERVER00_HPP_
-
-#include "dbt_constants.hpp"
-
-#include "dbt_server_test.hpp"
-
-class DBTServer00;
-typedef std::shared_ptr<DBTServer00> DBTServer00Ref;
-
-using namespace jau;
-
-/**
- * This peripheral BTRole::Slave test participant works with DBTClient00.
- */
-class DBTServer00 : public DBTServerTest {
- private:
- static jau::POctets make_poctets(const char* name) {
- return jau::POctets( (const uint8_t*)name, (nsize_t)strlen(name), endian::little );
- }
- static jau::POctets make_poctets(const char* name, const jau::nsize_t capacity) {
- const nsize_t name_len = (nsize_t)strlen(name);
- jau::POctets p( std::max<nsize_t>(capacity, name_len), name_len, endian::little );
- p.bzero();
- p.put_bytes_nc(0, reinterpret_cast<const uint8_t*>(name), name_len);
- return p;
- }
- static jau::POctets make_poctets(const uint16_t v) {
- jau::POctets p(2, endian::little);
- p.put_uint16_nc(0, v);
- return p;
- }
- static jau::POctets make_poctets(const jau::nsize_t capacity, const jau::nsize_t size) {
- jau::POctets p(capacity, size, endian::little);
- p.bzero();
- return p;
- }
-
- static const bool GATT_VERBOSE = false;
- static const bool SHOW_UPDATE_EVENTS = false;
-
- const std::string adapterShortName = "TDev1Srv";
- std::string adapterName = "TestDev1_Srv";
- jau::EUI48 useAdapter = jau::EUI48::ALL_DEVICE;
- BTMode btMode = BTMode::DUAL;
- bool use_SC = true;
- BTSecurityLevel adapterSecurityLevel = BTSecurityLevel::UNSET;
-
- jau::sc_atomic_int disconnectCount = 0;
- jau::sc_atomic_int servedProtocolSessionsTotal = 0;
- jau::sc_atomic_int servedProtocolSessionsSuccess = 0;
- jau::sc_atomic_int servingProtocolSessionsLeft = 1;
-
- DBGattServerRef dbGattServer = std::make_shared<DBGattServer>(
- /* services: */
- jau::make_darray( // DBGattService
- std::make_shared<DBGattService> ( true /* primary */,
- std::make_unique<const jau::uuid16_t>(GattServiceType::GENERIC_ACCESS) /* type_ */,
- jau::make_darray ( // DBGattChar
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::DEVICE_NAME) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets(adapterName.c_str(), 128) /* value */, true /* variable_length */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::APPEARANCE) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets((uint16_t)0) /* value */ )
- ) ),
- std::make_shared<DBGattService> ( true /* primary */,
- std::make_unique<const jau::uuid16_t>(GattServiceType::DEVICE_INFORMATION) /* type_ */,
- jau::make_darray ( // DBGattChar
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::MANUFACTURER_NAME_STRING) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets("Gothel Software") /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::MODEL_NUMBER_STRING) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets("2.4.0-pre") /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::SERIAL_NUMBER_STRING) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets("sn:0123456789") /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::HARDWARE_REVISION_STRING) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets("hw:0123456789") /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::FIRMWARE_REVISION_STRING) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets("fw:0123456789") /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid16_t>(GattCharacteristicType::SOFTWARE_REVISION_STRING) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::darray<DBGattDescRef>() /* intentionally empty */,
- make_poctets("sw:0123456789") /* value */ )
- ) ),
- std::make_shared<DBGattService> ( true /* primary */,
- std::make_unique<const jau::uuid128_t>(DBTConstants::DataServiceUUID) /* type_ */,
- jau::make_darray ( // DBGattChar
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid128_t>(DBTConstants::StaticDataUUID) /* value_type_ */,
- BTGattChar::PropertyBitVal::Read,
- jau::make_darray ( // DBGattDesc
- std::make_shared<DBGattDesc>( BTGattDesc::TYPE_USER_DESC, make_poctets("DATA_STATIC") )
- ),
- make_poctets("Proprietary Static Data 0x00010203") /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid128_t>(DBTConstants::CommandUUID) /* value_type_ */,
- BTGattChar::PropertyBitVal::WriteNoAck | BTGattChar::PropertyBitVal::WriteWithAck,
- jau::make_darray ( // DBGattDesc
- std::make_shared<DBGattDesc>( BTGattDesc::TYPE_USER_DESC, make_poctets("COMMAND") )
- ),
- make_poctets(128, 64) /* value */, true /* variable_length */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid128_t>(DBTConstants::ResponseUUID) /* value_type_ */,
- BTGattChar::PropertyBitVal::Notify | BTGattChar::PropertyBitVal::Indicate,
- jau::make_darray ( // DBGattDesc
- std::make_shared<DBGattDesc>( BTGattDesc::TYPE_USER_DESC, make_poctets("RESPONSE") ),
- DBGattDesc::createClientCharConfig()
- ),
- make_poctets((uint16_t)0) /* value */ ),
- std::make_shared<DBGattChar>( std::make_unique<const jau::uuid128_t>(DBTConstants::PulseDataUUID) /* value_type_ */,
- BTGattChar::PropertyBitVal::Notify | BTGattChar::PropertyBitVal::Indicate,
- jau::make_darray ( // DBGattDesc
- std::make_shared<DBGattDesc>( BTGattDesc::TYPE_USER_DESC, make_poctets("DATA_PULSE") ),
- DBGattDesc::createClientCharConfig()
- ),
- make_poctets("Synthethic Sensor 01") /* value */ )
- ) )
- ) );
-
-
- std::mutex mtx_sync;
- BTDeviceRef connectedDevice;
-
- void setDevice(BTDeviceRef cd) {
- const std::lock_guard<std::mutex> lock(mtx_sync); // RAII-style acquire and relinquish via destructor
- connectedDevice = cd;
- }
-
- BTDeviceRef getDevice() {
- const std::lock_guard<std::mutex> lock(mtx_sync); // RAII-style acquire and relinquish via destructor
- return connectedDevice;
- }
-
- bool matches(const BTDeviceRef& device) {
- const BTDeviceRef d = getDevice();
- return nullptr != d ? (*d) == *device : false;
- }
-
- class MyAdapterStatusListener : public AdapterStatusListener {
- public:
- DBTServer00& parent;
-
- MyAdapterStatusListener(DBTServer00& p) : parent(p) {}
-
- void adapterSettingsChanged(BTAdapter &a, const AdapterSetting oldmask, const AdapterSetting newmask,
- const AdapterSetting changedmask, const uint64_t timestamp) override {
- const bool initialSetting = AdapterSetting::NONE == oldmask;
- if( initialSetting ) {
- fprintf_td(stderr, "****** Server SETTINGS_INITIAL: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
- to_string(newmask).c_str(), to_string(changedmask).c_str());
- } else {
- fprintf_td(stderr, "****** Server SETTINGS_CHANGED: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
- to_string(newmask).c_str(), to_string(changedmask).c_str());
- }
- fprintf_td(stderr, "Server Status BTAdapter:\n");
- fprintf_td(stderr, "%s\n", a.toString().c_str());
- (void)timestamp;
- }
-
- void discoveringChanged(BTAdapter &a, const ScanType currentMeta, const ScanType changedType, const bool changedEnabled, const DiscoveryPolicy policy, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Server DISCOVERING: meta %s, changed[%s, enabled %d, policy %s]: %s\n",
- to_string(currentMeta).c_str(), to_string(changedType).c_str(), changedEnabled, to_string(policy).c_str(), a.toString().c_str());
- (void)timestamp;
- }
-
- bool deviceFound(BTDeviceRef device, const uint64_t timestamp) override {
- (void)timestamp;
-
- fprintf_td(stderr, "****** Server FOUND__-1: NOP %s\n", device->toString(true).c_str());
- return false;
- }
-
- void deviceUpdated(BTDeviceRef device, const EIRDataType updateMask, const uint64_t timestamp) override {
- if( SHOW_UPDATE_EVENTS ) {
- fprintf_td(stderr, "****** Server UPDATED: %s of %s\n", to_string(updateMask).c_str(), device->toString(true).c_str());
- }
- (void)timestamp;
- }
-
- void deviceConnected(BTDeviceRef device, const bool discovered, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Server CONNECTED (discovered %d): %s\n", discovered, device->toString(true).c_str());
- const bool available = nullptr == parent.getDevice();
- if( available ) {
- parent.setDevice(device);
- BTDeviceRegistry::addToProcessingDevices(device->getAddressAndType(), device->getName());
- }
- (void)discovered;
- (void)timestamp;
- }
-
- void devicePairingState(BTDeviceRef device, const SMPPairingState state, const PairingMode mode, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Server PAIRING STATE: state %s, mode %s, %s\n",
- to_string(state).c_str(), to_string(mode).c_str(), device->toString().c_str());
- (void)timestamp;
- switch( state ) {
- case SMPPairingState::NONE:
- // next: deviceReady(..)
- break;
- case SMPPairingState::FAILED: {
- // next: deviceReady() or deviceDisconnected(..)
- } break;
- case SMPPairingState::REQUESTED_BY_RESPONDER:
- // next: FEATURE_EXCHANGE_STARTED
- break;
- case SMPPairingState::FEATURE_EXCHANGE_STARTED:
- // next: FEATURE_EXCHANGE_COMPLETED
- break;
- case SMPPairingState::FEATURE_EXCHANGE_COMPLETED:
- // next: PASSKEY_EXPECTED... or KEY_DISTRIBUTION
- break;
- case SMPPairingState::PASSKEY_EXPECTED: {
- const BTSecurityRegistry::Entry* sec = BTSecurityRegistry::getStartOf(device->getAddressAndType().address, "");
- if( nullptr != sec && sec->getPairingPasskey() != BTSecurityRegistry::Entry::NO_PASSKEY ) {
- std::thread dc(&BTDevice::setPairingPasskey, device, static_cast<uint32_t>( sec->getPairingPasskey() ));
- dc.detach();
- } else {
- std::thread dc(&BTDevice::setPairingPasskey, device, 0);
- // 3s disconnect: std::thread dc(&BTDevice::setPairingPasskeyNegative, device);
- dc.detach();
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case SMPPairingState::NUMERIC_COMPARE_EXPECTED: {
- const BTSecurityRegistry::Entry* sec = BTSecurityRegistry::getStartOf(device->getAddressAndType().address, "");
- if( nullptr != sec ) {
- std::thread dc(&BTDevice::setPairingNumericComparison, device, sec->getPairingNumericComparison());
- dc.detach();
- } else {
- std::thread dc(&BTDevice::setPairingNumericComparison, device, false);
- dc.detach();
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case SMPPairingState::OOB_EXPECTED:
- // FIXME: ABORT
- break;
- case SMPPairingState::KEY_DISTRIBUTION:
- // next: COMPLETED or FAILED
- break;
- case SMPPairingState::COMPLETED:
- // next: deviceReady(..)
- break;
- default: // nop
- break;
- }
- }
-
- void deviceReady(BTDeviceRef device, const uint64_t timestamp) override {
- (void)timestamp;
- fprintf_td(stderr, "****** Server READY-1: NOP %s\n", device->toString(true).c_str());
- }
-
- void deviceDisconnected(BTDeviceRef device, const HCIStatusCode reason, const uint16_t handle, const uint64_t timestamp) override {
- fprintf_td(stderr, "****** Server DISCONNECTED (count %zu): Reason 0x%X (%s), old handle %s: %s\n",
- 1+parent.disconnectCount.load(), static_cast<uint8_t>(reason), to_string(reason).c_str(),
- to_hexstring(handle).c_str(), device->toString(true).c_str());
-
- const bool match = parent.matches(device);
- if( match ) {
- parent.setDevice(nullptr);
- }
- std::thread sd(&DBTServer00::processDisconnectedDevice, &parent, device); // @suppress("Invalid arguments")
- sd.detach();
- (void)timestamp;
- }
-
- std::string toString() const noexcept override {
- return "Server MyAdapterStatusListener[this "+to_hexstring(this)+"]";
- }
-
- };
-
- class MyGATTServerListener : public DBGattServer::Listener {
- private:
- DBTServer00& parent;
- jau::service_runner pulse_service;
-
- jau::sc_atomic_uint16 handlePulseDataNotify = 0;
- jau::sc_atomic_uint16 handlePulseDataIndicate = 0;
- jau::sc_atomic_uint16 handleResponseDataNotify = 0;
- jau::sc_atomic_uint16 handleResponseDataIndicate = 0;
-
- uint16_t usedMTU = BTGattHandler::number(BTGattHandler::Defaults::MIN_ATT_MTU);
-
- void pulse_worker_init(jau::service_runner& sr) noexcept {
- (void)sr;
- const BTDeviceRef connectedDevice_ = parent.getDevice();
- const std::string connectedDeviceStr = nullptr != connectedDevice_ ? connectedDevice_->toString() : "n/a";
- fprintf_td(stderr, "****** Server GATT::PULSE Start %s\n", connectedDeviceStr.c_str());
- }
- void pulse_worker(jau::service_runner& sr) noexcept {
- BTDeviceRef connectedDevice_ = parent.getDevice();
- if( nullptr != connectedDevice_ && connectedDevice_->getConnected() ) {
- if( 0 != handlePulseDataNotify || 0 != handlePulseDataIndicate ) {
- std::string data( "Dynamic Data Example. Elapsed Milliseconds: "+jau::to_decstring(environment::getElapsedMillisecond(), ',', 9) );
- jau::POctets v(data.size()+1, jau::endian::little);
- v.put_string_nc(0, data, v.size(), true /* includeEOS */);
- if( 0 != handlePulseDataNotify ) {
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** Server GATT::sendNotification: PULSE to %s\n", connectedDevice_->toString().c_str());
- }
- connectedDevice_->sendNotification(handlePulseDataNotify, v);
- }
- if( 0 != handlePulseDataIndicate ) {
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** Server GATT::sendIndication: PULSE to %s\n", connectedDevice_->toString().c_str());
- }
- connectedDevice_->sendIndication(handlePulseDataIndicate, v);
- }
- }
- }
- if( !sr.shall_stop() ) {
- jau::sleep_for( 100_ms );
- }
- }
- void pulse_worker_end(jau::service_runner& sr) noexcept {
- (void)sr;
- const BTDeviceRef connectedDevice_ = parent.getDevice();
- const std::string connectedDeviceStr = nullptr != connectedDevice_ ? connectedDevice_->toString() : "n/a";
- fprintf_td(stderr, "****** Server GATT::PULSE End %s\n", connectedDeviceStr.c_str());
- }
-
- void sendResponse(jau::POctets data) {
- BTDeviceRef connectedDevice_ = parent.getDevice();
- if( nullptr != connectedDevice_ && connectedDevice_->getConnected() ) {
- if( 0 != handleResponseDataNotify || 0 != handleResponseDataIndicate ) {
- if( 0 != handleResponseDataNotify ) {
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** GATT::sendNotification: %s to %s\n",
- data.toString().c_str(), connectedDevice_->toString().c_str());
- }
- connectedDevice_->sendNotification(handleResponseDataNotify, data);
- }
- if( 0 != handleResponseDataIndicate ) {
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** GATT::sendIndication: %s to %s\n",
- data.toString().c_str(), connectedDevice_->toString().c_str());
- }
- connectedDevice_->sendIndication(handleResponseDataIndicate, data);
- }
- }
- }
- }
-
- public:
-
- MyGATTServerListener(DBTServer00& p)
- : parent(p),
- pulse_service("MyGATTServerListener::pulse", THREAD_SHUTDOWN_TIMEOUT_MS,
- jau::bindMemberFunc(this, &MyGATTServerListener::pulse_worker),
- jau::bindMemberFunc(this, &MyGATTServerListener::pulse_worker_init),
- jau::bindMemberFunc(this, &MyGATTServerListener::pulse_worker_end))
- {
- pulse_service.start();
- }
-
- ~MyGATTServerListener() noexcept {
- pulse_service.stop();
- }
-
- void clear() {
- const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
-
- handlePulseDataNotify = 0;
- handlePulseDataIndicate = 0;
- handleResponseDataNotify = 0;
- handleResponseDataIndicate = 0;
-
- parent.dbGattServer->resetGattClientCharConfig(DBTConstants::DataServiceUUID, DBTConstants::PulseDataUUID);
- parent.dbGattServer->resetGattClientCharConfig(DBTConstants::DataServiceUUID, DBTConstants::ResponseUUID);
- }
-
- void close() noexcept {
- pulse_service.stop();
- clear();
- }
-
- void connected(BTDeviceRef device, const uint16_t initialMTU) override {
- const bool match = parent.matches(device);
- fprintf_td(stderr, "****** Server GATT::connected(match %d): initMTU %d, %s\n",
- match, (int)initialMTU, device->toString().c_str());
- if( match ) {
- const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
- usedMTU = initialMTU;
- }
- }
-
- void disconnected(BTDeviceRef device) override {
- const bool match = parent.matches(device);
- fprintf_td(stderr, "****** Server GATT::disconnected(match %d): %s\n", match, device->toString().c_str());
- if( match ) {
- clear();
- }
- }
-
- void mtuChanged(BTDeviceRef device, const uint16_t mtu) override {
- const bool match = parent.matches(device);
- const uint16_t usedMTU_old = usedMTU;
- if( match ) {
- const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
- usedMTU = mtu;
- }
- fprintf_td(stderr, "****** Server GATT::mtuChanged(match %d, served %zu, left %zu): %d -> %d, %s\n",
- match, parent.servedProtocolSessionsTotal.load(), parent.servingProtocolSessionsLeft.load(),
- match ? (int)usedMTU_old : 0, (int)mtu, device->toString().c_str());
- }
-
- bool readCharValue(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c) override {
- const bool match = parent.matches(device);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** Server GATT::readCharValue(match %d): to %s, from\n %s\n %s\n",
- match, device->toString().c_str(), s->toString().c_str(), c->toString().c_str());
- }
- return match;
- }
-
- bool readDescValue(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c, DBGattDescRef d) override {
- const bool match = parent.matches(device);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** Server GATT::readDescValue(match %d): to %s, from\n %s\n %s\n %s\n",
- match, device->toString().c_str(), s->toString().c_str(), c->toString().c_str(), d->toString().c_str());
- }
- return match;
- }
-
- bool writeCharValue(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c, const jau::TROOctets & value, const uint16_t value_offset) override {
- const bool match = parent.matches(device);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** Server GATT::writeCharValue(match %d): %s '%s' @ %u from %s, to\n %s\n %s\n",
- match, value.toString().c_str(), jau::dfa_utf8_decode( value.get_ptr(), value.size() ).c_str(),
- value_offset,
- device->toString().c_str(), s->toString().c_str(), c->toString().c_str());
- }
- return match;
- }
- void writeCharValueDone(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c) override {
- const bool match = parent.matches(device);
- const jau::TROOctets& value = c->getValue();
- bool isFinalHandshake = false;
- bool isFinalHandshakeSuccess = false;
-
- if( match &&
- c->getValueType()->equivalent( DBTConstants::CommandUUID ) &&
- ( 0 != handleResponseDataNotify || 0 != handleResponseDataIndicate ) )
- {
- isFinalHandshakeSuccess = DBTConstants::SuccessHandshakeCommandData.size() == value.size() &&
- 0 == ::memcmp(DBTConstants::SuccessHandshakeCommandData.data(), value.get_ptr(), value.size());
- isFinalHandshake = isFinalHandshakeSuccess ||
- ( DBTConstants::FailHandshakeCommandData.size() == value.size() &&
- 0 == ::memcmp(DBTConstants::FailHandshakeCommandData.data(), value.get_ptr(), value.size()) );
-
- if( isFinalHandshake ) {
- if( isFinalHandshakeSuccess ) {
- parent.servedProtocolSessionsSuccess++;
- }
- parent.servedProtocolSessionsTotal++;
- if( parent.servingProtocolSessionsLeft > 0 ) {
- parent.servingProtocolSessionsLeft--;
- }
- }
- jau::POctets value2(value);
- std::thread senderThread(&MyGATTServerListener::sendResponse, this, value2); // @suppress("Invalid arguments")
- senderThread.detach();
- }
- if( GATT_VERBOSE || isFinalHandshake ) {
- fprintf_td(stderr, "****** Server GATT::writeCharValueDone(match %d, finalCmd %d, sessions [%d ok / %d total], left %d): From %s, to\n %s\n %s\n Char-Value: %s\n",
- match, isFinalHandshake, parent.servedProtocolSessionsSuccess.load(), parent.servedProtocolSessionsTotal.load(), parent.servingProtocolSessionsLeft.load(),
- device->toString().c_str(), s->toString().c_str(), c->toString().c_str(), value.toString().c_str());
- }
- }
-
- bool writeDescValue(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c, DBGattDescRef d, const jau::TROOctets & value, const uint16_t value_offset) override {
- const bool match = parent.matches(device);
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "****** Server GATT::writeDescValue(match %d): %s '%s' @ %u from %s\n %s\n %s\n %s\n",
- match, value.toString().c_str(), jau::dfa_utf8_decode( value.get_ptr(), value.size() ).c_str(),
- value_offset,
- device->toString().c_str(), s->toString().c_str(), c->toString().c_str(), d->toString().c_str());
- }
- return match;
- }
- void writeDescValueDone(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c, DBGattDescRef d) override {
- if( GATT_VERBOSE ) {
- const bool match = parent.matches(device);
- const jau::TROOctets& value = d->getValue();
- fprintf_td(stderr, "****** Server GATT::writeDescValueDone(match %d): From %s\n %s\n %s\n %s\n Desc-Value: %s\n",
- match, device->toString().c_str(), s->toString().c_str(), c->toString().c_str(), d->toString().c_str(), value.toString().c_str());
- }
- }
-
- void clientCharConfigChanged(BTDeviceRef device, DBGattServiceRef s, DBGattCharRef c, DBGattDescRef d, const bool notificationEnabled, const bool indicationEnabled) override {
- const bool match = parent.matches(device);
- if( GATT_VERBOSE ) {
- const jau::TROOctets& value = d->getValue();
- fprintf_td(stderr, "****** GATT::clientCharConfigChanged(match %d): notify %d, indicate %d from %s\n %s\n %s\n %s\n Desc-Value: %s\n",
- match, notificationEnabled, indicationEnabled,
- device->toString().c_str(), s->toString().c_str(), c->toString().c_str(), d->toString().c_str(), value.toString().c_str());
- }
- if( match ) {
- if( c->getValueType()->equivalent( DBTConstants::PulseDataUUID ) ) {
- const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
- handlePulseDataNotify = notificationEnabled ? c->getValueHandle() : 0;
- handlePulseDataIndicate = indicationEnabled ? c->getValueHandle() : 0;
- } else if( c->getValueType()->equivalent( DBTConstants::ResponseUUID ) ) {
- const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
- handleResponseDataNotify = notificationEnabled ? c->getValueHandle() : 0;
- handleResponseDataIndicate = indicationEnabled ? c->getValueHandle() : 0;
- }
- }
- }
- };
-
- std::shared_ptr<MyGATTServerListener> gattServerListener = std::make_shared<MyGATTServerListener>(*this);
- std::shared_ptr<AdapterStatusListener> myAdapterStatusListener = std::make_shared<MyAdapterStatusListener>(*this);
-
- BTAdapterRef serverAdapter = nullptr;
-
- public:
-
- DBTServer00(const std::string& adapterName_, const jau::EUI48& useAdapter_, const BTMode btMode_, const bool use_SC_, const BTSecurityLevel adapterSecurityLevel_) {
- this->adapterName = adapterName_;
- this->useAdapter = useAdapter_;
- this->btMode = btMode_;
- this->use_SC = use_SC_;
- this->adapterSecurityLevel = adapterSecurityLevel_;
-
- dbGattServer->addListener( gattServerListener );
- }
- DBTServer00(const std::string& adapterName_, const jau::EUI48& useAdapter_, const BTSecurityLevel adapterSecurityLevel_)
- : DBTServer00(adapterName_, useAdapter_, BTMode::DUAL, true /* SC */, adapterSecurityLevel_)
- { }
-
- DBTServer00(const std::string& adapterName_, const BTSecurityLevel adapterSecurityLevel_)
- : DBTServer00(adapterName_, EUI48::ALL_DEVICE, BTMode::DUAL, true /* SC */, adapterSecurityLevel_)
- { }
-
- std::string getName() override { return adapterName; }
-
- BTSecurityLevel getSecurityLevel() override { return adapterSecurityLevel; }
-
- void setAdapter(BTAdapterRef serverAdapter_) override {
- this->serverAdapter = serverAdapter_;
- }
-
- BTAdapterRef getAdapter() override { return serverAdapter; }
-
- private:
- static const uint16_t adv_interval_min=160; // x0.625 = 100ms
- static const uint16_t adv_interval_max=480; // x0.625 = 300ms
- static const AD_PDU_Type adv_type=AD_PDU_Type::ADV_IND;
- static const uint8_t adv_chan_map=0x07;
- static const uint8_t filter_policy=0x00;
-
- public:
-
- void close(const std::string& msg) override {
- fprintf_td(stderr, "****** Server Close.0: %s\n", msg.c_str());
- serverAdapter->removeStatusListener( myAdapterStatusListener );
- {
- stopAdvertising(msg);
- BTDeviceRef connectedDevice_ = getDevice();
- if( nullptr != connectedDevice_ ) {
- setDevice(nullptr);
- connectedDevice_->disconnect();
- }
- }
- gattServerListener->close();
- // dbGattServer = nullptr; // keep alive
- stopAdvertising(msg); // try once more in case of already started AdapterStatusListener
- fprintf_td(stderr, "****** Server Close.X: %s\n", msg.c_str());
- }
-
- void setProtocolSessionsLeft(const int v) override {
- servingProtocolSessionsLeft = v;
- }
- int getProtocolSessionsLeft() override {
- return servingProtocolSessionsLeft;
- }
- int getProtocolSessionsDoneTotal() override {
- return servedProtocolSessionsTotal;
- }
- int getProtocolSessionsDoneSuccess() override {
- return servedProtocolSessionsSuccess;
- }
- int getDisconnectCount() override {
- return disconnectCount;
- }
-
- private:
- HCIStatusCode stopAdvertising(std::string msg) {
- HCIStatusCode status = serverAdapter->stopAdvertising();
- fprintf_td(stderr, "****** Server Stop advertising (%s) result: %s: %s\n", msg.c_str(), to_string(status).c_str(), serverAdapter->toString().c_str());
- return status;
- }
-
- public:
-
- HCIStatusCode startAdvertising(const std::string& msg) override {
- EInfoReport eir;
- EIRDataType adv_mask = EIRDataType::FLAGS | EIRDataType::SERVICE_UUID;
- EIRDataType scanrsp_mask = EIRDataType::NAME | EIRDataType::CONN_IVAL;
-
- eir.addFlags(GAPFlags::LE_Gen_Disc);
- eir.addFlags(GAPFlags::BREDR_UNSUP);
-
- eir.addService(DBTConstants::DataServiceUUID);
- eir.setServicesComplete(false);
-
- eir.setName(serverAdapter->getName());
- eir.setConnInterval(8, 12); // 10ms - 15ms
-
- DBGattCharRef gattDevNameChar = dbGattServer->findGattChar( jau::uuid16_t(GattServiceType::GENERIC_ACCESS),
- jau::uuid16_t(GattCharacteristicType::DEVICE_NAME) );
- if( nullptr != gattDevNameChar ) {
- std::string aname = serverAdapter->getName();
- gattDevNameChar->setValue(reinterpret_cast<uint8_t*>(aname.data()), aname.size(), 0);
- }
-
- fprintf_td(stderr, "****** Start advertising (%s): EIR %s\n", msg.c_str(), eir.toString().c_str());
- fprintf_td(stderr, "****** Start advertising (%s): adv %s, scanrsp %s\n", msg.c_str(), to_string(adv_mask).c_str(), to_string(scanrsp_mask).c_str());
-
- HCIStatusCode status = serverAdapter->startAdvertising(dbGattServer, eir, adv_mask, scanrsp_mask,
- adv_interval_min, adv_interval_max,
- adv_type, adv_chan_map, filter_policy);
- fprintf_td(stderr, "****** Server Start advertising (%s) result: %s: %s\n", msg.c_str(), to_string(status).c_str(), serverAdapter->toString().c_str());
- if( GATT_VERBOSE ) {
- fprintf_td(stderr, "%s", dbGattServer->toFullString().c_str());
- }
- return status;
- }
-
- private:
- void processDisconnectedDevice(BTDeviceRef device) {
- fprintf_td(stderr, "****** Server Disconnected Device (count %zu, seved %zu, left %zu): Start %s\n",
- 1+disconnectCount.load(), servedProtocolSessionsTotal.load(), servingProtocolSessionsLeft.load(), device->toString().c_str());
-
- // already unpaired
- stopAdvertising("device-disconnected");
- device->remove();
- BTDeviceRegistry::removeFromProcessingDevices(device->getAddressAndType());
-
- disconnectCount++;
-
- jau::sleep_for( 100_ms ); // wait a little (FIXME: Fast restart of advertising error)
-
- if( servingProtocolSessionsLeft > 0 ) {
- startAdvertising("device-disconnected");
- }
-
- fprintf_td(stderr, "****** Server Disonnected Device: End %s\n", device->toString().c_str());
- }
-
- public:
-
- bool initAdapter(BTAdapterRef adapter) override {
- if( useAdapter != EUI48::ALL_DEVICE && useAdapter != adapter->getAddressAndType().address ) {
- fprintf_td(stderr, "initServerAdapter: Adapter not selected: %s\n", adapter->toString().c_str());
- return false;
- }
- adapterName = adapterName + "-" + adapter->getAddressAndType().address.toString();
- {
- auto it = std::remove( adapterName.begin(), adapterName.end(), ':');
- adapterName.erase(it, adapterName.end());
- }
-
- if( !adapter->isInitialized() ) {
- // Initialize with defaults and power-on
- const HCIStatusCode status = adapter->initialize( btMode );
- if( HCIStatusCode::SUCCESS != status ) {
- fprintf_td(stderr, "initServerAdapter: initialize failed: %s: %s\n",
- to_string(status).c_str(), adapter->toString().c_str());
- return false;
- }
- } else if( !adapter->setPowered( true ) ) {
- fprintf_td(stderr, "initServerAdapter: setPower.1 on failed: %s\n", adapter->toString().c_str());
- return false;
- }
- // adapter is powered-on
- fprintf_td(stderr, "initServerAdapter.1: %s\n", adapter->toString().c_str());
-
- if( adapter->setPowered(false) ) {
- HCIStatusCode status = adapter->setName(adapterName, adapterShortName);
- if( HCIStatusCode::SUCCESS == status ) {
- fprintf_td(stderr, "initServerAdapter: setLocalName OK: %s\n", adapter->toString().c_str());
- } else {
- fprintf_td(stderr, "initServerAdapter: setLocalName failed: %s\n", adapter->toString().c_str());
- return false;
- }
-
- status = adapter->setSecureConnections( use_SC );
- if( HCIStatusCode::SUCCESS == status ) {
- fprintf_td(stderr, "initServerAdapter: setSecureConnections OK: %s\n", adapter->toString().c_str());
- } else {
- fprintf_td(stderr, "initServerAdapter: setSecureConnections failed: %s\n", adapter->toString().c_str());
- return false;
- }
-
- const uint16_t conn_min_interval = 8; // 10ms
- const uint16_t conn_max_interval = 40; // 50ms
- const uint16_t conn_latency = 0;
- const uint16_t supervision_timeout = 50; // 500ms
- status = adapter->setDefaultConnParam(conn_min_interval, conn_max_interval, conn_latency, supervision_timeout);
- if( HCIStatusCode::SUCCESS == status ) {
- fprintf_td(stderr, "initServerAdapter: setDefaultConnParam OK: %s\n", adapter->toString().c_str());
- } else {
- fprintf_td(stderr, "initServerAdapter: setDefaultConnParam failed: %s\n", adapter->toString().c_str());
- return false;
- }
-
- if( !adapter->setPowered( true ) ) {
- fprintf_td(stderr, "initServerAdapter: setPower.2 on failed: %s\n", adapter->toString().c_str());
- return false;
- }
- } else {
- fprintf_td(stderr, "initServerAdapter: setPowered.2 off failed: %s\n", adapter->toString().c_str());
- return false;
- }
- // adapter is powered-on
- fprintf_td(stderr, "initServerAdapter.2: %s\n", adapter->toString().c_str());
-
- {
- const LE_Features le_feats = adapter->getLEFeatures();
- fprintf_td(stderr, "initServerAdapter: LE_Features %s\n", to_string(le_feats).c_str());
- }
- if( adapter->getBTMajorVersion() > 4 ) {
- LE_PHYs Tx { LE_PHYs::LE_2M }, Rx { LE_PHYs::LE_2M };
- HCIStatusCode res = adapter->setDefaultLE_PHY(Tx, Rx);
- fprintf_td(stderr, "initServerAdapter: Set Default LE PHY: status %s: Tx %s, Rx %s\n",
- to_string(res).c_str(), to_string(Tx).c_str(), to_string(Rx).c_str());
- }
- adapter->setSMPKeyPath(DBTConstants::SERVER_KEY_PATH);
-
- adapter->addStatusListener( myAdapterStatusListener );
-
- adapter->setServerConnSecurity(adapterSecurityLevel, SMPIOCapability::UNSET);
-
- return true;
- }
-};
-
-#endif // DBT_SERVER00_HPP_
diff --git a/trial/direct_bt/dbt_server01.hpp b/trial/direct_bt/dbt_server01.hpp
index e435b83d..4db62506 100644
--- a/trial/direct_bt/dbt_server01.hpp
+++ b/trial/direct_bt/dbt_server01.hpp
@@ -430,7 +430,6 @@ class DBTServer01 : public DBTServerTest {
clear();
}
- public:
void connected(BTDeviceRef device, const uint16_t initialMTU) override {
const bool match = parent.matches(device);
fprintf_td(stderr, "****** Server GATT::connected(match %d): initMTU %d, %s\n",
@@ -519,11 +518,9 @@ class DBTServer01 : public DBTServerTest {
parent.servingProtocolSessionsLeft--;
}
}
- {
- jau::POctets value2(value);
- std::thread senderThread(&MyGATTServerListener::sendResponse, this, value2);
- senderThread.detach();
- }
+ jau::POctets value2(value);
+ std::thread senderThread(&MyGATTServerListener::sendResponse, this, value2);
+ senderThread.detach();
}
if( GATT_VERBOSE || isFinalHandshake ) {
fprintf_td(stderr, "****** Server GATT::writeCharValueDone(match %d, finalCmd %d, sessions [%d ok / %d total], left %d): From %s, to\n %s\n %s\n Char-Value: %s\n",
@@ -690,7 +687,7 @@ class DBTServer01 : public DBTServerTest {
private:
void processDisconnectedDevice(BTDeviceRef device) {
- fprintf_td(stderr, "****** Server Disconnected Device (count %zu, seved %zu, left %zu): Start %s\n",
+ fprintf_td(stderr, "****** Server Disconnected Device (count %zu, served %zu, left %zu): Start %s\n",
1+disconnectCount.load(), servedProtocolSessionsTotal.load(), servingProtocolSessionsLeft.load(), device->toString().c_str());
// already unpaired
diff --git a/trial/direct_bt/test_client_server00.cpp b/trial/direct_bt/test_client_server00.cpp
index 43e8eb1c..f545191d 100644
--- a/trial/direct_bt/test_client_server00.cpp
+++ b/trial/direct_bt/test_client_server00.cpp
@@ -34,7 +34,7 @@
#include "dbt_base_client_server.hpp"
-#include "dbt_server00.hpp"
+#include "dbt_server01.hpp"
using namespace direct_bt;
@@ -96,7 +96,8 @@ TEST_CASE( "Server StartStop and SwitchRole Trial 00.2", "[trial][startstop][swi
REQUIRE( manager->getAdapterCount() >= 1 );
const std::string serverName = "TestDBTCS00-S-T10";
- std::shared_ptr<DBTServer00> server = std::make_shared<DBTServer00>(serverName, EUI48::ALL_DEVICE, BTMode::DUAL, true /* SC */, BTSecurityLevel::NONE);
+ std::shared_ptr<DBTServer01> server = std::make_shared<DBTServer01>(serverName, EUI48::ALL_DEVICE, BTMode::DUAL,
+ true /* SC */, BTSecurityLevel::NONE, false /* do_disconnect_ */);
server->setProtocolSessionsLeft(1);
ChangedAdapterSetCallback myChangedAdapterSetFunc = DBTEndpoint::initChangedAdapterSetListener(manager, { server });
diff --git a/trial/direct_bt/test_provoke_client_server_i470.cpp b/trial/direct_bt/test_provoke_client_server_i470.cpp
index 0e7ce19a..d2da1908 100644
--- a/trial/direct_bt/test_provoke_client_server_i470.cpp
+++ b/trial/direct_bt/test_provoke_client_server_i470.cpp
@@ -27,11 +27,10 @@
#include <catch2/catch_amalgamated.hpp>
#include <jau/test/catch2_ext.hpp>
-// #include "dbt_base_client_server.hpp"
#include "dbt_client_server1x.hpp"
-#include "dbt_server01.hpp"
-#include "dbt_client01.hpp"
+// #include "dbt_server01.hpp"
+// #include "dbt_client01.hpp"
using namespace direct_bt;
diff --git a/trial/java/trial/org/direct_bt/DBTClient00.java b/trial/java/trial/org/direct_bt/DBTClient00.java
deleted file mode 100644
index 7366eb72..00000000
--- a/trial/java/trial/org/direct_bt/DBTClient00.java
+++ /dev/null
@@ -1,717 +0,0 @@
-/**
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2022 Gothel Software e.K.
- *
- * 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.
- */
-
-package trial.org.direct_bt;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.direct_bt.AdapterSettings;
-import org.direct_bt.AdapterStatusListener;
-import org.direct_bt.BTMode;
-import org.direct_bt.BTSecurityLevel;
-import org.direct_bt.BTAdapter;
-import org.direct_bt.BTDevice;
-import org.direct_bt.BTDeviceRegistry;
-import org.direct_bt.BTGattChar;
-import org.direct_bt.BTGattCharListener;
-import org.direct_bt.BTGattCmd;
-import org.direct_bt.BTGattDesc;
-import org.direct_bt.BTGattService;
-import org.direct_bt.BTSecurityRegistry;
-import org.direct_bt.BTUtils;
-import org.direct_bt.DiscoveryPolicy;
-import org.direct_bt.EIRDataTypeSet;
-import org.direct_bt.EInfoReport;
-import org.direct_bt.GattCharPropertySet;
-import org.direct_bt.HCIStatusCode;
-import org.direct_bt.LE_Features;
-import org.direct_bt.LE_PHYs;
-import org.direct_bt.PairingMode;
-import org.direct_bt.SMPIOCapability;
-import org.direct_bt.SMPKeyBin;
-import org.direct_bt.SMPPairingState;
-import org.direct_bt.ScanType;
-import org.jau.net.EUI48;
-import org.junit.Assert;
-
-/**
- * This central BTRole::Master participant works with DBTServer00.
- */
-public class DBTClient00 implements DBTClientTest {
- private final boolean GATT_VERBOSE = false;
-
- private final long timestamp_t0 = BTUtils.startupTimeMillis();
-
- private final String adapterShortName = "TDev2Clt";
-
- private final MyAdapterStatusListener myAdapterStatusListener = new MyAdapterStatusListener();
-
- private final byte cmd_arg = (byte)0x44;
-
- private String adapterName = "TestDev2_Clt";
- private EUI48 useAdapter = EUI48.ALL_DEVICE;
- private BTMode btMode = BTMode.DUAL;
- private BTAdapter clientAdapter = null;
-
- private boolean KEEP_CONNECTED = false;
-
- private boolean REMOVE_DEVICE = false;
-
- private DiscoveryPolicy discoveryPolicy = DiscoveryPolicy.PAUSE_CONNECTED_UNTIL_READY; // default value
-
- private final AtomicInteger disconnectCount = new AtomicInteger(0);
- private final AtomicInteger measurementsLeft = new AtomicInteger(1);
- private final AtomicInteger deviceReadyCount = new AtomicInteger(0);
- private final AtomicInteger notificationsReceived = new AtomicInteger(0);
- private final AtomicInteger indicationsReceived = new AtomicInteger(0);
- private final AtomicInteger completedGATTCommands = new AtomicInteger(0);
- private final AtomicInteger completedMeasurementsTotal = new AtomicInteger(0);
- private final AtomicInteger completedMeasurementsSuccess = new AtomicInteger(0);
-
- public DBTClient00(final String adapterName, final EUI48 useAdapter, final BTMode btMode) {
- this.adapterName = adapterName;
- this.useAdapter = useAdapter;
- this.btMode = btMode;
- }
-
- @Override
- public String getName() { return adapterName; }
-
- @Override
- public void setAdapter(final BTAdapter clientAdapter) {
- this.clientAdapter = clientAdapter;
- }
- @Override
- public BTAdapter getAdapter() { return clientAdapter; }
-
- @Override
- public void setProtocolSessionsLeft(final int v) {
- measurementsLeft.set(v);
- }
- @Override
- public int getProtocolSessionsLeft() {
- return measurementsLeft.get();
- }
- @Override
- public int getProtocolSessionsDoneTotal() {
- return completedMeasurementsTotal.get();
- }
- @Override
- public int getProtocolSessionsDoneSuccess() {
- return completedMeasurementsSuccess.get();
- }
- @Override
- public int getDisconnectCount() {
- return this.disconnectCount.get();
- }
-
- @Override
- public void setDiscoveryPolicy(final DiscoveryPolicy v) {
- discoveryPolicy = v;
- }
- @Override
- public void setKeepConnected(final boolean v) {
- KEEP_CONNECTED = v;
- }
- @Override
- public void setRemoveDevice(final boolean v) {
- REMOVE_DEVICE = v;
- }
-
- static void executeOffThread(final Runnable runobj, final String threadName, final boolean detach) {
- final Thread t = new Thread( runobj, threadName );
- if( detach ) {
- t.setDaemon(true); // detach thread
- }
- t.start();
- }
- static void execute(final Runnable task, final boolean offThread) {
- if( offThread ) {
- final Thread t = new Thread(task);
- t.setDaemon(true);
- t.start();
- } else {
- task.run();
- }
- }
-
- class MyAdapterStatusListener extends AdapterStatusListener {
- @Override
- public void adapterSettingsChanged(final BTAdapter adapter, final AdapterSettings oldmask,
- final AdapterSettings newmask, final AdapterSettings changedmask, final long timestamp) {
- final boolean initialSetting = oldmask.isEmpty();
- if( initialSetting ) {
- BTUtils.println(System.err, "****** Client SETTINGS: "+oldmask+" -> "+newmask+", initial "+changedmask);
- } else {
- BTUtils.println(System.err, "****** Client SETTINGS: "+oldmask+" -> "+newmask+", changed "+changedmask);
- }
- BTUtils.println(System.err, "Client Status Adapter:");
- BTUtils.println(System.err, adapter.toString());
- }
-
- @Override
- public void discoveringChanged(final BTAdapter adapter, final ScanType currentMeta, final ScanType changedType, final boolean changedEnabled, final DiscoveryPolicy policy, final long timestamp) {
- BTUtils.println(System.err, "****** Client DISCOVERING: meta "+currentMeta+", changed["+changedType+", enabled "+changedEnabled+", policy "+policy+"] on "+adapter);
- }
-
- @Override
- public boolean deviceFound(final BTDevice device, final long timestamp) {
- if( !BTDeviceRegistry.isDeviceProcessing( device.getAddressAndType() ) &&
- ( !BTDeviceRegistry.isWaitingForAnyDevice() ||
- ( BTDeviceRegistry.isWaitingForDevice(device.getAddressAndType().address, device.getName()) &&
- ( 0 < measurementsLeft.get() || !BTDeviceRegistry.isDeviceProcessed(device.getAddressAndType()) )
- )
- )
- )
- {
- BTUtils.println(System.err, "****** Client FOUND__-0: Connecting "+device.toString());
- {
- final long td = BTUtils.currentTimeMillis() - timestamp_t0; // adapter-init -> now
- BTUtils.println(System.err, "PERF: adapter-init -> FOUND__-0 " + td + " ms");
- }
- executeOffThread( () -> { connectDiscoveredDevice(device); },
- "Client DBT-Connect-"+device.getAddressAndType(), true /* detach */);
- return true;
- } else {
- BTUtils.println(System.err, "****** Client FOUND__-1: NOP "+device.toString());
- return false;
- }
- }
-
- @Override
- public void deviceUpdated(final BTDevice device, final EIRDataTypeSet updateMask, final long timestamp) {
- }
-
- @Override
- public void deviceConnected(final BTDevice device, final boolean discovered, final long timestamp) {
- BTUtils.println(System.err, "****** Client CONNECTED (discovered "+discovered+"): "+device.toString());
- }
-
- @Override
- public void devicePairingState(final BTDevice device, final SMPPairingState state, final PairingMode mode, final long timestamp) {
- BTUtils.println(System.err, "****** Client PAIRING_STATE: state "+state+", mode "+mode+": "+device);
- switch( state ) {
- case NONE:
- // next: deviceReady(..)
- break;
- case FAILED: {
- final boolean res = SMPKeyBin.remove(DBTConstants.CLIENT_KEY_PATH, device);
- BTUtils.println(System.err, "****** Client PAIRING_STATE: state "+state+"; Remove key file "+SMPKeyBin.getFilename(DBTConstants.CLIENT_KEY_PATH, device)+", res "+res);
- // next: deviceReady() or deviceDisconnected(..)
- } break;
- case REQUESTED_BY_RESPONDER:
- // next: FEATURE_EXCHANGE_STARTED
- break;
- case FEATURE_EXCHANGE_STARTED:
- // next: FEATURE_EXCHANGE_COMPLETED
- break;
- case FEATURE_EXCHANGE_COMPLETED:
- // next: PASSKEY_EXPECTED... or KEY_DISTRIBUTION
- break;
- case PASSKEY_EXPECTED: {
- final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address, "");
- if( null != sec && sec.getPairingPasskey() != BTSecurityRegistry.NO_PASSKEY ) {
- executeOffThread( () -> { device.setPairingPasskey( sec.getPairingPasskey() ); }, "DBT-SetPasskey-"+device.getAddressAndType(), true /* detach */);
- } else {
- executeOffThread( () -> { device.setPairingPasskey( 0 ); }, "DBT-SetPasskey-"+device.getAddressAndType(), true /* detach */);
- // 3s disconnect: executeOffThread( () -> { device.setPairingPasskeyNegative(); }, "DBT-SetPasskeyNegative-"+device.getAddressAndType(), true /* detach */);
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case NUMERIC_COMPARE_EXPECTED: {
- final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address, "");
- if( null != sec ) {
- executeOffThread( () -> { device.setPairingNumericComparison( sec.getPairingNumericComparison() ); }, "DBT-SetNumericComp-"+device.getAddressAndType(), true /* detach */);
- } else {
- executeOffThread( () -> { device.setPairingNumericComparison( false ); }, "DBT-SetNumericCompFalse-"+device.getAddressAndType(), true /* detach */);
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case OOB_EXPECTED:
- // FIXME: ABORT
- break;
- case KEY_DISTRIBUTION:
- // next: COMPLETED or FAILED
- break;
- case COMPLETED:
- // next: deviceReady(..)
- break;
- default: // nop
- break;
- }
- }
-
- @Override
- public void deviceReady(final BTDevice device, final long timestamp) {
- if( !BTDeviceRegistry.isDeviceProcessing( device.getAddressAndType() ) &&
- ( !BTDeviceRegistry.isWaitingForAnyDevice() ||
- ( BTDeviceRegistry.isWaitingForDevice(device.getAddressAndType().address, device.getName()) &&
- ( 0 < measurementsLeft.get() || !BTDeviceRegistry.isDeviceProcessed(device.getAddressAndType()) )
- )
- )
- )
- {
- deviceReadyCount.incrementAndGet();
- BTUtils.println(System.err, "****** Client READY-0: Processing["+deviceReadyCount.get()+"] "+device.toString());
- {
- final long td = BTUtils.currentTimeMillis() - timestamp_t0; // adapter-init -> now
- BTUtils.println(System.err, "PERF: adapter-init -> READY-0 " + td + " ms");
- }
- BTDeviceRegistry.addToProcessingDevices(device.getAddressAndType(), device.getName());
-
- // Be nice to Test* case, allowing to reach its own listener.deviceReady() added later
- executeOffThread( () -> { processReadyDevice(device); },
- "DBT-Process-"+device.getAddressAndType(), true /* detach */);
- // processReadyDevice(device); // AdapterStatusListener::deviceReady() explicitly allows prolonged and complex code execution!
- } else {
- BTUtils.println(System.err, "****** Client READY-1: NOP " + device.toString());
- }
- }
-
- @Override
- public void deviceDisconnected(final BTDevice device, final HCIStatusCode reason, final short handle, final long timestamp) {
- BTUtils.println(System.err, "****** Client DISCONNECTED: Reason "+reason+", old handle 0x"+Integer.toHexString(handle)+": "+device+" on "+device.getAdapter());
-
- disconnectCount.addAndGet(1);
-
- executeOffThread( () -> { removeDevice(device); }, "Client DBT-Remove-"+device.getAddressAndType(), true /* detach */);
- }
-
- @Override
- public String toString() {
- return "Client AdapterStatusListener[user, per-adapter]";
- }
- };
-
- class MyGATTEventListener extends BTGattCharListener {
- @Override
- public void notificationReceived(final BTGattChar charDecl,
- final byte[] value, final long timestamp) {
- if( GATT_VERBOSE ) {
- final long tR = BTUtils.currentTimeMillis();
- BTUtils.fprintf_td(System.err, "** Characteristic-Notify: UUID %s, td %d ******\n",
- charDecl.getUUID(), (tR-timestamp));
- BTUtils.fprintf_td(System.err, "** Characteristic: %s ******\n", charDecl.toString());
- BTUtils.fprintf_td(System.err, "** Value R: size %d, ro: %s ******\n", value.length, BTUtils.bytesHexString(value, 0, -1, true));
- BTUtils.fprintf_td(System.err, "** Value S: %s ******\n", BTUtils.decodeUTF8String(value, 0, value.length));
- }
- notificationsReceived.incrementAndGet();
- }
-
- @Override
- public void indicationReceived(final BTGattChar charDecl,
- final byte[] value, final long timestamp, final boolean confirmationSent) {
- if( GATT_VERBOSE ) {
- final long tR = BTUtils.currentTimeMillis();
- BTUtils.fprintf_td(System.err, "** Characteristic-Indication: UUID %s, td %d, confirmed %b ******\n",
- charDecl.getUUID(), (tR-timestamp), confirmationSent);
- BTUtils.fprintf_td(System.err, "** Characteristic: %s ******\n", charDecl.toString());
- BTUtils.fprintf_td(System.err, "** Value R: size %d, ro: %s ******\n", value.length, BTUtils.bytesHexString(value, 0, -1, true));
- BTUtils.fprintf_td(System.err, "** Value S: %s ******\n", BTUtils.decodeUTF8String(value, 0, value.length));
- }
- indicationsReceived.incrementAndGet();
- }
- }
-
- private void resetLastProcessingStats() {
- completedGATTCommands.set(0);
- notificationsReceived.set(0);
- indicationsReceived.set(0);
- }
-
- private void connectDiscoveredDevice(final BTDevice device) {
- BTUtils.println(System.err, "****** Client Connecting Device: Start " + device.toString());
-
- resetLastProcessingStats();
-
- final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address, device.getName());
- if( null != sec ) {
- BTUtils.println(System.err, "****** Client Connecting Device: Found SecurityDetail "+sec.toString()+" for "+device.toString());
- } else {
- BTUtils.println(System.err, "****** Client Connecting Device: No SecurityDetail for "+device.toString());
- }
- final BTSecurityLevel req_sec_level = null != sec ? sec.getSecLevel() : BTSecurityLevel.UNSET;
- HCIStatusCode res = device.uploadKeys(DBTConstants.CLIENT_KEY_PATH, req_sec_level, true /* verbose_ */);
- BTUtils.fprintf_td(System.err, "****** Client Connecting Device: BTDevice::uploadKeys(...) result %s\n", res.toString());
- if( HCIStatusCode.SUCCESS != res ) {
- if( null != sec ) {
- if( sec.isSecurityAutoEnabled() ) {
- final boolean r = device.setConnSecurityAuto( sec.getSecurityAutoIOCap() );
- BTUtils.println(System.err, "****** Client Connecting Device: Using SecurityDetail.SEC AUTO "+sec+" -> set OK "+r);
- } else if( sec.isSecLevelOrIOCapSet() ) {
- final boolean r = device.setConnSecurity(sec.getSecLevel(), sec.getIOCap());
- BTUtils.println(System.err, "****** Client Connecting Device: Using SecurityDetail.Level+IOCap "+sec+" -> set OK "+r);
- } else {
- final boolean r = device.setConnSecurityAuto( SMPIOCapability.KEYBOARD_ONLY );
- BTUtils.println(System.err, "****** Client Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY ("+sec+") -> set OK "+r);
- }
- } else {
- final boolean r = device.setConnSecurityAuto( SMPIOCapability.KEYBOARD_ONLY );
- BTUtils.println(System.err, "****** Client Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY -> set OK "+r);
- }
- }
- final EInfoReport eir = device.getEIR();
- BTUtils.println(System.err, "Client EIR-1 "+device.getEIRInd().toString());
- BTUtils.println(System.err, "Client EIR-2 "+device.getEIRScanRsp().toString());
- BTUtils.println(System.err, "Client EIR-+ "+eir.toString());
-
- short conn_interval_min = (short)8; // 10ms
- short conn_interval_max = (short)12; // 15ms
- final short conn_latency = (short)0;
- if( eir.isSet(EIRDataTypeSet.DataType.CONN_IVAL) ) {
- final short[] minmax = new short[2];
- eir.getConnInterval(minmax);
- conn_interval_min = minmax[0];
- conn_interval_max = minmax[1];
- }
- final short supervision_timeout = BTUtils.getHCIConnSupervisorTimeout(conn_latency, (int) ( conn_interval_max * 1.25 ) /* ms */);
- res = device.connectLE(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, supervision_timeout);
- // res = device.connectDefault();
- BTUtils.println(System.err, "****** Client Connecting Device Command, res "+res+": End result "+res+" of " + device.toString());
- }
-
- private void processReadyDevice(final BTDevice device) {
- BTUtils.println(System.err, "****** Client Processing Ready Device: Start " + device.toString());
- final long t1 = BTUtils.currentTimeMillis();
-
- SMPKeyBin.createAndWrite(device, DBTConstants.CLIENT_KEY_PATH, true /* verbose */);
- final long t2 = BTUtils.currentTimeMillis();
-
- boolean success = false;
-
- {
- final LE_PHYs resTx[] = { new LE_PHYs() };
- final LE_PHYs resRx[] = { new LE_PHYs() };
- final HCIStatusCode res = device.getConnectedLE_PHY(resTx, resRx);
- BTUtils.fprintf_td(System.err, "****** Client Got Connected LE PHY: status %s: Tx %s, Rx %s\n",
- res.toString(), resTx[0].toString(), resRx[0].toString());
- }
- final long t3 = BTUtils.currentTimeMillis();
-
- //
- // GATT Service Processing
- //
- try {
- final List<BTGattService> primServices = device.getGattServices();
- if( null == primServices || 0 == primServices.size() ) {
- // Cheating the flow, but avoiding: goto, do-while-false and lastly unreadable intendations
- // And it is an error case nonetheless ;-)
- throw new RuntimeException("Processing Ready Device: getServices() failed " + device.toString());
- }
- final long t5 = BTUtils.currentTimeMillis();
- {
- final long td00 = device.getLastDiscoveryTimestamp() - timestamp_t0; // adapter-init to discovered
- final long td01 = t1 - timestamp_t0; // adapter-init to processing-start
- final long td05 = t5 - timestamp_t0; // adapter-init -> gatt-complete
- final long tdc1 = t1 - device.getLastDiscoveryTimestamp(); // discovered to processing-start
- final long tdc5 = t5 - device.getLastDiscoveryTimestamp(); // discovered to gatt-complete
- final long td12 = t2 - t1; // SMPKeyBin
- final long td23 = t3 - t2; // LE_PHY
- final long td13 = t3 - t1; // SMPKeyBin + LE_PHY
- final long td35 = t5 - t3; // get-gatt-services
- BTUtils.println(System.err, System.lineSeparator()+System.lineSeparator());
- BTUtils.println(System.err, "PERF: GATT primary-services completed"+System.lineSeparator()+
- "PERF: adapter-init to discovered " + td00 + " ms,"+System.lineSeparator()+
- "PERF: adapter-init to processing-start " + td01 + " ms,"+System.lineSeparator()+
- "PERF: adapter-init to gatt-complete " + td05 + " ms,"+System.lineSeparator()+
- "PERF: discovered to processing-start " + tdc1 + " ms,"+System.lineSeparator()+
- "PERF: discovered to gatt-complete " + tdc5 + " ms,"+System.lineSeparator()+
- "PERF: SMPKeyBin + LE_PHY " + td13 + " ms (SMPKeyBin "+td12+"ms, LE_PHY "+td23+"ms), "+System.lineSeparator()+
- "PERF: get-gatt-services " + td35 + " ms,"+System.lineSeparator());
- }
-
- {
- final BTGattCmd cmd = new BTGattCmd(device, "TestCmd", null /* service_uuid */, DBTConstants.CommandUUID, DBTConstants.ResponseUUID);
- cmd.setVerbose(true);
- final boolean cmd_resolved = cmd.isResolved();
- BTUtils.println(System.err, "Client Command test: "+cmd.toString()+", resolved "+cmd_resolved);
- final byte[] cmd_data = { cmd_arg };
- final HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3000 /* timeoutMS */);
- if( HCIStatusCode.SUCCESS == cmd_res ) {
- final byte[] resp = cmd.getResponse();
- if( 1 == resp.length && resp[0] == cmd_arg ) {
- BTUtils.fprintf_td(System.err, "Client Success: %s -> %s (echo response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */));
- completedGATTCommands.incrementAndGet();
- } else {
- BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s (different response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */));
- }
- } else {
- BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s\n", cmd.toString(), cmd_res.toString());
- }
- cmd.close();
- }
-
- boolean gattListenerError = false;
- final List<BTGattCharListener> gattListener = new ArrayList<BTGattCharListener>();
- int loop = 0;
- do {
- try {
- int i=0;
- for(final Iterator<BTGattService> srvIter = primServices.iterator(); srvIter.hasNext(); i++) {
- final BTGattService primService = srvIter.next();
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, " [%02d] Service UUID %s\n", i, primService.getUUID());
- BTUtils.fprintf_td(System.err, " [%02d] %s\n", i, primService.toString());
- }
- int j=0;
- final List<BTGattChar> serviceCharacteristics = primService.getChars();
- for(final Iterator<BTGattChar> charIter = serviceCharacteristics.iterator(); charIter.hasNext(); j++) {
- final BTGattChar serviceChar = charIter.next();
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, " [%02d.%02d] Characteristic: UUID %s\n", i, j, serviceChar.getUUID());
- BTUtils.fprintf_td(System.err, " [%02d.%02d] %s\n", i, j, serviceChar.toString());
- }
- final GattCharPropertySet properties = serviceChar.getProperties();
- if( properties.isSet(GattCharPropertySet.Type.Read) ) {
- final byte[] value = serviceChar.readValue();
- final String svalue = BTUtils.decodeUTF8String(value, 0, value.length);
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, " [%02d.%02d] value: %s ('%s')\n", i, j, BTUtils.bytesHexString(value, 0, -1, true), svalue);
- }
- }
- int k=0;
- final List<BTGattDesc> charDescList = serviceChar.getDescriptors();
- for(final Iterator<BTGattDesc> descIter = charDescList.iterator(); descIter.hasNext(); k++) {
- final BTGattDesc charDesc = descIter.next();
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, " [%02d.%02d.%02d] Descriptor: UUID %s\n", i, j, k, charDesc.getUUID());
- BTUtils.fprintf_td(System.err, " [%02d.%02d.%02d] %s\n", i, j, k, charDesc.toString());
- }
- }
- if( 0 == loop ) {
- final boolean cccdEnableResult[] = { false, false };
- if( serviceChar.enableNotificationOrIndication( cccdEnableResult ) ) {
- // ClientCharConfigDescriptor (CCD) is available
- final MyGATTEventListener gattEventListener = new MyGATTEventListener();
- final boolean clAdded = serviceChar.addCharListener( gattEventListener );
- if( clAdded ) {
- gattListener.add(gattEventListener);
- } else {
- gattListenerError = true;
- BTUtils.fprintf_td(System.err, "Client Error: Failed to add GattListener: %s @ %s, gattListener %d\n",
- gattEventListener.toString(), serviceChar.toString(), gattListener.size());
- }
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, " [%02d.%02d] Characteristic-Listener: Notification(%b), Indication(%b): Added %b\n",
- i, j, cccdEnableResult[0], cccdEnableResult[1], clAdded);
- BTUtils.fprintf_td(System.err, "\n");
- }
- }
- }
- }
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "\n");
- }
- }
- success = notificationsReceived.get() >= 2 || indicationsReceived.get() >= 2;
- ++loop;
- } catch( final Exception ex) {
- BTUtils.println(System.err, "****** Client Processing Ready Device: Exception.2 caught for " + device.toString() + ": "+ex.getMessage());
- ex.printStackTrace();
- }
- } while( !success && device.getConnected() && !gattListenerError );
-
- if( gattListenerError ) {
- success = false;
- }
- {
- int i = 0;
- for(final BTGattCharListener gcl : gattListener) {
- if( !device.removeCharListener(gcl) ) {
- BTUtils.fprintf_td(System.err, "Client Error: Failed to remove GattListener[%d/%d]: %s @ %s\n",
- i, gattListener.size(), gcl.toString(), device.toString());
- success = false;
- }
- ++i;
- }
- }
-
- if( device.getConnected() ) {
- // Tell server we have successfully completed the test.
- final BTGattCmd cmd = new BTGattCmd(device, "FinalHandshake", null /* service_uuid */, DBTConstants.CommandUUID, DBTConstants.ResponseUUID);
- cmd.setVerbose(true);
- final boolean cmd_resolved = cmd.isResolved();
- BTUtils.println(System.err, "Client FinalCommand test: "+cmd.toString()+", resolved "+cmd_resolved);
- final byte[] cmd_data = success ? DBTConstants.SuccessHandshakeCommandData : DBTConstants.FailHandshakeCommandData;
- final HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3000 /* timeoutMS */);
- if( HCIStatusCode.SUCCESS == cmd_res ) {
- final byte[] resp = cmd.getResponse();
- if( Arrays.equals(cmd_data, resp) ) {
- BTUtils.fprintf_td(System.err, "Client Success: %s -> %s (echo response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */));
- } else {
- BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s (different response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */));
- success = false;
- }
- } else {
- BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s\n", cmd.toString(), cmd_res.toString());
- success = false;
- }
- cmd.close();
- }
- } catch (final Throwable t ) {
- BTUtils.println(System.err, "****** Client Processing Ready Device: Exception.2 caught for " + device.toString() + ": "+t.getMessage());
- t.printStackTrace();
- }
-
- BTUtils.println(System.err, "****** Client Processing Ready Device: End-1: Success " + success +
- " on " + device.toString() + "; devInProc "+BTDeviceRegistry.getProcessingDeviceCount());
-
- BTDeviceRegistry.removeFromProcessingDevices( device.getAddressAndType() );
-
- if( DiscoveryPolicy.PAUSE_CONNECTED_UNTIL_DISCONNECTED == discoveryPolicy ) {
- device.getAdapter().removeDevicePausingDiscovery(device);
- }
-
- BTUtils.println(System.err, "****** Client Processing Ready Device: End-2: Success " + success +
- " on " + device.toString() + "; devInProc "+BTDeviceRegistry.getProcessingDeviceCount());
- if( success ) {
- BTDeviceRegistry.addToProcessedDevices(device.getAddressAndType(), device.getName());
- }
- device.removeAllCharListener();
-
- if( !KEEP_CONNECTED ) {
- if( REMOVE_DEVICE ) {
- device.remove();
- } else {
- device.disconnect();
- }
- }
-
- completedMeasurementsTotal.addAndGet(1);
- if( success ) {
- completedMeasurementsSuccess.addAndGet(1);
- }
- if( 0 < measurementsLeft.get() ) {
- measurementsLeft.decrementAndGet();
- }
- BTUtils.println(System.err, "****** Client Processing Ready Device: Success "+success+
- "; Measurements completed "+completedMeasurementsSuccess.get()+
- ", left "+measurementsLeft.get()+
- "; Received notitifications "+notificationsReceived.get()+", indications "+indicationsReceived.get()+
- "; Completed GATT commands "+completedGATTCommands.get()+
- ": "+device.getAddressAndType());
- }
-
- private void removeDevice(final BTDevice device) {
- BTUtils.println(System.err, "****** Client Remove Device: removing: "+device.getAddressAndType());
-
- BTDeviceRegistry.removeFromProcessingDevices(device.getAddressAndType());
-
- if( REMOVE_DEVICE ) {
- device.remove();
- }
- }
-
- static final boolean le_scan_active = true; // default value
- static final short le_scan_interval = (short)24; // 15ms, default value
- static final short le_scan_window = (short)24; // 15ms, default value
- static final byte filter_policy = (byte)0; // default value
- static final boolean filter_dup = true; // default value
-
- @Override
- public HCIStatusCode startDiscovery(final String msg) {
- resetLastProcessingStats();
-
- final HCIStatusCode status = clientAdapter.startDiscovery( discoveryPolicy, le_scan_active, le_scan_interval, le_scan_window, filter_policy, filter_dup );
- BTUtils.println(System.err, "****** Client Start discovery ("+msg+") result: "+status);
- return status;
- }
-
- @Override
- public HCIStatusCode stopDiscovery(final String msg) {
- final HCIStatusCode status = clientAdapter.stopDiscovery();
- BTUtils.println(System.err, "****** Client Stop discovery ("+msg+") result: "+status);
- return status;
- }
-
- @Override
- public void close(final String msg) {
- BTUtils.println(System.err, "****** Client Close: "+msg);
- clientAdapter.stopDiscovery();
- clientAdapter.removeStatusListener( myAdapterStatusListener );
- }
-
- @Override
- public boolean initAdapter(final BTAdapter adapter) {
- if( !useAdapter.equals(EUI48.ALL_DEVICE) && !useAdapter.equals(adapter.getAddressAndType().address) ) {
- BTUtils.fprintf_td(System.err, "initClientAdapter: Adapter not selected: %s\n", adapter.toString());
- return false;
- }
- adapterName = adapterName + "-" + adapter.getAddressAndType().address.toString().replace(":", "");
-
- // Initialize with defaults and power-on
- if( !adapter.isInitialized() ) {
- final HCIStatusCode status = adapter.initialize( btMode );
- if( HCIStatusCode.SUCCESS != status ) {
- BTUtils.fprintf_td(System.err, "initClientAdapter: Adapter initialization failed: %s: %s\n",
- status.toString(), adapter.toString());
- return false;
- }
- } else if( !adapter.setPowered( true ) ) {
- BTUtils.fprintf_td(System.err, "initClientAdapter: Already initialized adapter power-on failed:: %s\n", adapter.toString());
- return false;
- }
- // adapter is powered-on
- BTUtils.fprintf_td(System.err, "initClientAdapter.1: %s\n", adapter.toString());
-
- if( adapter.setPowered(false) ) {
- final HCIStatusCode status = adapter.setName(adapterName, adapterShortName);
- if( HCIStatusCode.SUCCESS == status ) {
- BTUtils.fprintf_td(System.err, "initClientAdapter: setLocalName OK: %s\n", adapter.toString());
- } else {
- BTUtils.fprintf_td(System.err, "initClientAdapter: setLocalName failed: %s\n", adapter.toString());
- return false;
- }
- if( !adapter.setPowered( true ) ) {
- BTUtils.fprintf_td(System.err, "initClientAdapter: setPower.2 on failed: %s\n", adapter.toString());
- return false;
- }
- } else {
- BTUtils.fprintf_td(System.err, "initClientAdapter: setPowered.2 off failed: %s\n", adapter.toString());
- }
- // adapter is powered-on
- BTUtils.println(System.err, "initClientAdapter.2: "+adapter.toString());
-
- {
- final LE_Features le_feats = adapter.getLEFeatures();
- BTUtils.fprintf_td(System.err, "initClientAdapter: LE_Features %s\n", le_feats.toString());
- }
- if( adapter.getBTMajorVersion() > 4 ) {
- // BT5 specific
- final LE_PHYs Tx = new LE_PHYs(LE_PHYs.PHY.LE_2M);
- final LE_PHYs Rx = new LE_PHYs(LE_PHYs.PHY.LE_2M);
-
- final HCIStatusCode res = adapter.setDefaultLE_PHY(Tx, Rx);
- BTUtils.fprintf_td(System.err, "initClientAdapter: Set Default LE PHY: status %s: Tx %s, Rx %s\n",
- res.toString(), Tx.toString(), Rx.toString());
- }
- adapter.addStatusListener( myAdapterStatusListener );
-
- return true;
- }
-}
diff --git a/trial/java/trial/org/direct_bt/DBTClient01.java b/trial/java/trial/org/direct_bt/DBTClient01.java
index 22d905e3..4f239afd 100644
--- a/trial/java/trial/org/direct_bt/DBTClient01.java
+++ b/trial/java/trial/org/direct_bt/DBTClient01.java
@@ -70,6 +70,8 @@ public class DBTClient01 implements DBTClientTest {
private final MyAdapterStatusListener myAdapterStatusListener = new MyAdapterStatusListener();
+ private final byte cmd_arg = (byte)0x44;
+
private String adapterName = "TestDev2_Clt";
private EUI48 useAdapter = EUI48.ALL_DEVICE;
private BTMode btMode = BTMode.DUAL;
@@ -86,6 +88,7 @@ public class DBTClient01 implements DBTClientTest {
private final AtomicInteger deviceReadyCount = new AtomicInteger(0);
private final AtomicInteger notificationsReceived = new AtomicInteger(0);
private final AtomicInteger indicationsReceived = new AtomicInteger(0);
+ private final AtomicInteger completedGATTCommands = new AtomicInteger(0);
private final AtomicInteger completedMeasurementsTotal = new AtomicInteger(0);
private final AtomicInteger completedMeasurementsSuccess = new AtomicInteger(0);
@@ -342,6 +345,7 @@ public class DBTClient01 implements DBTClientTest {
}
private void resetLastProcessingStats() {
+ completedGATTCommands.set(0);
notificationsReceived.set(0);
indicationsReceived.set(0);
}
@@ -447,6 +451,27 @@ public class DBTClient01 implements DBTClientTest {
"PERF: get-gatt-services " + td35 + " ms,"+System.lineSeparator());
}
+ {
+ final BTGattCmd cmd = new BTGattCmd(device, "TestCmd", null /* service_uuid */, DBTConstants.CommandUUID, DBTConstants.ResponseUUID);
+ cmd.setVerbose(true);
+ final boolean cmd_resolved = cmd.isResolved();
+ BTUtils.println(System.err, "Client Command test: "+cmd.toString()+", resolved "+cmd_resolved);
+ final byte[] cmd_data = { cmd_arg };
+ final HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3000 /* timeoutMS */);
+ if( HCIStatusCode.SUCCESS == cmd_res ) {
+ final byte[] resp = cmd.getResponse();
+ if( 1 == resp.length && resp[0] == cmd_arg ) {
+ BTUtils.fprintf_td(System.err, "Client Success: %s -> %s (echo response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */));
+ completedGATTCommands.incrementAndGet();
+ } else {
+ BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s (different response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */));
+ }
+ } else {
+ BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s\n", cmd.toString(), cmd_res.toString());
+ }
+ cmd.close();
+ }
+
boolean gattListenerError = false;
final List<BTGattCharListener> gattListener = new ArrayList<BTGattCharListener>();
int loop = 0;
@@ -517,6 +542,8 @@ public class DBTClient01 implements DBTClientTest {
}
} while( !success && device.getConnected() && !gattListenerError );
+ success = success && completedGATTCommands.get() >= 1;
+
if( gattListenerError ) {
success = false;
}
@@ -589,6 +616,7 @@ public class DBTClient01 implements DBTClientTest {
"; Measurements completed "+completedMeasurementsSuccess.get()+
", left "+measurementsLeft.get()+
"; Received notitifications "+notificationsReceived.get()+", indications "+indicationsReceived.get()+
+ "; Completed GATT commands "+completedGATTCommands.get()+
": "+device.getAddressAndType());
}
diff --git a/trial/java/trial/org/direct_bt/DBTClientServer1x.java b/trial/java/trial/org/direct_bt/DBTClientServer1x.java
index 823aed8d..0a15b68f 100644
--- a/trial/java/trial/org/direct_bt/DBTClientServer1x.java
+++ b/trial/java/trial/org/direct_bt/DBTClientServer1x.java
@@ -72,8 +72,8 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer {
final boolean serverSC, final BTSecurityLevel secLevelServer, final ExpectedPairing serverExpPairing,
final BTSecurityLevel secLevelClient, final ExpectedPairing clientExpPairing)
{
- final DBTServer00 server = new DBTServer00("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, secLevelServer);
- final DBTClient00 client = new DBTClient00("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL);
+ final DBTServer01 server = new DBTServer01("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, secLevelServer, false /* do_disconnect */);
+ final DBTClient01 client = new DBTClient01("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, false /* do_disconnect */);
test8x_fullCycle(timeout_value, suffix,
protocolSessionCount, DBTConstants.max_connections_per_session, true /* expSuccess */,
server_client_order,
diff --git a/trial/java/trial/org/direct_bt/DBTServer00.java b/trial/java/trial/org/direct_bt/DBTServer00.java
deleted file mode 100644
index 5d5ec583..00000000
--- a/trial/java/trial/org/direct_bt/DBTServer00.java
+++ /dev/null
@@ -1,814 +0,0 @@
-/**
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2022 Gothel Software e.K.
- *
- * 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.
- */
-
-package trial.org.direct_bt;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.direct_bt.AdapterSettings;
-import org.direct_bt.AdapterStatusListener;
-import org.direct_bt.BDAddressAndType;
-import org.direct_bt.BTMode;
-import org.direct_bt.BTSecurityLevel;
-import org.direct_bt.BTAdapter;
-import org.direct_bt.BTDevice;
-import org.direct_bt.BTDeviceRegistry;
-import org.direct_bt.BTSecurityRegistry;
-import org.direct_bt.BTUtils;
-import org.direct_bt.DBGattChar;
-import org.direct_bt.DBGattDesc;
-import org.direct_bt.DBGattServer;
-import org.direct_bt.DBGattService;
-import org.direct_bt.DBGattValue;
-import org.direct_bt.DiscoveryPolicy;
-import org.direct_bt.EIRDataTypeSet;
-import org.direct_bt.EInfoReport;
-import org.direct_bt.GAPFlags;
-import org.direct_bt.GattCharPropertySet;
-import org.direct_bt.HCIStatusCode;
-import org.direct_bt.LE_Features;
-import org.direct_bt.LE_PHYs;
-import org.direct_bt.PairingMode;
-import org.direct_bt.SMPIOCapability;
-import org.direct_bt.SMPPairingState;
-import org.direct_bt.ScanType;
-import org.jau.net.EUI48;
-
-/**
- * This peripheral BTRole::Slave test participant works with DBTClient00.
- */
-public class DBTServer00 implements DBTServerTest {
- final boolean GATT_VERBOSE = false;
- private final String adapterShortName = "TDev1Srv";
-
- private final boolean SHOW_UPDATE_EVENTS = false;
-
- private String adapterName = "TestDev1_Srv";
- private EUI48 useAdapter = EUI48.ALL_DEVICE;
- private BTMode btMode = BTMode.DUAL;
- private boolean use_SC = true;
- private BTSecurityLevel adapterSecurityLevel = BTSecurityLevel.UNSET;
- private final MyAdapterStatusListener myAdapterStatusListener = new MyAdapterStatusListener();
- private final MyGATTServerListener gattServerListener = new MyGATTServerListener();
- private BTAdapter serverAdapter = null;
- private final Object sync_lock = new Object();
- private volatile BTDevice connectedDevice;
-
- private final AtomicInteger disconnectCount = new AtomicInteger(0);
- private final AtomicInteger servedProtocolSessionsTotal = new AtomicInteger(0);
- private final AtomicInteger servedProtocolSessionsSuccess = new AtomicInteger(0);
- private final AtomicInteger servingProtocolSessionsLeft = new AtomicInteger(1);
-
- public DBTServer00(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean use_SC, final BTSecurityLevel adapterSecurityLevel) {
- this.adapterName = adapterName;
- this.useAdapter = useAdapter;
- this.btMode = btMode;
- this.use_SC = use_SC;
- this.adapterSecurityLevel = adapterSecurityLevel;
-
- dbGattServer.addListener( gattServerListener );
- }
- public DBTServer00(final String adapterName, final EUI48 useAdapter, final BTSecurityLevel adapterSecurityLevel) {
- this(adapterName, useAdapter, BTMode.DUAL, true /* SC */, adapterSecurityLevel);
- }
- public DBTServer00(final String adapterName, final BTSecurityLevel adapterSecurityLevel) {
- this(adapterName, EUI48.ALL_DEVICE, BTMode.DUAL, true /* SC */, adapterSecurityLevel);
- }
-
- @Override
- public String getName() { return adapterName; }
-
- @Override
- public BTSecurityLevel getSecurityLevel() { return adapterSecurityLevel; }
-
- @Override
- public void setAdapter(final BTAdapter serverAdapter) {
- this.serverAdapter = serverAdapter;
- }
- @Override
- public BTAdapter getAdapter() { return serverAdapter; }
-
- @Override
- public void setProtocolSessionsLeft(final int v) {
- servingProtocolSessionsLeft.set(v);
- }
- @Override
- public int getProtocolSessionsLeft() {
- return servingProtocolSessionsLeft.get();
- }
- @Override
- public int getProtocolSessionsDoneTotal() {
- return servedProtocolSessionsTotal.get();
- }
- @Override
- public int getProtocolSessionsDoneSuccess() {
- return servedProtocolSessionsSuccess.get();
- }
- @Override
- public int getDisconnectCount() {
- return this.disconnectCount.get();
- }
-
- private final void setDevice(final BTDevice cd) {
- synchronized( sync_lock ) {
- connectedDevice = cd;
- }
- }
-
- private final BTDevice getDevice() {
- synchronized( sync_lock ) {
- return connectedDevice;
- }
- }
-
- private boolean matches(final BTDevice device) {
- final BTDevice d = getDevice();
- return null != d ? d.equals(device) : false;
- }
-
- static Thread executeOffThread(final Runnable runobj, final String threadName, final boolean detach) {
- final Thread t = new Thread( runobj, threadName );
- t.setDaemon( detach );
- t.start();
- return t;
- }
- static Thread executeOffThread(final Runnable runobj, final boolean detach) {
- final Thread t = new Thread( runobj );
- t.setDaemon( detach );
- t.start();
- return t;
- }
-
- static DBGattValue make_gvalue(final String name) {
- final byte[] p = name.getBytes(StandardCharsets.UTF_8);
- return new DBGattValue(p, p.length);
- }
- static DBGattValue make_gvalue(final String name, final int capacity) {
- final byte[] p = name.getBytes(StandardCharsets.UTF_8);
- return new DBGattValue(p, Math.max(capacity, p.length), capacity > p.length/* variable_length */);
- }
- static DBGattValue make_gvalue(final short v) {
- final byte[] p = { (byte)0, (byte)0 };
- p[0] = (byte)(v);
- p[1] = (byte)(v >> 8);
- return new DBGattValue(p, p.length);
- }
- static DBGattValue make_gvalue(final int capacity, final int size) {
- final byte[] p = new byte[size];
- return new DBGattValue(p, capacity, true /* variable_length */);
- }
-
- // DBGattServerRef dbGattServer = std::make_shared<DBGattServer>(
- private final DBGattServer dbGattServer = new DBGattServer(
- /* services: */
- Arrays.asList( // DBGattService
- new DBGattService ( true /* primary */,
- DBGattService.UUID16.GENERIC_ACCESS /* type_ */,
- Arrays.asList( // DBGattChar
- new DBGattChar( DBGattChar.UUID16.DEVICE_NAME /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue(adapterName, 128) /* value */ ),
- new DBGattChar( DBGattChar.UUID16.APPEARANCE /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue((short)0) /* value */ )
- ) ),
- new DBGattService ( true /* primary */,
- DBGattService.UUID16.DEVICE_INFORMATION /* type_ */,
- Arrays.asList( // DBGattChar
- new DBGattChar( DBGattChar.UUID16.MANUFACTURER_NAME_STRING /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue("Gothel Software") /* value */ ),
- new DBGattChar( DBGattChar.UUID16.MODEL_NUMBER_STRING /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue("2.4.0-pre") /* value */ ),
- new DBGattChar( DBGattChar.UUID16.SERIAL_NUMBER_STRING /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue("sn:0123456789") /* value */ ),
- new DBGattChar( DBGattChar.UUID16.HARDWARE_REVISION_STRING /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue("hw:0123456789") /* value */ ),
- new DBGattChar( DBGattChar.UUID16.FIRMWARE_REVISION_STRING /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue("fw:0123456789") /* value */ ),
- new DBGattChar( DBGattChar.UUID16.SOFTWARE_REVISION_STRING /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- new ArrayList<DBGattDesc>(/* intentionally w/o Desc */ ),
- make_gvalue("sw:0123456789") /* value */ )
- ) ),
- new DBGattService ( true /* primary */,
- DBTConstants.DataServiceUUID /* type_ */,
- Arrays.asList( // DBGattChar
- new DBGattChar( DBTConstants.StaticDataUUID /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Read),
- Arrays.asList( // DBGattDesc
- new DBGattDesc( DBGattDesc.UUID16.USER_DESC, make_gvalue("DATA_STATIC") )
- ),
- make_gvalue("Proprietary Static Data 0x00010203") /* value */ ),
- new DBGattChar( DBTConstants.CommandUUID /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.WriteNoAck).set(GattCharPropertySet.Type.WriteWithAck),
- Arrays.asList( // DBGattDesc
- new DBGattDesc( DBGattDesc.UUID16.USER_DESC, make_gvalue("COMMAND") )
- ),
- make_gvalue(128, 64) /* value */ ),
- new DBGattChar( DBTConstants.ResponseUUID /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Notify).set(GattCharPropertySet.Type.Indicate),
- Arrays.asList( // DBGattDesc
- new DBGattDesc( DBGattDesc.UUID16.USER_DESC, make_gvalue("RESPONSE") ),
- DBGattDesc.createClientCharConfig()
- ),
- make_gvalue((short)0) /* value */ ),
- new DBGattChar( DBTConstants.PulseDataUUID /* value_type_ */,
- new GattCharPropertySet(GattCharPropertySet.Type.Notify).set(GattCharPropertySet.Type.Indicate),
- Arrays.asList( // DBGattDesc
- new DBGattDesc( DBGattDesc.UUID16.USER_DESC, make_gvalue("DATA_PULSE") ),
- DBGattDesc.createClientCharConfig()
- ),
- make_gvalue("Synthethic Sensor 01") /* value */ )
- ) )
- ) );
-
-
- class MyAdapterStatusListener extends AdapterStatusListener {
- @Override
- public void adapterSettingsChanged(final BTAdapter adapter, final AdapterSettings oldmask,
- final AdapterSettings newmask, final AdapterSettings changedmask, final long timestamp) {
- final boolean initialSetting = oldmask.isEmpty();
- if( initialSetting ) {
- BTUtils.println(System.err, "****** Server SETTINGS: "+oldmask+" -> "+newmask+", initial "+changedmask);
- } else {
- BTUtils.println(System.err, "****** Server SETTINGS: "+oldmask+" -> "+newmask+", changed "+changedmask);
- }
- BTUtils.println(System.err, "Server Status Adapter:");
- BTUtils.println(System.err, adapter.toString());
- }
-
- @Override
- public void discoveringChanged(final BTAdapter adapter, final ScanType currentMeta, final ScanType changedType, final boolean changedEnabled, final DiscoveryPolicy policy, final long timestamp) {
- BTUtils.println(System.err, "****** Server DISCOVERING: meta "+currentMeta+", changed["+changedType+", enabled "+changedEnabled+", policy "+policy+"] on "+adapter);
- }
-
- @Override
- public boolean deviceFound(final BTDevice device, final long timestamp) {
- BTUtils.println(System.err, "****** Server FOUND__-1: NOP "+device.toString());
- return false;
- }
-
- @Override
- public void deviceUpdated(final BTDevice device, final EIRDataTypeSet updateMask, final long timestamp) {
- if( SHOW_UPDATE_EVENTS ) {
- BTUtils.println(System.err, "****** Server UPDATED: "+updateMask+" of "+device);
- }
- }
-
- @Override
- public void deviceConnected(final BTDevice device, final boolean discovered, final long timestamp) {
- BTUtils.println(System.err, "****** Server CONNECTED (served "+disconnectCount.get()+", left "+servingProtocolSessionsLeft.get()+"): discovered "+discovered+": "+device+" on "+device.getAdapter());
- final boolean available = null == getDevice();
- if( available ) {
- setDevice(device);
- BTDeviceRegistry.addToProcessingDevices(device.getAddressAndType(), device.getName());
- }
- }
-
- @Override
- public void devicePairingState(final BTDevice device, final SMPPairingState state, final PairingMode mode, final long timestamp) {
- BTUtils.println(System.err, "****** Server PAIRING_STATE: state "+state+", mode "+mode+": "+device);
- switch( state ) {
- case NONE:
- // next: deviceReady(..)
- break;
- case FAILED: {
- // next: deviceReady() or deviceDisconnected(..)
- } break;
- case REQUESTED_BY_RESPONDER:
- // next: FEATURE_EXCHANGE_STARTED
- break;
- case FEATURE_EXCHANGE_STARTED:
- // next: FEATURE_EXCHANGE_COMPLETED
- break;
- case FEATURE_EXCHANGE_COMPLETED:
- // next: PASSKEY_EXPECTED... or KEY_DISTRIBUTION
- break;
- case PASSKEY_EXPECTED: {
- final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address, "");
- if( null != sec && sec.getPairingPasskey() != BTSecurityRegistry.NO_PASSKEY ) {
- executeOffThread( () -> { device.setPairingPasskey( sec.getPairingPasskey() ); }, "DBT-SetPasskey-"+device.getAddressAndType(), true /* detach */);
- } else {
- executeOffThread( () -> { device.setPairingPasskey( 0 ); }, "DBT-SetPasskey-"+device.getAddressAndType(), true /* detach */);
- // 3s disconnect: executeOffThread( () -> { device.setPairingPasskeyNegative(); }, "DBT-SetPasskeyNegative-"+device.getAddressAndType(), true /* detach */);
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case NUMERIC_COMPARE_EXPECTED: {
- final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address, "");
- if( null != sec ) {
- executeOffThread( () -> { device.setPairingNumericComparison( sec.getPairingNumericComparison() ); }, "DBT-SetNumericComp-"+device.getAddressAndType(), true /* detach */);
- } else {
- executeOffThread( () -> { device.setPairingNumericComparison( false ); }, "DBT-SetNumericCompFalse-"+device.getAddressAndType(), true /* detach */);
- }
- // next: KEY_DISTRIBUTION or FAILED
- } break;
- case OOB_EXPECTED:
- // FIXME: ABORT
- break;
- case KEY_DISTRIBUTION:
- // next: COMPLETED or FAILED
- break;
- case COMPLETED:
- // next: deviceReady(..)
- break;
- default: // nop
- break;
- }
- }
-
- @Override
- public void deviceReady(final BTDevice device, final long timestamp) {
- BTUtils.println(System.err, "****** Server READY-1: NOP " + device.toString());
- }
-
- @Override
- public void deviceDisconnected(final BTDevice device, final HCIStatusCode reason, final short handle, final long timestamp) {
- BTUtils.println(System.err, "****** Server DISCONNECTED (served "+(1+disconnectCount.get())+", left "+servingProtocolSessionsLeft.get()+"): Reason "+reason+", old handle 0x"+Integer.toHexString(handle)+": "+device+" on "+device.getAdapter());
- final boolean match = matches(device);
- if( match ) {
- setDevice(null);
- }
- executeOffThread( () -> { processDisconnectedDevice(device); },
- "Server DBT-Disconnected-"+device.getAdapter().getAddressAndType(), true /* detach */);
- }
-
- @Override
- public String toString() {
- return "Server AdapterStatusListener[user, per-adapter]";
- }
- };
-
- class MyGATTServerListener extends DBGattServer.Listener implements AutoCloseable {
- private final Thread pulseSenderThread;
- private volatile boolean stopPulseSenderFlag = false;
-
- private volatile short handlePulseDataNotify = 0;
- private volatile short handlePulseDataIndicate = 0;
- private volatile short handleResponseDataNotify = 0;
- private volatile short handleResponseDataIndicate = 0;
-
- private int usedMTU = 23; // BTGattHandler::number(BTGattHandler::Defaults::MIN_ATT_MTU);
-
- private void clear() {
- synchronized( sync_lock ) {
- handlePulseDataNotify = 0;
- handlePulseDataIndicate = 0;
- handleResponseDataNotify = 0;
- handleResponseDataIndicate = 0;
-
- dbGattServer.resetGattClientCharConfig(DBTConstants.DataServiceUUID, DBTConstants.PulseDataUUID);
- dbGattServer.resetGattClientCharConfig(DBTConstants.DataServiceUUID, DBTConstants.ResponseUUID);
- }
- }
-
- private boolean shallStopPulseSender() {
- synchronized( sync_lock ) {
- return stopPulseSenderFlag;
- }
- }
- private void pulseSender() {
- {
- final BTDevice connectedDevice_ = getDevice();
- final String connectedDeviceStr = null != connectedDevice_ ? connectedDevice_.toString() : "n/a";
- BTUtils.fprintf_td(System.err, "****** Server GATT::PULSE Start %s\n", connectedDeviceStr);
- }
- while( !shallStopPulseSender() ) {
- final BTDevice connectedDevice_ = getDevice();
- if( null != connectedDevice_ && connectedDevice_.getConnected() ) {
- if( 0 != handlePulseDataNotify || 0 != handlePulseDataIndicate ) {
- final String data = String.format("Dynamic Data Example. Elapsed Milliseconds: %,9d", BTUtils.elapsedTimeMillis());
- final byte[] v = data.getBytes(StandardCharsets.UTF_8);
- if( 0 != handlePulseDataNotify ) {
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::sendNotification: PULSE to %s\n", connectedDevice_.toString());
- }
- connectedDevice_.sendNotification(handlePulseDataNotify, v);
- }
- if( 0 != handlePulseDataIndicate ) {
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::sendIndication: PULSE to %s\n", connectedDevice_.toString());
- }
- connectedDevice_.sendIndication(handlePulseDataIndicate, v);
- }
- }
- }
- if( !shallStopPulseSender() ) {
- try {
- Thread.sleep(100); // 100ms
- } catch (final InterruptedException e) { }
- }
- }
- {
- final BTDevice connectedDevice_ = getDevice();
- final String connectedDeviceStr = null != connectedDevice_ ? connectedDevice_.toString() : "n/a";
- BTUtils.fprintf_td(System.err, "****** Server GATT::PULSE End %s\n", connectedDeviceStr);
- }
- }
-
- private void sendResponse(final byte[] data) {
- final BTDevice connectedDevice_ = getDevice();
- if( null != connectedDevice_ && connectedDevice_.getConnected() ) {
- if( 0 != handleResponseDataNotify || 0 != handleResponseDataIndicate ) {
- if( 0 != handleResponseDataNotify ) {
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::sendNotification: %s to %s\n",
- BTUtils.bytesHexString(data, 0, data.length, true /* lsb */), connectedDevice_.toString());
- }
- connectedDevice_.sendNotification(handleResponseDataNotify, data);
- }
- if( 0 != handleResponseDataIndicate ) {
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::sendIndication: %s to %s\n",
- BTUtils.bytesHexString(data, 0, data.length, true /* lsb */), connectedDevice_.toString());
- }
- connectedDevice_.sendIndication(handleResponseDataIndicate, data);
- }
- }
- }
- }
-
- public MyGATTServerListener() {
- pulseSenderThread = executeOffThread( () -> { pulseSender(); }, "GattServer-PulseSender", false /* detach */);
- }
-
- @Override
- public void close() {
- synchronized( sync_lock ) {
- clear();
- stopPulseSenderFlag = true;
- }
- try {
- pulseSenderThread.join(1000);
- } catch (final InterruptedException e) { }
- super.close();
- }
-
- @Override
- public void connected(final BTDevice device, final int initialMTU) {
- final boolean match = matches(device);
- BTUtils.fprintf_td(System.err, "****** Server GATT::connected(match %b): initMTU %d, %s\n",
- match, initialMTU, device.toString());
- if( match ) {
- synchronized( sync_lock ) {
- usedMTU = initialMTU;
- }
- }
- }
-
- @Override
- public void disconnected(final BTDevice device) {
- final boolean match = matches(device);
- BTUtils.fprintf_td(System.err, "****** Server GATT::disconnected(match %b): %s\n", match, device.toString());
- if( match ) {
- clear();
- }
- }
-
- @Override
- public void mtuChanged(final BTDevice device, final int mtu) {
- final boolean match = matches(device);
- final int usedMTU_old = usedMTU;
- if( match ) {
- synchronized( sync_lock ) {
- usedMTU = mtu;
- }
- }
- BTUtils.fprintf_td(System.err, "****** Server GATT::mtuChanged(match %b, served %d, left %d): %d -> %d, %s\n",
- match, servedProtocolSessionsTotal.get(), servingProtocolSessionsLeft.get(),
- match ? usedMTU_old : 0, mtu, device.toString());
- }
-
- @Override
- public boolean readCharValue(final BTDevice device, final DBGattService s, final DBGattChar c) {
- final boolean match = matches(device);
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::readCharValue(match %b): to %s, from\n %s\n %s\n",
- match, device.toString(), s.toString(), c.toString());
- }
- return match;
- }
-
- @Override
- public boolean readDescValue(final BTDevice device, final DBGattService s, final DBGattChar c, final DBGattDesc d) {
- final boolean match = matches(device);
- if( GATT_VERBOSE ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::readDescValue(match %b): to %s, from\n %s\n %s\n %s\n",
- match, device.toString(), s.toString(), c.toString(), d.toString());
- }
- return match;
- }
-
- @Override
- public boolean writeCharValue(final BTDevice device, final DBGattService s, final DBGattChar c, final byte[] value, final int value_offset) {
- final boolean match = matches(device);
- if( GATT_VERBOSE ) {
- final String value_s = BTUtils.bytesHexString(value, 0, value.length, true /* lsbFirst */)+
- " '"+BTUtils.decodeUTF8String(value, 0, value.length)+"'";
- BTUtils.fprintf_td(System.err, "****** Server GATT::writeCharValue(match %b): %s @ %d from %s, to\n %s\n %s\n",
- match, value_s, value_offset,
- device.toString(), s.toString(), c.toString());
- }
- return match;
- }
-
- @Override
- public void writeCharValueDone(final BTDevice device, final DBGattService s, final DBGattChar c) {
- final boolean match = matches(device);
- final DBGattValue value = c.getValue();
- final byte[] data = value.data();
- boolean isFinalHandshake = false;
- boolean isFinalHandshakeSuccess = false;
-
- if( match &&
- c.getValueType().equals( DBTConstants.CommandUUID ) &&
- ( 0 != handleResponseDataNotify || 0 != handleResponseDataIndicate ) )
- {
- isFinalHandshakeSuccess = Arrays.equals(DBTConstants.SuccessHandshakeCommandData, data);
- isFinalHandshake = isFinalHandshakeSuccess ||
- Arrays.equals(DBTConstants.FailHandshakeCommandData, data);
-
- if( isFinalHandshake ) {
- if( isFinalHandshakeSuccess ) {
- servedProtocolSessionsSuccess.addAndGet(1);
- }
- servedProtocolSessionsTotal.addAndGet(1); // we assume this to be server, i.e. connected, SMP done and GATT action ..
- if( servingProtocolSessionsLeft.get() > 0 ) {
- servingProtocolSessionsLeft.decrementAndGet();
- }
- }
- executeOffThread( () -> { sendResponse( data ); }, true /* detach */);
- }
- if( GATT_VERBOSE || isFinalHandshake ) {
- BTUtils.fprintf_td(System.err, "****** Server GATT::writeCharValueDone(match %b, finalCmd %b, sessions [%d ok / %d total], left %d): From %s, to\n %s\n %s\n Char-Value: %s\n",
- match, isFinalHandshake, servedProtocolSessionsSuccess.get(), servedProtocolSessionsTotal.get(), servingProtocolSessionsLeft.get(),
- device.toString(), s.toString(), c.toString(), value.toString());
- }
- }
-
- @Override
- public boolean writeDescValue(final BTDevice device, final DBGattService s, final DBGattChar c, final DBGattDesc d,
- final byte[] value, final int value_offset)
- {
- final boolean match = matches(device);
- if( GATT_VERBOSE ) {
- final String value_s = BTUtils.bytesHexString(value, 0, value.length, true /* lsbFirst */)+
- " '"+BTUtils.decodeUTF8String(value, 0, value.length)+"'";
- BTUtils.fprintf_td(System.err, "****** Server GATT::writeDescValue(match %b): %s @ %d from %s\n %s\n %s\n %s\n",
- match, value_s, value_offset,
- device.toString(), s.toString(), c.toString(), d.toString());
- }
- return match;
- }
-
- @Override
- public void writeDescValueDone(final BTDevice device, final DBGattService s, final DBGattChar c, final DBGattDesc d) {
- if( GATT_VERBOSE ) {
- final boolean match = matches(device);
- final DBGattValue value = d.getValue();
- BTUtils.fprintf_td(System.err, "****** Server GATT::writeDescValueDone(match %b): From %s\n %s\n %s\n %s\n Desc-Value: %s\n",
- match, device.toString(), s.toString(), c.toString(), d.toString(), value.toString());
- }
- }
-
- @Override
- public void clientCharConfigChanged(final BTDevice device, final DBGattService s, final DBGattChar c, final DBGattDesc d,
- final boolean notificationEnabled, final boolean indicationEnabled)
- {
- final boolean match = matches(device);
- if( GATT_VERBOSE ) {
- final DBGattValue value = d.getValue();
- BTUtils.fprintf_td(System.err, "****** Server GATT::clientCharConfigChanged(match %b): notify %b, indicate %b from %s\n %s\n %s\n %s\n Desc-Value: %s\n",
- match, notificationEnabled, indicationEnabled,
- device.toString(), s.toString(), c.toString(), d.toString(), value.toString());
- }
- if( match ) {
- final String value_type = c.getValueType();
- final short value_handle = c.getValueHandle();
- if( value_type.equals( DBTConstants.PulseDataUUID ) ) {
- synchronized( sync_lock ) {
- handlePulseDataNotify = notificationEnabled ? value_handle : 0;
- handlePulseDataIndicate = indicationEnabled ? value_handle : 0;
- }
- } else if( value_type.equals( DBTConstants.ResponseUUID ) ) {
- synchronized( sync_lock ) {
- handleResponseDataNotify = notificationEnabled ? value_handle : 0;
- handleResponseDataIndicate = indicationEnabled ? value_handle : 0;
- }
- }
- }
- }
- }
- static final short adv_interval_min=(short)160; // x0.625 = 100ms
- static final short adv_interval_max=(short)480; // x0.625 = 300ms
- static final byte adv_type=(byte)0; // AD_PDU_Type::ADV_IND;
- static final byte adv_chan_map=(byte)0x07;
- static final byte filter_policy=(byte)0x00;
-
- @Override
- public void close(final String msg) {
- BTUtils.println(System.err, "****** Server Close.0: "+msg);
- serverAdapter.removeStatusListener( myAdapterStatusListener );
- {
- stopAdvertising(msg);
- final BTDevice connectedDevice_ = getDevice();
- if( null != connectedDevice_ ) {
- setDevice(null);
- connectedDevice_.disconnect();
- }
- }
- gattServerListener.close();
- // dbGattServer.close(); // keep alive
- stopAdvertising(msg); // try once more in case of already started AdapterStatusListener
- BTUtils.println(System.err, "****** Server Close.X: "+msg);
- }
-
- private HCIStatusCode stopAdvertising(final String msg) {
- final HCIStatusCode status = serverAdapter.stopAdvertising();
- BTUtils.println(System.err, "****** Server Stop advertising ("+msg+") result: "+status+": "+serverAdapter.toString());
- return status;
- }
-
- @Override
- public HCIStatusCode startAdvertising(final String msg) {
- final EInfoReport eir = new EInfoReport();
- final EIRDataTypeSet adv_mask = new EIRDataTypeSet();
- final EIRDataTypeSet scanrsp_mask = new EIRDataTypeSet();
-
- adv_mask.set(EIRDataTypeSet.DataType.FLAGS);
- adv_mask.set(EIRDataTypeSet.DataType.SERVICE_UUID);
-
- scanrsp_mask.set(EIRDataTypeSet.DataType.NAME);
- scanrsp_mask.set(EIRDataTypeSet.DataType.CONN_IVAL);
-
- eir.addFlag(GAPFlags.Bit.LE_Gen_Disc);
- eir.addFlag(GAPFlags.Bit.BREDR_UNSUP);
-
- eir.addService(DBTConstants.DataServiceUUID);
- eir.setServicesComplete(false);
-
- eir.setName(serverAdapter.getName());
- eir.setConnInterval((short)8, (short)12); // 10ms - 15ms
-
- final DBGattChar gattDevNameChar = dbGattServer.findGattChar(DBGattService.UUID16.GENERIC_ACCESS, DBGattChar.UUID16.DEVICE_NAME);
- if( null != gattDevNameChar ) {
- final byte[] aname_bytes = serverAdapter.getName().getBytes(StandardCharsets.UTF_8);
- gattDevNameChar.setValue(aname_bytes, 0, aname_bytes.length, 0);
- }
-
- BTUtils.println(System.err, "****** Server Start advertising ("+msg+"): EIR "+eir.toString());
- BTUtils.println(System.err, "****** Server Start advertising ("+msg+"): adv "+adv_mask.toString()+", scanrsp "+scanrsp_mask.toString());
-
- final HCIStatusCode status = serverAdapter.startAdvertising(dbGattServer, eir, adv_mask, scanrsp_mask,
- adv_interval_min, adv_interval_max,
- adv_type, adv_chan_map, filter_policy);
- BTUtils.println(System.err, "****** Server Start advertising ("+msg+") result: "+status+": "+serverAdapter.toString());
- if( GATT_VERBOSE ) {
- BTUtils.println(System.err, dbGattServer.toFullString());
- }
- return status;
- }
-
- private void processDisconnectedDevice(final BTDevice device) {
- BTUtils.println(System.err, "****** Server Disconnected Device (count "+(1+disconnectCount.get())+
- ", served "+servedProtocolSessionsTotal.get()+", left "+servingProtocolSessionsLeft.get()+"): Start "+device.toString());
-
- // already unpaired
- stopAdvertising("device-disconnected");
- device.remove();
- BTDeviceRegistry.removeFromProcessingDevices(device.getAddressAndType());
-
- disconnectCount.addAndGet(1);
-
- try {
- Thread.sleep(100); // wait a little (FIXME: Fast restart of advertising error)
- } catch (final InterruptedException e) { }
-
- if( servingProtocolSessionsLeft.get() > 0 ) {
- startAdvertising("device-disconnected");
- }
-
- BTUtils.println(System.err, "****** Server Disonnected Device: End "+device.toString());
- }
-
- @Override
- public boolean initAdapter(final BTAdapter adapter) {
- if( !useAdapter.equals(EUI48.ALL_DEVICE) && !useAdapter.equals(adapter.getAddressAndType().address) ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: Adapter not selected: %s\n", adapter.toString());
- return false;
- }
- adapterName = adapterName + "-" + adapter.getAddressAndType().address.toString().replace(":", "");
-
- if( !adapter.isInitialized() ) {
- // Initialize with defaults and power-on
- final HCIStatusCode status = adapter.initialize( btMode );
- if( HCIStatusCode.SUCCESS != status ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: initialization failed: %s: %s\n",
- status.toString(), adapter.toString());
- return false;
- }
- } else if( !adapter.setPowered( true ) ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setPower.1 on failed: %s\n", adapter.toString());
- return false;
- }
- // adapter is powered-on
- BTUtils.println(System.err, "initServerAdapter.1: "+adapter.toString());
-
- if( adapter.setPowered(false) ) {
- HCIStatusCode status = adapter.setName(adapterName, adapterShortName);
- if( HCIStatusCode.SUCCESS == status ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setLocalName OK: %s\n", adapter.toString());
- } else {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setLocalName failed: %s\n", adapter.toString());
- return false;
- }
-
- status = adapter.setSecureConnections( use_SC );
- if( HCIStatusCode.SUCCESS == status ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setSecureConnections OK: %s\n", adapter.toString());
- } else {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setSecureConnections failed: %s\n", adapter.toString());
- return false;
- }
-
- final short conn_min_interval = 8; // 10ms
- final short conn_max_interval = 40; // 50ms
- final short conn_latency = 0;
- final short supervision_timeout = 50; // 500ms
- status = adapter.setDefaultConnParam(conn_min_interval, conn_max_interval, conn_latency, supervision_timeout);
- if( HCIStatusCode.SUCCESS == status ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setDefaultConnParam OK: %s\n", adapter.toString());
- } else {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setDefaultConnParam failed: %s\n", adapter.toString());
- return false;
- }
-
- if( !adapter.setPowered( true ) ) {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setPower.2 on failed: %s\n", adapter.toString());
- return false;
- }
- } else {
- BTUtils.fprintf_td(System.err, "initServerAdapter: setPowered.2 off failed: %s\n", adapter.toString());
- }
- // adapter is powered-on
- BTUtils.println(System.err, "initServerAdapter.2: "+adapter.toString());
-
- {
- final LE_Features le_feats = adapter.getLEFeatures();
- BTUtils.fprintf_td(System.err, "initServerAdapter: LE_Features %s\n", le_feats.toString());
- }
- if( adapter.getBTMajorVersion() > 4 ) {
- // BT5 specific
- final LE_PHYs Tx = new LE_PHYs( LE_PHYs.PHY.LE_2M );
- final LE_PHYs Rx = new LE_PHYs( LE_PHYs.PHY.LE_2M );
- final HCIStatusCode res = adapter.setDefaultLE_PHY(Tx, Rx);
- BTUtils.fprintf_td(System.err, "initServerAdapter: Set Default LE PHY: status %s: Tx %s, Rx %s\n",
- res.toString(), Tx.toString(), Rx.toString());
- }
- adapter.setSMPKeyPath(DBTConstants.SERVER_KEY_PATH);
-
- adapter.addStatusListener( myAdapterStatusListener );
-
- adapter.setServerConnSecurity(adapterSecurityLevel, SMPIOCapability.UNSET);
-
- return true;
- }
-}
diff --git a/trial/java/trial/org/direct_bt/TestDBTClientServer00.java b/trial/java/trial/org/direct_bt/TestDBTClientServer00.java
index 22c116ed..4d369082 100644
--- a/trial/java/trial/org/direct_bt/TestDBTClientServer00.java
+++ b/trial/java/trial/org/direct_bt/TestDBTClientServer00.java
@@ -107,7 +107,7 @@ public class TestDBTClientServer00 extends BaseDBTClientServer {
}
final String serverName = "TestDBTCS00-S-T10";
- final DBTServer00 server = new DBTServer00(serverName, EUI48.ALL_DEVICE, BTMode.DUAL, true /* SC */, BTSecurityLevel.NONE);
+ final DBTServer01 server = new DBTServer01(serverName, EUI48.ALL_DEVICE, BTMode.DUAL, true /* SC */, BTSecurityLevel.NONE, false /* do_disconnect */);
server.setProtocolSessionsLeft(1);
final DBTEndpoint.ChangedAdapterSetListener myChangedAdapterSetListener =