Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
dbt_scanner10.cpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include <cstring>
27 #include <string>
28 #include <memory>
29 #include <cstdint>
30 #include <fstream>
31 #include <iostream>
32 
33 #include <cinttypes>
34 
35 #include <pthread.h>
36 #include <csignal>
37 
38 #include <jau/cpp_lang_util.hpp>
39 #include <jau/dfa_utf8_decode.hpp>
40 #include <jau/basic_algos.hpp>
41 #include <jau/darray.hpp>
42 
43 #include <direct_bt/DirectBT.hpp>
44 
45 extern "C" {
46  #include <unistd.h>
47 }
48 
49 using namespace direct_bt;
50 using namespace jau;
51 
52 /** \file
53  * This _dbt_scanner10_ C++ scanner example uses the Direct-BT fully event driven workflow
54  * and adds multithreading, i.e. one thread processes each found device found
55  * as notified via the event listener.
56  *
57  * _dbt_scanner10_ represents the recommended utilization of Direct-BT.
58  *
59  * ### dbt_scanner10 Invocation Examples:
60  * Using `scripts/run-dbt_scanner10.sh` from `dist` directory:
61  * * Scan and read all devices (using default auto-sec w/ keyboard iocap)
62  * ~~~
63  * ../scripts/run-dbt_scanner10.sh
64  * ~~~
65  *
66  * * Read device C0:26:DA:01:DA:B1 (using default auto-sec w/ keyboard iocap)
67  * ~~~
68  * ../scripts/run-dbt_scanner10.sh -dev C0:26:DA:01:DA:B1
69  * ~~~
70  *
71  * * Read device C0:26:DA:01:DA:B1 (enforcing no security)
72  * ~~~
73  * ../scripts/run-dbt_scanner10.sh -dev C0:26:DA:01:DA:B1 -seclevel C0:26:DA:01:DA:B1 1
74  * ~~~
75  *
76  * * Read any device containing C0:26:DA (enforcing no security)
77  * ~~~
78  * ../scripts/run-dbt_scanner10.sh -dev C0:26:DA -seclevel C0:26:DA 1
79  * ~~~
80  *
81  * * Read any device containing name `TAIDOC` (enforcing no security)
82  * ~~~
83  * ../scripts/run-dbt_scanner10.sh -dev 'TAIDOC' -seclevel 'TAIDOC' 1
84  * ~~~
85  *
86  * * Read device C0:26:DA:01:DA:B1, basic debug flags enabled (using default auto-sec w/ keyboard iocap)
87  * ~~~
88  * ../scripts/run-dbt_scanner10.sh -dev C0:26:DA:01:DA:B1 -dbt_debug true
89  * ~~~
90  *
91  * * Read device C0:26:DA:01:DA:B1, all debug flags enabled (using default auto-sec w/ keyboard iocap)
92  * ~~~
93  * ../scripts/run-dbt_scanner10.sh -dev C0:26:DA:01:DA:B1 -dbt_debug adapter.event,gatt.data,hci.event,hci.scan_ad_eir,mgmt.event
94  * ~~~
95  *
96  * ## Special Actions
97  * * To do a BT adapter removal/add via software, assuming the device is '1-4' (Bus 1.Port 4):
98  * ~~~
99  * echo '1-4' > /sys/bus/usb/drivers/usb/unbind
100  * echo '1-4' > /sys/bus/usb/drivers/usb/bind
101  * ~~~
102  */
103 
104 const static std::string KEY_PATH = "keys";
105 
106 static uint64_t timestamp_t0;
107 
108 static int RESET_ADAPTER_EACH_CONN = 0;
109 static std::atomic<int> deviceReadyCount = 0;
110 
111 static std::atomic<int> MULTI_MEASUREMENTS = 8;
112 
113 static bool KEEP_CONNECTED = true;
114 static bool GATT_PING_ENABLED = false;
115 static bool REMOVE_DEVICE = true;
116 
117 static bool USE_WHITELIST = false;
119 
120 static std::string charIdentifier = "";
121 static int charValue = 0;
122 
123 static bool SHOW_UPDATE_EVENTS = false;
124 static bool QUIET = false;
125 
126 static void connectDiscoveredDevice(std::shared_ptr<BTDevice> device);
127 
128 static void processReadyDevice(std::shared_ptr<BTDevice> device);
129 
130 static void removeDevice(std::shared_ptr<BTDevice> device);
131 static void resetAdapter(BTAdapter *a, int mode);
132 static bool startDiscovery(BTAdapter *a, std::string msg);
133 
135 
136  void adapterSettingsChanged(BTAdapter &a, const AdapterSetting oldmask, const AdapterSetting newmask,
137  const AdapterSetting changedmask, const uint64_t timestamp) override {
138  const bool initialSetting = AdapterSetting::NONE == oldmask;
139  if( initialSetting ) {
140  fprintf_td(stderr, "****** SETTINGS_INITIAL: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
141  to_string(newmask).c_str(), to_string(changedmask).c_str());
142  } else {
143  fprintf_td(stderr, "****** SETTINGS_CHANGED: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
144  to_string(newmask).c_str(), to_string(changedmask).c_str());
145  }
146  fprintf_td(stderr, "Status BTAdapter:\n");
147  fprintf_td(stderr, "%s\n", a.toString().c_str());
148  (void)timestamp;
149 
150  if( !initialSetting &&
153  {
154  std::thread sd(::startDiscovery, &a, "powered-on"); // @suppress("Invalid arguments")
155  sd.detach();
156  }
157  }
158 
159  void discoveringChanged(BTAdapter &a, const ScanType currentMeta, const ScanType changedType, const bool changedEnabled, const bool keepAlive, const uint64_t timestamp) override {
160  fprintf_td(stderr, "****** DISCOVERING: meta %s, changed[%s, enabled %d, keepAlive %d]: %s\n",
161  to_string(currentMeta).c_str(), to_string(changedType).c_str(), changedEnabled, keepAlive, a.toString().c_str());
162  (void)timestamp;
163  }
164 
165  bool deviceFound(std::shared_ptr<BTDevice> device, const uint64_t timestamp) override {
166  (void)timestamp;
167 
170  // Requires BREDR or LE Secure Connection support: WIP
171  fprintf_td(stderr, "****** FOUND__-2: Skip non 'public LE' and non 'random static public LE' %s\n", device->toString(true).c_str());
172  return false;
173  }
178  )
179  )
180  )
181  {
182  fprintf_td(stderr, "****** FOUND__-0: Connecting %s\n", device->toString(true).c_str());
183  {
184  const uint64_t td = getCurrentMilliseconds() - timestamp_t0; // adapter-init -> now
185  fprintf_td(stderr, "PERF: adapter-init -> FOUND__-0 %" PRIu64 " ms\n", td);
186  }
187  std::thread dc(::connectDiscoveredDevice, device); // @suppress("Invalid arguments")
188  dc.detach();
189  return true;
190  } else {
191  fprintf_td(stderr, "****** FOUND__-1: NOP %s\n", device->toString(true).c_str());
192  return false;
193  }
194  }
195 
196  void deviceUpdated(std::shared_ptr<BTDevice> device, const EIRDataType updateMask, const uint64_t timestamp) override {
197  if( SHOW_UPDATE_EVENTS ) {
198  fprintf_td(stderr, "****** UPDATED: %s of %s\n", to_string(updateMask).c_str(), device->toString(true).c_str());
199  }
200  (void)timestamp;
201  }
202 
203  void deviceConnected(std::shared_ptr<BTDevice> device, const uint16_t handle, const uint64_t timestamp) override {
204  fprintf_td(stderr, "****** CONNECTED: %s\n", device->toString(true).c_str());
205  (void)handle;
206  (void)timestamp;
207  }
208 
209  void devicePairingState(std::shared_ptr<BTDevice> device, const SMPPairingState state, const PairingMode mode, const uint64_t timestamp) override {
210  fprintf_td(stderr, "****** PAIRING STATE: state %s, mode %s, %s\n",
211  to_string(state).c_str(), to_string(mode).c_str(), device->toString().c_str());
212  (void)timestamp;
213  switch( state ) {
215  // next: deviceReady(..)
216  break;
218  const bool res = SMPKeyBin::remove(KEY_PATH, device->getAddressAndType());
219  fprintf_td(stderr, "****** PAIRING_STATE: state %s; Remove key file %s, res %d\n",
220  to_string(state).c_str(), SMPKeyBin::getFilename(KEY_PATH, device->getAddressAndType()).c_str(), res);
221  // next: deviceReady() or deviceDisconnected(..)
222  } break;
224  // next: FEATURE_EXCHANGE_STARTED
225  break;
227  // next: FEATURE_EXCHANGE_COMPLETED
228  break;
230  // next: PASSKEY_EXPECTED... or KEY_DISTRIBUTION
231  break;
234  if( nullptr != sec && sec->getPairingPasskey() != BTSecurityRegistry::Entry::NO_PASSKEY ) {
235  std::thread dc(&BTDevice::setPairingPasskey, device, static_cast<uint32_t>( sec->getPairingPasskey() ));
236  dc.detach();
237  } else {
238  std::thread dc(&BTDevice::setPairingPasskey, device, 0);
239  // 3s disconnect: std::thread dc(&BTDevice::setPairingPasskeyNegative, device);
240  dc.detach();
241  }
242  // next: KEY_DISTRIBUTION or FAILED
243  } break;
246  if( nullptr != sec ) {
248  dc.detach();
249  } else {
250  std::thread dc(&BTDevice::setPairingNumericComparison, device, false);
251  dc.detach();
252  }
253  // next: KEY_DISTRIBUTION or FAILED
254  } break;
256  // FIXME: ABORT
257  break;
259  // next: COMPLETED or FAILED
260  break;
262  // next: deviceReady(..)
263  break;
264  default: // nop
265  break;
266  }
267  }
268 
269  void deviceReady(std::shared_ptr<BTDevice> device, const uint64_t timestamp) override {
270  (void)timestamp;
275  )
276  )
277  )
278  {
280  fprintf_td(stderr, "****** READY-0: Processing[%d] %s\n", deviceReadyCount.load(), device->toString(true).c_str());
282  processReadyDevice(device); // AdapterStatusListener::deviceReady() explicitly allows prolonged and complex code execution!
283  } else {
284  fprintf_td(stderr, "****** READY-1: NOP %s\n", device->toString(true).c_str());
285  }
286  }
287 
288  void deviceDisconnected(std::shared_ptr<BTDevice> device, const HCIStatusCode reason, const uint16_t handle, const uint64_t timestamp) override {
289  fprintf_td(stderr, "****** DISCONNECTED: Reason 0x%X (%s), old handle %s: %s\n",
290  static_cast<uint8_t>(reason), to_string(reason).c_str(),
291  to_hexstring(handle).c_str(), device->toString(true).c_str());
292  (void)timestamp;
293 
294  if( REMOVE_DEVICE ) {
295  std::thread dc(::removeDevice, device); // @suppress("Invalid arguments")
296  dc.detach();
297  } else {
299  }
301  std::thread dc(::resetAdapter, &device->getAdapter(), 1); // @suppress("Invalid arguments")
302  dc.detach();
303  }
304  }
305 
306  std::string toString() const override {
307  return "MyAdapterStatusListener[this "+to_hexstring(this)+"]";
308  }
309 
310 };
311 
313 
315  private:
316  int i, j;
317 
318  public:
319 
320  MyGATTEventListener(int i_, int j_) : i(i_), j(j_) {}
321 
322  void notificationReceived(BTGattCharRef charDecl, const TROOctets& char_value, const uint64_t timestamp) override {
323  const uint64_t tR = getCurrentMilliseconds();
324  fprintf_td(stderr, "**[%2.2d.%2.2d] Characteristic-Notify: UUID %s, td %" PRIu64 " ******\n",
325  i, j, charDecl->value_type->toUUID128String().c_str(), (tR-timestamp));
326  fprintf_td(stderr, "**[%2.2d.%2.2d] Characteristic: %s ******\n", i, j, charDecl->toString().c_str());
327  if( _TEMPERATURE_MEASUREMENT == *charDecl->value_type ) {
328  std::shared_ptr<GattTemperatureMeasurement> temp = GattTemperatureMeasurement::get(char_value);
329  if( nullptr != temp ) {
330  fprintf_td(stderr, "**[%2.2d.%2.2d] Value T: %s ******\n", i, j, temp->toString().c_str());
331  }
332  }
333  fprintf_td(stderr, "**[%2.2d.%2.2d] Value R: %s ******\n", i, j, char_value.toString().c_str());
334  }
335 
337  const TROOctets& char_value, const uint64_t timestamp,
338  const bool confirmationSent) override
339  {
340  const uint64_t tR = getCurrentMilliseconds();
341  fprintf_td(stderr, "**[%2.2d.%2.2d] Characteristic-Indication: UUID %s, td %" PRIu64 ", confirmed %d ******\n",
342  i, j, charDecl->value_type->toUUID128String().c_str(), (tR-timestamp), confirmationSent);
343  fprintf_td(stderr, "**[%2.2d.%2.2d] Characteristic: %s ******\n", i, j, charDecl->toString().c_str());
344  if( _TEMPERATURE_MEASUREMENT == *charDecl->value_type ) {
345  std::shared_ptr<GattTemperatureMeasurement> temp = GattTemperatureMeasurement::get(char_value);
346  if( nullptr != temp ) {
347  fprintf_td(stderr, "**[%2.2d.%2.2d] Value T: %s ******\n", i, j, temp->toString().c_str());
348  }
349  }
350  fprintf_td(stderr, "**[%2.2d.%2.2d] Value R: %s ******\n", i, j, char_value.toString().c_str());
351  }
352 };
353 
354 static void connectDiscoveredDevice(std::shared_ptr<BTDevice> device) {
355  fprintf_td(stderr, "****** Connecting Device: Start %s\n", device->toString().c_str());
356 
357  // Testing listener lifecycle @ device dtor
358  class TempAdapterStatusListener : public AdapterStatusListener {
359  void deviceUpdated(std::shared_ptr<BTDevice> device, const EIRDataType updateMask, const uint64_t timestamp) override {
360  if( SHOW_UPDATE_EVENTS ) {
361  fprintf_td(stderr, "****** UPDATED(2): %s of %s\n", to_string(updateMask).c_str(), device->toString(true).c_str());
362  }
363  (void)timestamp;
364  }
365  void deviceConnected(std::shared_ptr<BTDevice> device, const uint16_t handle, const uint64_t timestamp) override {
366  fprintf_td(stderr, "****** CONNECTED(2): %s\n", device->toString(true).c_str());
367  (void)handle;
368  (void)timestamp;
369  }
370  std::string toString() const override {
371  return "TempAdapterStatusListener[this "+to_hexstring(this)+"]";
372  }
373  };
374  device->addStatusListener(std::shared_ptr<AdapterStatusListener>(new TempAdapterStatusListener()));
375 
376  {
377  const HCIStatusCode r = device->unpair();
378  fprintf_td(stderr, "****** Connecting Device: Unpair-Pre result: %s\n", to_string(r).c_str());
379  }
380 
381  {
382  const HCIStatusCode r = device->getAdapter().stopDiscovery();
383  fprintf_td(stderr, "****** Connecting Device: stopDiscovery result %s\n", to_string(r).c_str());
384  }
385 
387  if( nullptr != sec ) {
388  fprintf_td(stderr, "****** Connecting Device: Found SecurityDetail %s for %s\n", sec->toString().c_str(), device->toString().c_str());
389  } else {
390  fprintf_td(stderr, "****** Connecting Device: No SecurityDetail for %s\n", device->toString().c_str());
391  }
392  const BTSecurityLevel req_sec_level = nullptr != sec ? sec->getSecLevel() : BTSecurityLevel::UNSET;
393  HCIStatusCode res = SMPKeyBin::readAndApply(KEY_PATH, *device, req_sec_level, true /* verbose */);
394  fprintf_td(stderr, "****** Connecting Device: SMPKeyBin::readAndApply(..) result %s\n", to_string(res).c_str());
395  if( HCIStatusCode::SUCCESS != res ) {
396  if( nullptr != sec ) {
397  if( sec->isSecurityAutoEnabled() ) {
398  bool r = device->setConnSecurityAuto( sec->getSecurityAutoIOCap() );
399  fprintf_td(stderr, "****** Connecting Device: Using SecurityDetail.SEC AUTO %s, set OK %d\n", sec->toString().c_str(), r);
400  } else if( sec->isSecLevelOrIOCapSet() ) {
401  bool r = device->setConnSecurityBest( sec->getSecLevel(), sec->getIOCap() );
402  fprintf_td(stderr, "****** Connecting Device: Using SecurityDetail.Level+IOCap %s, set OK %d\n", sec->toString().c_str(), r);
403  } else {
405  fprintf_td(stderr, "****** Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY (%s) -> set OK %d\n", sec->toString().c_str(), r);
406  }
407  } else {
409  fprintf_td(stderr, "****** Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY -> set OK %d\n", r);
410  }
411  }
412 
413  if( !USE_WHITELIST ) {
414  res = device->connectDefault();
415  } else {
417  }
418  fprintf_td(stderr, "****** Connecting Device: End result %s of %s\n", to_string(res).c_str(), device->toString().c_str());
419 
421  startDiscovery(&device->getAdapter(), "post-connect");
422  }
423 }
424 
425 static void processReadyDevice(std::shared_ptr<BTDevice> device) {
426  fprintf_td(stderr, "****** Processing Ready Device: Start %s\n", device->toString().c_str());
427  device->getAdapter().stopDiscovery(); // make sure for pending connections on failed connect*(..) command
428 
429  const uint64_t t1 = getCurrentMilliseconds();
430 
431  SMPKeyBin::createAndWrite(*device, KEY_PATH, false /* overwrite */, true /* verbose */);
432 
433  bool success = false;
434 
435  {
436  LE_PHYs resRx, resTx;
437  HCIStatusCode res = device->getConnectedLE_PHY(resRx, resTx);
438  fprintf_td(stderr, "****** Connected LE PHY: status %s: RX %s, TX %s\n",
439  to_string(res).c_str(), to_string(resRx).c_str(), to_string(resTx).c_str());
440  }
441 
442  //
443  // GATT Service Processing
444  //
445  fprintf_td(stderr, "****** Processing Ready Device: GATT start: %s\n", device->getAddressAndType().toString().c_str());
446  if( !QUIET ) {
447  device->getAdapter().printDeviceLists();
448  }
449  try {
450  jau::darray<BTGattServiceRef> primServices = device->getGattServices();
451  if( 0 == primServices.size() ) {
452  fprintf_td(stderr, "****** Processing Ready Device: getServices() failed %s\n", device->toString().c_str());
453  goto exit;
454  }
455 
456  const uint64_t t5 = getCurrentMilliseconds();
457  if( !QUIET ) {
458  const uint64_t td01 = t1 - timestamp_t0; // adapter-init -> processing-start
459  const uint64_t td15 = t5 - t1; // get-gatt-services
460  const uint64_t tdc5 = t5 - device->getLastDiscoveryTimestamp(); // discovered to gatt-complete
461  const uint64_t td05 = t5 - timestamp_t0; // adapter-init -> gatt-complete
462  fprintf_td(stderr, "\n\n\n");
463  fprintf_td(stderr, "PERF: GATT primary-services completed\n");
464  fprintf_td(stderr, "PERF: adapter-init to processing-start %" PRIu64 " ms,\n"
465  "PERF: get-gatt-services %" PRIu64 " ms,\n"
466  "PERF: discovered to gatt-complete %" PRIu64 " ms (connect %" PRIu64 " ms),\n"
467  "PERF: adapter-init to gatt-complete %" PRIu64 " ms\n\n",
468  td01, td15, tdc5, (tdc5 - td15), td05);
469  }
470 #if 0
471  {
472  // WIP: Implement a simple Characteristic ping-pong writeValue <-> notify transmission for stress testing.
473  BTManager & manager = device->getAdapter().getManager();
474  if( nullptr != charIdentifier && charIdentifier.length() > 0 ) {
475  BTGattChar * char2 = (BTGattChar*) nullptr;
476  // manager.find(BluetoothType.GATT_CHARACTERISTIC, null, charIdentifier, device);
477  fprintf_td(stderr, "Char UUID %s\n", charIdentifier.c_str());
478  fprintf_td(stderr, " over device : %s\n", char2->toString().c_str());
479  if( nullptr != char2 ) {
480  bool cccdEnableResult[2];
481  bool cccdRet = char2->addCharListener( std::shared_ptr<BTGattCharListener>( new MyGATTEventListener(char2) ),
482  cccdEnableResult );
483  if( !QUIET ) {
484  fprintf_td(stderr, "Added CharPingPongListenerRes Notification(%d), Indication(%d): Result %d\n",
485  cccdEnableResult[0], cccdEnableResult[1], cccdRet);
486  }
487  if( cccdRet ) {
488  uint8_t cmd[] { (uint8_t)charValue }; // request device model
489  bool wres = char2->writeValueNoResp(cmd);
490  if( !QUIET ) {
491  fprintf_td(stderr, "Write response: "+wres);
492  }
493  }
494  }
495  }
496  }
497 #endif
498 
499  std::shared_ptr<GattGenericAccessSvc> ga = device->getGattGenericAccess();
500  if( nullptr != ga && !QUIET ) {
501  fprintf_td(stderr, " GenericAccess: %s\n\n", ga->toString().c_str());
502  }
503  {
504  std::shared_ptr<BTGattHandler> gatt = device->getGattHandler();
505  if( nullptr != gatt && gatt->isConnected() ) {
506  std::shared_ptr<GattDeviceInformationSvc> di = gatt->getDeviceInformation(primServices);
507  if( nullptr != di && !QUIET ) {
508  fprintf_td(stderr, " DeviceInformation: %s\n\n", di->toString().c_str());
509  }
510  }
511  }
512 
513  for(size_t i=0; i<primServices.size(); i++) {
514  BTGattService & primService = *primServices.at(i);
515  if( !QUIET ) {
516  fprintf_td(stderr, " [%2.2d] Service UUID %s\n", i, primService.type->toUUID128String().c_str());
517  fprintf_td(stderr, " [%2.2d] %s\n", i, primService.toString().c_str());
518  }
519  jau::darray<BTGattCharRef> & serviceCharacteristics = primService.characteristicList;
520  for(size_t j=0; j<serviceCharacteristics.size(); j++) {
521  BTGattChar & serviceChar = *serviceCharacteristics.at(j);
522  if( !QUIET ) {
523  fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic: UUID %s\n", i, j, serviceChar.value_type->toUUID128String().c_str());
524  fprintf_td(stderr, " [%2.2d.%2.2d] %s\n", i, j, serviceChar.toString().c_str());
525  }
528  if( serviceChar.readValue(value) ) {
529  std::string sval = dfa_utf8_decode(value.get_ptr(), value.getSize());
530  if( !QUIET ) {
531  fprintf_td(stderr, " [%2.2d.%2.2d] value: %s ('%s')\n", (int)i, (int)j, value.toString().c_str(), sval.c_str());
532  }
533  }
534  }
535  jau::darray<BTGattDescRef> & charDescList = serviceChar.descriptorList;
536  for(size_t k=0; k<charDescList.size(); k++) {
537  BTGattDesc & charDesc = *charDescList.at(k);
538  if( !QUIET ) {
539  fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] Descriptor: UUID %s\n", i, j, k, charDesc.type->toUUID128String().c_str());
540  fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] %s\n", i, j, k, charDesc.toString().c_str());
541  }
542  }
543  bool cccdEnableResult[2];
544  bool cccdRet = serviceChar.addCharListener( std::shared_ptr<BTGattChar::Listener>( new MyGATTEventListener(i, j) ),
545  cccdEnableResult );
546  if( !QUIET ) {
547  fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic-Listener: Notification(%d), Indication(%d): Added %d\n",
548  (int)i, (int)j, cccdEnableResult[0], cccdEnableResult[1], cccdRet);
549  fprintf_td(stderr, "\n");
550  }
551  }
552  fprintf_td(stderr, "\n");
553  }
554  // FIXME sleep 1s for potential callbacks ..
555  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
556  success = true;
557  } catch ( std::exception & e ) {
558  fprintf_td(stderr, "****** Processing Ready Device: Exception caught for %s: %s\n", device->toString().c_str(), e.what());
559  }
560 
561 exit:
562  fprintf_td(stderr, "****** Processing Ready Device: End-1: Success %d on %s; devInProc %zu\n",
563  success, device->toString().c_str(), BTDeviceRegistry::getProcessingDeviceCount());
564 
566 
568  startDiscovery(&device->getAdapter(), "post-processing-1");
569  }
570 
571  if( KEEP_CONNECTED && GATT_PING_ENABLED && success ) {
572  while( device->pingGATT() ) {
573  fprintf_td(stderr, "****** Processing Ready Device: pingGATT OK: %s\n", device->getAddressAndType().toString().c_str());
574  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
575  }
576  fprintf_td(stderr, "****** Processing Ready Device: pingGATT failed, waiting for disconnect: %s\n", device->getAddressAndType().toString().c_str());
577  // Even w/ GATT_PING_ENABLED, we utilize disconnect event to clean up -> remove
578  }
579 
580  if( !QUIET ) {
581  device->getAdapter().printDeviceLists();
582  }
583 
584  fprintf_td(stderr, "****** Processing Ready Device: End-2: Success %d on %s; devInProc %zu\n",
585  success, device->toString().c_str(), BTDeviceRegistry::getProcessingDeviceCount());
586 
587  if( success ) {
589  }
590  device->removeAllCharListener();
591 
592  if( !KEEP_CONNECTED ) {
593  {
594  const HCIStatusCode unpair_res = device->unpair();
595  fprintf_td(stderr, "****** Processing Ready Device: Unpair-Post result: %s\n", to_string(unpair_res).c_str());
596  }
597 
598  device->remove();
599 
601  resetAdapter(&device->getAdapter(), 2);
603  startDiscovery(&device->getAdapter(), "post-processing-2");
604  }
605  }
606 
607  if( 0 < MULTI_MEASUREMENTS ) {
609  fprintf_td(stderr, "****** Processing Ready Device: MULTI_MEASUREMENTS left %d: %s\n", MULTI_MEASUREMENTS.load(), device->getAddressAndType().toString().c_str());
610  }
611 }
612 
613 static void removeDevice(std::shared_ptr<BTDevice> device) {
614  fprintf_td(stderr, "****** Remove Device: removing: %s\n", device->getAddressAndType().toString().c_str());
615  device->getAdapter().stopDiscovery();
616 
618 
619  device->remove();
620 
622  startDiscovery(&device->getAdapter(), "post-remove-device");
623  }
624 }
625 
626 static void resetAdapter(BTAdapter *a, int mode) {
627  fprintf_td(stderr, "****** Reset Adapter: reset[%d] start: %s\n", mode, a->toString().c_str());
628  HCIStatusCode res = a->reset();
629  fprintf_td(stderr, "****** Reset Adapter: reset[%d] end: %s, %s\n", mode, to_string(res).c_str(), a->toString().c_str());
630 }
631 
632 static bool le_scan_active = true; // default value
633 static const uint16_t le_scan_interval = 24; // default value
634 static const uint16_t le_scan_window = 24; // default value
635 static const uint8_t filter_policy = 0; // default value
636 
637 static bool startDiscovery(BTAdapter *a, std::string msg) {
639  fprintf_td(stderr, "****** Start discovery (%s) result: %s\n", msg.c_str(), to_string(status).c_str());
640  return HCIStatusCode::SUCCESS == status;
641 }
642 
643 static bool initAdapter(std::shared_ptr<BTAdapter>& adapter) {
644  // Even if adapter is not yet powered, listen to it and act when it gets powered-on
645  adapter->addStatusListener(std::shared_ptr<AdapterStatusListener>(new MyAdapterStatusListener()));
646  // Flush discovered devices after registering our status listener.
647  // This avoids discovered devices before we have registered!
648  adapter->removeDiscoveredDevices();
649 
650  if( !adapter->isPowered() ) { // should have been covered above
651  fprintf_td(stderr, "Adapter not powered (2): %s\n", adapter->toString().c_str());
652  return false;
653  }
654 
655  if( USE_WHITELIST ) {
656  for (auto it = WHITELIST.begin(); it != WHITELIST.end(); ++it) {
658  fprintf_td(stderr, "Added to WHITELIST: res %d, address %s\n", res, it->toString().c_str());
659  }
660  } else {
661  if( !startDiscovery(adapter.get(), "kick-off") ) {
662  return false;
663  }
664  }
665  return true;
666 }
667 
668 static bool myChangedAdapterSetFunc(const bool added, std::shared_ptr<BTAdapter>& adapter) {
669  if( added ) {
670  if( initAdapter( adapter ) ) {
671  fprintf_td(stderr, "****** Adapter ADDED__: InitOK. %s\n", adapter->toString().c_str());
672  } else {
673  fprintf_td(stderr, "****** Adapter ADDED__: Ignored %s\n", adapter->toString().c_str());
674  }
675  fprintf_td(stderr, "****** Adapter Features: %s\n", direct_bt::to_string(adapter->getLEFeatures()).c_str());
676  } else {
677  fprintf_td(stderr, "****** Adapter REMOVED: %s\n", adapter->toString().c_str());
678  }
679  return true;
680 }
681 
682 void test() {
683  bool done = false;
684 
685  fprintf_td(stderr, "DirectBT Native Version %s (API %s)\n", DIRECT_BT_VERSION, DIRECT_BT_VERSION_API);
686 
688 
689  BTManager & mngr = BTManager::get();
691 
692  while( !done ) {
693  if( 0 == MULTI_MEASUREMENTS ||
695  )
696  {
697  fprintf_td(stderr, "****** EOL Test MULTI_MEASUREMENTS left %d, processed %zu/%zu\n",
699  fprintf_td(stderr, "****** WaitForDevice %s\n", BTDeviceRegistry::getWaitForDevicesString().c_str());
700  fprintf_td(stderr, "****** DevicesProcessed %s\n", BTDeviceRegistry::getProcessedDevicesString().c_str());
701  done = true;
702  } else {
703  std::this_thread::sleep_for(std::chrono::milliseconds(2000));
704  }
705  }
706 
707  //
708  // just a manually controlled pull down to show status, not required
709  //
711 
712  jau::for_each_const(adapterList, [](const std::shared_ptr<BTAdapter>& adapter) {
713  fprintf_td(stderr, "****** EOL Adapter's Devices - pre close: %s\n", adapter->toString().c_str());
714  adapter->printDeviceLists();
715  });
716  {
718  fprintf_td(stderr, "****** EOL Removed ChangedAdapterSetCallback %d\n", count);
719 
720  mngr.close();
721  }
722  jau::for_each_const(adapterList, [](const std::shared_ptr<BTAdapter>& adapter) {
723  fprintf_td(stderr, "****** EOL Adapter's Devices - post close: %s\n", adapter->toString().c_str());
724  adapter->printDeviceLists();
725  });
726 }
727 
728 #include <cstdio>
729 
730 int main(int argc, char *argv[])
731 {
732  BTMode btMode = BTMode::DUAL;
733  bool waitForEnter=false;
734 
735  for(int i=1; i<argc; i++) {
736  if( !strcmp("-dbt_debug", argv[i]) && argc > (i+1) ) {
737  setenv("direct_bt.debug", argv[++i], 1 /* overwrite */);
738  } else if( !strcmp("-dbt_verbose", argv[i]) && argc > (i+1) ) {
739  setenv("direct_bt.verbose", argv[++i], 1 /* overwrite */);
740  } else if( !strcmp("-dbt_gatt", argv[i]) && argc > (i+1) ) {
741  setenv("direct_bt.gatt", argv[++i], 1 /* overwrite */);
742  } else if( !strcmp("-dbt_l2cap", argv[i]) && argc > (i+1) ) {
743  setenv("direct_bt.l2cap", argv[++i], 1 /* overwrite */);
744  } else if( !strcmp("-dbt_hci", argv[i]) && argc > (i+1) ) {
745  setenv("direct_bt.hci", argv[++i], 1 /* overwrite */);
746  } else if( !strcmp("-dbt_mgmt", argv[i]) && argc > (i+1) ) {
747  setenv("direct_bt.mgmt", argv[++i], 1 /* overwrite */);
748  } else if( !strcmp("-btmode", argv[i]) && argc > (i+1) ) {
749  btMode = to_BTMode(argv[++i]);
750  if( BTMode::NONE != btMode ) {
751  setenv("direct_bt.mgmt.btmode", to_string(btMode).c_str(), 1 /* overwrite */);
752  }
753  } else if( !strcmp("-wait", argv[i]) ) {
754  waitForEnter = true;
755  } else if( !strcmp("-show_update_events", argv[i]) ) {
756  SHOW_UPDATE_EVENTS = true;
757  } else if( !strcmp("-quiet", argv[i]) ) {
758  QUIET = true;
759  } else if( !strcmp("-scanPassive", argv[i]) ) {
760  le_scan_active = false;
761  } else if( !strcmp("-dev", argv[i]) && argc > (i+1) ) {
762  std::string addrOrNameSub = std::string(argv[++i]);
763  BTDeviceRegistry::addToWaitForDevices( addrOrNameSub );
764  } else if( !strcmp("-wl", argv[i]) && argc > (i+1) ) {
765  std::string macstr = std::string(argv[++i]);
767  fprintf(stderr, "Whitelist + %s\n", wle.toString().c_str());
768  WHITELIST.push_back( wle );
769  USE_WHITELIST = true;
770  } else if( !strcmp("-passkey", argv[i]) && argc > (i+2) ) {
771  const std::string addrOrNameSub(argv[++i]);
773  sec->passkey = atoi(argv[++i]);
774  fprintf(stderr, "Set passkey in %s\n", sec->toString().c_str());
775  } else if( !strcmp("-seclevel", argv[i]) && argc > (i+2) ) {
776  const std::string addrOrNameSub(argv[++i]);
778  sec->sec_level = to_BTSecurityLevel(atoi(argv[++i]));
779  fprintf(stderr, "Set sec_level in %s\n", sec->toString().c_str());
780  } else if( !strcmp("-iocap", argv[i]) && argc > (i+2) ) {
781  const std::string addrOrNameSub(argv[++i]);
783  sec->io_cap = to_SMPIOCapability(atoi(argv[++i]));
784  fprintf(stderr, "Set io_cap in %s\n", sec->toString().c_str());
785  } else if( !strcmp("-secauto", argv[i]) && argc > (i+2) ) {
786  const std::string addrOrNameSub(argv[++i]);
788  sec->io_cap_auto = to_SMPIOCapability(atoi(argv[++i]));
789  fprintf(stderr, "Set SEC AUTO security io_cap in %s\n", sec->toString().c_str());
790  } else if( !strcmp("-charid", argv[i]) && argc > (i+1) ) {
791  charIdentifier = std::string(argv[++i]);
792  } else if( !strcmp("-charval", argv[i]) && argc > (i+1) ) {
793  charValue = atoi(argv[++i]);
794  } else if( !strcmp("-disconnect", argv[i]) ) {
795  KEEP_CONNECTED = false;
796  } else if( !strcmp("-enableGATTPing", argv[i]) ) {
797  GATT_PING_ENABLED = true;
798  } else if( !strcmp("-keepDevice", argv[i]) ) {
799  REMOVE_DEVICE = false;
800  } else if( !strcmp("-count", argv[i]) && argc > (i+1) ) {
801  MULTI_MEASUREMENTS = atoi(argv[++i]);
802  } else if( !strcmp("-single", argv[i]) ) {
803  MULTI_MEASUREMENTS = -1;
804  } else if( !strcmp("-resetEachCon", argv[i]) && argc > (i+1) ) {
805  RESET_ADAPTER_EACH_CONN = atoi(argv[++i]);
806  }
807  }
808  fprintf(stderr, "pid %d\n", getpid());
809 
810  fprintf(stderr, "Run with '[-btmode LE|BREDR|DUAL] "
811  "[-disconnect] [-enableGATTPing] [-count <number>] [-single] [-show_update_events] [-quiet] "
812  "[-scanPassive]"
813  "[-resetEachCon connectionCount] "
814  "(-dev <device_[address|name]_sub>)* (-wl <device_address>)* "
815  "(-seclevel <device_[address|name]_sub> <int_sec_level>)* "
816  "(-iocap <device_[address|name]_sub> <int_iocap>)* "
817  "(-secauto <device_[address|name]_sub> <int_iocap>)* "
818  "(-passkey <device_[address|name]_sub> <digits>)* "
819  "[-unpairPre] [-unpairPost] "
820  "[-charid <uuid>] [-charval <byte-val>] "
821  "[-dbt_verbose true|false] "
822  "[-dbt_debug true|false|adapter.event,gatt.data,hci.event,hci.scan_ad_eir,mgmt.event] "
823  "[-dbt_mgmt cmd.timeout=3000,ringsize=64,...] "
824  "[-dbt_hci cmd.complete.timeout=10000,cmd.status.timeout=3000,ringsize=64,...] "
825  "[-dbt_gatt cmd.read.timeout=500,cmd.write.timeout=500,cmd.init.timeout=2500,ringsize=128,...] "
826  "[-dbt_l2cap reader.timeout=10000,restart.count=0,...] "
827  "\n");
828 
829  fprintf(stderr, "MULTI_MEASUREMENTS %d\n", MULTI_MEASUREMENTS.load());
830  fprintf(stderr, "KEEP_CONNECTED %d\n", KEEP_CONNECTED);
831  fprintf(stderr, "RESET_ADAPTER_EACH_CONN %d\n", RESET_ADAPTER_EACH_CONN);
832  fprintf(stderr, "GATT_PING_ENABLED %d\n", GATT_PING_ENABLED);
833  fprintf(stderr, "REMOVE_DEVICE %d\n", REMOVE_DEVICE);
834  fprintf(stderr, "USE_WHITELIST %d\n", USE_WHITELIST);
835  fprintf(stderr, "SHOW_UPDATE_EVENTS %d\n", SHOW_UPDATE_EVENTS);
836  fprintf(stderr, "QUIET %d\n", QUIET);
837  fprintf(stderr, "btmode %s\n", to_string(btMode).c_str());
838  fprintf(stderr, "scanActive %s\n", to_string(le_scan_active).c_str());
839  fprintf(stderr, "characteristic-id: %s\n", charIdentifier.c_str());
840  fprintf(stderr, "characteristic-value: %d\n", charValue);
841 
842  fprintf(stderr, "security-details: %s\n", BTSecurityRegistry::allToString().c_str());
843  fprintf(stderr, "waitForDevice: %s\n", BTDeviceRegistry::getWaitForDevicesString().c_str());
844 
845  if( waitForEnter ) {
846  fprintf(stderr, "Press ENTER to continue\n");
847  getchar();
848  }
849  fprintf(stderr, "****** TEST start\n");
850  test();
851  fprintf(stderr, "****** TEST end\n");
852  if( true ) {
853  // Just for testing purpose, i.e. triggering BTManager::close() within the test controlled app,
854  // instead of program shutdown.
855  fprintf(stderr, "****** Manager close start\n");
856  BTManager & mngr = BTManager::get(); // already existing
857  mngr.close();
858  fprintf(stderr, "****** Manager close end\n");
859  }
860 }
direct_bt::BTDeviceRegistry::getWaitForDevicesString
std::string getWaitForDevicesString() noexcept
Definition: BTDeviceRegistry.cpp:62
direct_bt::BTGattService::characteristicList
jau::darray< BTGattCharRef > characteristicList
List of Characteristic Declarations as shared reference.
Definition: BTGattService.hpp:97
direct_bt::BTAdapter::stopDiscovery
HCIStatusCode stopDiscovery() noexcept
Closes the discovery session.
Definition: BTAdapter.cpp:756
direct_bt::BTDevice::connectDefault
HCIStatusCode connectDefault() noexcept
Establish a default HCI connection to this device, using certain default parameter.
Definition: BTDevice.cpp:532
jau::darray::at
const_reference at(size_type i) const
Like std::vector::at(size_type), immutable reference.
Definition: darray.hpp:719
direct_bt::AdapterSetting
AdapterSetting
Adapter Setting Bits.
Definition: BTTypes1.hpp:136
DirectBT.hpp
direct_bt::BTSecurityRegistry::getOrCreate
Entry * getOrCreate(const std::string &addrOrNameSub) noexcept
Determines whether the given.
Definition: BTSecurityRegistry.cpp:71
direct_bt::BTDeviceRegistry::areAllDevicesProcessed
bool areAllDevicesProcessed(DeviceQueryMatchFunc m) noexcept
Returns.
Definition: BTDeviceRegistry.cpp:126
direct_bt::BTGattHandler::getDeviceInformation
std::shared_ptr< GattDeviceInformationSvc > getDeviceInformation(jau::darray< BTGattServiceRef > &primServices)
Definition: BTGattHandler.cpp:1096
direct_bt::BTGattChar::hasProperties
bool hasProperties(const PropertyBitVal v) const noexcept
Definition: BTGattChar.hpp:216
direct_bt::BTDevice::remove
void remove() noexcept
Disconnects this device via disconnect(..) if getConnected()==true and explicitly removes its shared ...
Definition: BTDevice.cpp:1784
direct_bt::BTDeviceRegistry::getProcessedDevicesString
std::string getProcessedDevicesString() noexcept
Definition: BTDeviceRegistry.cpp:92
direct_bt::GattGenericAccessSvc::toString
std::string toString() const noexcept
Definition: GATTNumbers.cpp:382
direct_bt::BTDevice::setConnSecurityAuto
bool setConnSecurityAuto(const SMPIOCapability iocap_auto) noexcept
Set automatic security negotiation of BTSecurityLevel and SMPIOCapability pairing mode.
Definition: BTDevice.cpp:1274
darray.hpp
direct_bt::TROOctets::getSize
constexpr jau::nsize_t getSize() const noexcept
Returns the used memory size for read and write operations, may be zero.
Definition: OctetTypes.hpp:118
direct_bt::GattTemperatureMeasurement::get
static std::shared_ptr< GattTemperatureMeasurement > get(const TROOctets &source) noexcept
Definition: GATTNumbers.cpp:414
direct_bt::BTSecurityRegistry::Entry::isSecLevelOrIOCapSet
constexpr bool isSecLevelOrIOCapSet() const noexcept
Definition: BTSecurityRegistry.hpp:59
le_scan_interval
static const uint16_t le_scan_interval
Definition: dbt_scanner10.cpp:633
direct_bt::HCIWhitelistConnectType::HCI_AUTO_CONN_ALWAYS
@ HCI_AUTO_CONN_ALWAYS
Auto Connect: Only supported for LE on Linux .
direct_bt::EIRDataType
EIRDataType
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
Definition: BTTypes0.hpp:752
direct_bt::BTAdapter::reset
HCIStatusCode reset() noexcept
Reset the adapter.
Definition: BTAdapter.cpp:489
direct_bt::to_BTSecurityLevel
constexpr BTSecurityLevel to_BTSecurityLevel(const uint8_t v) noexcept
Definition: BTTypes0.hpp:244
direct_bt::BTSecurityRegistry::allToString
std::string allToString() noexcept
Definition: BTSecurityRegistry.cpp:93
direct_bt::SMPPairingState::PASSKEY_EXPECTED
@ PASSKEY_EXPECTED
Phase 2: Authentication (MITM) PASSKEY expected now, see PairingMode::PASSKEY_ENTRY_ini.
direct_bt::BDAddressAndType::getBLERandomAddressType
BLERandomAddressType getBLERandomAddressType() const noexcept
Returns the BLERandomAddressType.
Definition: BTAddress.hpp:479
direct_bt::BTAdapter::getLEFeatures
constexpr LE_Features getLEFeatures() const noexcept
Return LE_Features for this controller.
Definition: BTAdapter.hpp:465
basic_algos.hpp
direct_bt::BTGattChar::readValue
bool readValue(POctets &res, int expectedLength=-1)
BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.1 Read Characteristic Value.
Definition: BTGattChar.cpp:304
direct_bt::BTSecurityRegistry::getStartOf
Entry * getStartOf(const EUI48 &addr, const std::string &name) noexcept
Returns a matching Entry,.
Definition: BTSecurityRegistry.hpp:153
direct_bt::BTGattDesc::type
std::unique_ptr< const uuid_t > type
Type of descriptor.
Definition: BTGattDesc.hpp:102
direct_bt::BTSecurityRegistry::Entry::io_cap_auto
SMPIOCapability io_cap_auto
Definition: BTSecurityRegistry.hpp:50
direct_bt::TROOctets::toString
std::string toString() const noexcept
Definition: OctetTypes.hpp:244
direct_bt::BTSecurityRegistry::Entry::getPairingPasskey
constexpr int getPairingPasskey() const noexcept
Definition: BTSecurityRegistry.hpp:70
SHOW_UPDATE_EVENTS
static bool SHOW_UPDATE_EVENTS
Definition: dbt_scanner10.cpp:123
direct_bt::BTSecurityRegistry::Entry
Definition: BTSecurityRegistry.hpp:42
dfa_utf8_decode.hpp
direct_bt
Definition: ATTPDUTypes.hpp:171
direct_bt::to_BTMode
BTMode to_BTMode(const std::string &value) noexcept
Maps the specified name to a constant of BTMode.
Definition: BTTypes0.cpp:360
direct_bt::BTGattDesc::toString
virtual std::string toString() const noexcept override
Definition: BTGattDesc.cpp:82
direct_bt::BTMode::NONE
@ NONE
Zero mode, neither DUAL, BREDR nor LE.
direct_bt::BTGattChar
Definition: BTGattChar.hpp:75
direct_bt::BTDevice::getConnectedLE_PHY
HCIStatusCode getConnectedLE_PHY(LE_PHYs &resRx, LE_PHYs &resTx) noexcept
Request and return LE_PHYs bit for the given connection.
Definition: BTDevice.cpp:1648
direct_bt::AdapterStatusListener
BTAdapter status listener for BTDevice discovery events: Added, updated and removed; as well as for c...
Definition: BTAdapter.hpp:67
direct_bt::BTAdapter::removeDiscoveredDevices
int removeDiscoveredDevices() noexcept
Discards all discovered devices.
Definition: BTAdapter.cpp:877
direct_bt::BTDevice::setPairingNumericComparison
HCIStatusCode setPairingNumericComparison(const bool equal) noexcept
Method sets the numeric comparison result, see PairingMode::NUMERIC_COMPARE_ini.
Definition: BTDevice.cpp:1350
direct_bt::SMPPairingState::OOB_EXPECTED
@ OOB_EXPECTED
Phase 2: Authentication (MITM) OOB data expected now, see PairingMode::OUT_OF_BAND.
direct_bt::BTDevice::getLastDiscoveryTimestamp
uint64_t getLastDiscoveryTimestamp() const noexcept
Returns the timestamp in monotonic milliseconds when this device instance has discovered or connected...
Definition: BTDevice.hpp:260
direct_bt::BTDevice::pingGATT
bool pingGATT() noexcept
Issues a GATT ping to the device, validating whether it is still reachable.
Definition: BTDevice.cpp:1575
direct_bt::SMPKeyBin::getFilename
static std::string getFilename(const std::string &path, const BDAddressAndType &addrAndType_)
Definition: SMPKeyBin.hpp:292
direct_bt::BTDeviceRegistry::getProcessingDeviceCount
size_t getProcessingDeviceCount() noexcept
Definition: BTDeviceRegistry.cpp:162
direct_bt::to_SMPIOCapability
constexpr SMPIOCapability to_SMPIOCapability(const uint8_t v) noexcept
Definition: SMPTypes.hpp:199
_TEMPERATURE_MEASUREMENT
static const uuid16_t _TEMPERATURE_MEASUREMENT(GattCharacteristicType::TEMPERATURE_MEASUREMENT)
removeDevice
static void removeDevice(std::shared_ptr< BTDevice > device)
Definition: dbt_scanner10.cpp:613
direct_bt::SMPPairingState::KEY_DISTRIBUTION
@ KEY_DISTRIBUTION
Phase 3: Key & value distribution started after SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Conn...
direct_bt::uuid16_t
Definition: UUID.hpp:98
direct_bt::TROOctets::get_ptr
constexpr uint8_t const * get_ptr() const noexcept
Definition: OctetTypes.hpp:228
direct_bt::BDAddressAndType::toString
std::string toString() const noexcept
Definition: BTTypes0.cpp:333
direct_bt::BTAdapter::printDeviceLists
void printDeviceLists() noexcept
Print the internally maintained BTDevice lists to stderr:
Definition: BTAdapter.cpp:325
jau
Definition: basic_algos.hpp:34
direct_bt::BTDeviceRegistry::addToProcessingDevices
void addToProcessingDevices(const BDAddressAndType &a, const std::string &n) noexcept
Definition: BTDeviceRegistry.cpp:145
direct_bt::BTSecurityRegistry::Entry::toString
std::string toString() const noexcept
Definition: BTSecurityRegistry.hpp:74
direct_bt::BTGattService
Representing a complete [Primary] Service Declaration including its list of Characteristic Declaratio...
Definition: BTGattService.hpp:67
direct_bt::ScanType
ScanType
Meta ScanType as derived from BTMode, with defined value mask consisting of BDAddressType bits.
Definition: BTTypes0.hpp:294
WHITELIST
static jau::darray< BDAddressAndType > WHITELIST
Definition: dbt_scanner10.cpp:118
direct_bt::BTDevice::toString
std::string toString() const noexcept override
Definition: BTDevice.hpp:303
direct_bt::BTManager::close
void close() noexcept
Definition: BTManager.cpp:538
direct_bt::BTDevice::getAddressAndType
constexpr BDAddressAndType const & getAddressAndType() const noexcept
Returns the unique device EUI48 address and BDAddressType type.
Definition: BTDevice.hpp:278
direct_bt::BTGattChar::addCharListener
bool addCharListener(std::shared_ptr< Listener > l)
Add the given BTGattChar::Listener to the listener list if not already present.
Definition: BTGattChar.cpp:285
direct_bt::BTDeviceRegistry::isWaitingForDevice
bool isWaitingForDevice(const EUI48 &address, const std::string &name, DeviceQueryMatchFunc m) noexcept
Returns.
Definition: BTDeviceRegistry.cpp:120
direct_bt::BTSecurityLevel
BTSecurityLevel
Bluetooth Security Level.
Definition: BTTypes0.hpp:211
direct_bt::BTSecurityRegistry::Entry::getIOCap
constexpr const SMPIOCapability & getIOCap() const noexcept
Definition: BTSecurityRegistry.hpp:63
QUIET
static bool QUIET
Definition: dbt_scanner10.cpp:124
direct_bt::BTAdapter::isPowered
bool isPowered() const noexcept
Returns whether the adapter is valid, plugged in and powered.
Definition: BTAdapter.hpp:437
direct_bt::HCIStatusCode
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Definition: HCITypes.hpp:124
RESET_ADAPTER_EACH_CONN
static int RESET_ADAPTER_EACH_CONN
Definition: dbt_scanner10.cpp:108
jau::darray
Implementation of a dynamic linear array storage, aka vector.
Definition: darray.hpp:102
timestamp_t0
static uint64_t timestamp_t0
Definition: dbt_scanner10.cpp:106
direct_bt::BTGattCharRef
std::shared_ptr< BTGattChar > BTGattCharRef
Definition: BTGattChar.hpp:409
direct_bt::BTSecurityRegistry::Entry::getPairingNumericComparison
constexpr bool getPairingNumericComparison() const noexcept
Definition: BTSecurityRegistry.hpp:72
direct_bt::BTDevice::getGattGenericAccess
std::shared_ptr< GattGenericAccessSvc > getGattGenericAccess()
Returns the shared GenericAccess instance, retrieved by getGattService() or nullptr if not available.
Definition: BTDevice.cpp:1590
le_scan_window
static const uint16_t le_scan_window
Definition: dbt_scanner10.cpp:634
TEMPERATURE_MEASUREMENT
@ TEMPERATURE_MEASUREMENT
Definition: test_datatype02.hpp:82
direct_bt::BDAddressAndType::type
BDAddressType type
Definition: BTAddress.hpp:429
jau::fprintf_td
int fprintf_td(FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the environment::getElapsedMillisecond() timestamp.
Definition: debug.cpp:188
MyGATTEventListener::notificationReceived
void notificationReceived(BTGattCharRef charDecl, const TROOctets &char_value, const uint64_t timestamp) override
Called from native BLE stack, initiated by a received notification associated with the given BTGattCh...
Definition: dbt_scanner10.cpp:322
direct_bt::BTManager::getAdapters
jau::darray< std::shared_ptr< BTAdapter > > getAdapters()
Returns a list of currently added DBTAdapter.
Definition: BTManager.hpp:367
MULTI_MEASUREMENTS
static std::atomic< int > MULTI_MEASUREMENTS
Definition: dbt_scanner10.cpp:111
direct_bt::BTAdapter::toString
std::string toString() const noexcept override
Definition: BTAdapter.hpp:784
direct_bt::BTDevice::setPairingPasskey
HCIStatusCode setPairingPasskey(const uint32_t passkey) noexcept
Method sets the given passkey entry, see PairingMode::PASSKEY_ENTRY_ini.
Definition: BTDevice.cpp:1304
direct_bt::SMPPairingState::FAILED
@ FAILED
Pairing failed.
direct_bt::BTGattHandler::Defaults::MAX_ATT_MTU
@ MAX_ATT_MTU
direct_bt::BTDeviceRegistry::addToWaitForDevices
void addToWaitForDevices(const std::string &addrOrNameSub) noexcept
Definition: BTDeviceRegistry.cpp:46
direct_bt::BTDeviceRegistry::removeFromProcessingDevices
bool removeFromProcessingDevices(const BDAddressAndType &a) noexcept
Definition: BTDeviceRegistry.cpp:149
direct_bt::SMPPairingState::FEATURE_EXCHANGE_COMPLETED
@ FEATURE_EXCHANGE_COMPLETED
Phase 1: Pairing responded by responding (slave) device via SMPPairingMsg.
direct_bt::BTManager::removeChangedAdapterSetCallback
int removeChangedAdapterSetCallback(const ChangedAdapterSetCallback &l)
Remove the given ChangedAdapterSetCallback from this manager.
Definition: BTManager.cpp:1238
direct_bt::BTManager::get
static BTManager & get(const BTMode defaultBTMode=BTMode::NONE)
Retrieves the singleton instance.
Definition: BTManager.hpp:320
direct_bt::BTSecurityRegistry::Entry::io_cap
SMPIOCapability io_cap
Definition: BTSecurityRegistry.hpp:49
GATT_PING_ENABLED
static bool GATT_PING_ENABLED
Definition: dbt_scanner10.cpp:114
direct_bt::GattDeviceInformationSvc::toString
std::string toString() const noexcept
Definition: GATTNumbers.cpp:407
direct_bt::BTSecurityLevel::UNSET
@ UNSET
Security Level not set, value 0.
jau::darray::size
constexpr size_type size() const noexcept
Like std::vector::size().
Definition: darray.hpp:668
Read
@ Read
Definition: test_datatype02.hpp:106
direct_bt::PairingMode
PairingMode
Bluetooth secure pairing mode.
Definition: BTTypes0.hpp:261
direct_bt::BTDevice::removeAllCharListener
int removeAllCharListener() noexcept
Remove all BTGattCharListener from the list.
Definition: BTDevice.cpp:1638
direct_bt::BTDeviceRegistry::addToProcessedDevices
void addToProcessedDevices(const BDAddressAndType &a, const std::string &n) noexcept
Definition: BTDeviceRegistry.cpp:80
MyAdapterStatusListener
Definition: dbt_scanner00.cpp:55
direct_bt::BTManager
A thread safe singleton handler of the Linux Kernel's BlueZ manager control channel.
Definition: BTManager.hpp:201
direct_bt::BTDeviceRegistry::isDeviceProcessing
bool isDeviceProcessing(const BDAddressAndType &a) noexcept
Definition: BTDeviceRegistry.cpp:158
main
int main(int argc, char *argv[])
Definition: dbt_scanner10.cpp:730
direct_bt::BLERandomAddressType::STATIC_PUBLIC
@ STATIC_PUBLIC
Static public 'random' device address 0b11.
direct_bt::SMPPairingState::REQUESTED_BY_RESPONDER
@ REQUESTED_BY_RESPONDER
Phase 0: Pairing requested by responding (slave) device via SMPSecurityReqMsg.
jau::dfa_utf8_decode
uint32_t dfa_utf8_decode(uint32_t &state, uint32_t &codep, const uint32_t byte_value)
Definition: dfa_utf8_decode.cpp:90
direct_bt::BTDevice::setConnSecurityBest
bool setConnSecurityBest(const BTSecurityLevel sec_level, const SMPIOCapability io_cap) noexcept
Convenience method to determine the best practice BTSecurityLevel and SMPIOCapability based on the gi...
Definition: BTDevice.cpp:1258
direct_bt::BTGattService::type
std::unique_ptr< const uuid_t > type
Service type UUID.
Definition: BTGattService.hpp:94
jau::for_each_const
constexpr UnaryFunction for_each_const(T &data, UnaryFunction f, std::enable_if_t< is_cow_type< T >::value, bool >=true) noexcept
Definition: basic_algos.hpp:323
direct_bt::BTAdapter::addStatusListener
bool addStatusListener(std::shared_ptr< AdapterStatusListener > l)
Add the given listener to the list if not already present.
Definition: BTAdapter.cpp:548
REMOVE_DEVICE
static bool REMOVE_DEVICE
Definition: dbt_scanner10.cpp:115
direct_bt::BTGattChar::toString
std::string toString() const noexcept override
Definition: BTGattChar.cpp:106
le_scan_active
static bool le_scan_active
Definition: dbt_scanner10.cpp:632
KEY_PATH
static const std::string KEY_PATH
Definition: dbt_scanner10.cpp:104
direct_bt::SMPPairingState::NUMERIC_COMPARE_EXPECTED
@ NUMERIC_COMPARE_EXPECTED
Phase 2: Authentication (MITM) Numeric Comparison Reply expected now, see PairingMode::NUMERIC_COMPAR...
USE_WHITELIST
static bool USE_WHITELIST
Definition: dbt_scanner10.cpp:117
direct_bt::TROOctets
Transient read only octet data, i.e.
Definition: OctetTypes.hpp:59
direct_bt::SMPKeyBin::readAndApply
static HCIStatusCode readAndApply(const std::string &path, BTDevice &device, const BTSecurityLevel minSecLevel, const bool verbose_)
Create a new SMPKeyBin instance on the fly based upon stored file denoted by path and BTDevice::getAd...
Definition: SMPKeyBin.cpp:92
direct_bt::to_string
std::string to_string(const BDAddressType type) noexcept
Definition: BTTypes0.cpp:129
direct_bt::BTManager::addChangedAdapterSetCallback
void addChangedAdapterSetCallback(const ChangedAdapterSetCallback &l)
ChangedAdapterSetCallback handling.
Definition: BTManager.cpp:1230
direct_bt::BTAdapter
BTAdapter represents one Bluetooth Controller.
Definition: BTAdapter.hpp:250
direct_bt::BTSecurityRegistry::Entry::getSecurityAutoIOCap
constexpr const SMPIOCapability & getSecurityAutoIOCap() const noexcept
Definition: BTSecurityRegistry.hpp:68
direct_bt::SMPIOCapability::KEYBOARD_ONLY
@ KEYBOARD_ONLY
Keyboard input only, value 2.
direct_bt::BTMode::DUAL
@ DUAL
Dual Bluetooth mode, i.e.
jau::getCurrentMilliseconds
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
Definition: basic_types.cpp:47
charValue
static int charValue
Definition: dbt_scanner10.cpp:121
direct_bt::AdapterSetting::NONE
@ NONE
direct_bt::EUI48
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: BTAddress.hpp:388
direct_bt::BDAddressAndType::address
EUI48 address
Definition: BTAddress.hpp:428
direct_bt::BTAdapter::getManager
BTManager & getManager() const noexcept
Returns a reference to the used singleton BTManager instance, used to create this adapter.
Definition: BTAdapter.hpp:570
jau::to_hexstring
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
Definition: string_util.hpp:104
cpp_lang_util.hpp
connectDiscoveredDevice
static void connectDiscoveredDevice(std::shared_ptr< BTDevice > device)
Definition: dbt_scanner10.cpp:354
direct_bt::BTSecurityRegistry::Entry::sec_level
BTSecurityLevel sec_level
Definition: BTSecurityRegistry.hpp:48
direct_bt::BTGattService::toString
std::string toString() const noexcept override
Definition: BTGattService.cpp:66
direct_bt::BTDeviceRegistry::isWaitingForAnyDevice
bool isWaitingForAnyDevice() noexcept
Definition: BTDeviceRegistry.cpp:56
direct_bt::BTDevice::getGattServices
jau::darray< std::shared_ptr< BTGattService > > getGattServices() noexcept
Returns a list of shared GATTService available on this device if successful, otherwise returns an emp...
Definition: BTDevice.cpp:1525
direct_bt::BTGattHandler::isConnected
bool isConnected() const noexcept
Definition: BTGattHandler.hpp:253
initAdapter
static bool initAdapter(std::shared_ptr< BTAdapter > &adapter)
Definition: dbt_scanner10.cpp:643
direct_bt::SMPPairingState::NONE
@ NONE
No pairing in process.
MyGATTEventListener::indicationReceived
void indicationReceived(BTGattCharRef charDecl, const TROOctets &char_value, const uint64_t timestamp, const bool confirmationSent) override
Called from native BLE stack, initiated by a received indication associated with the given BTGattChar...
Definition: dbt_scanner10.cpp:336
MyGATTEventListener
Definition: dbt_scanner00.cpp:118
direct_bt::SMPPairingState::FEATURE_EXCHANGE_STARTED
@ FEATURE_EXCHANGE_STARTED
Phase 1: Pairing requested by initiating (master) device via SMPPairingMsg.
processReadyDevice
static void processReadyDevice(std::shared_ptr< BTDevice > device)
Definition: dbt_scanner10.cpp:425
direct_bt::BTDeviceRegistry::getProcessedDeviceCount
size_t getProcessedDeviceCount() noexcept
Definition: BTDeviceRegistry.cpp:88
direct_bt::HCIStatusCode::SUCCESS
@ SUCCESS
direct_bt::SMPKeyBin::remove
static bool remove(const std::string &path, const BDAddressAndType &addrAndType_)
Definition: SMPKeyBin.hpp:296
direct_bt::BTDevice::addStatusListener
bool addStatusListener(std::shared_ptr< AdapterStatusListener > l)
Add the given AdapterStatusListener to the list if not already present, intended to listen only for e...
Definition: BTDevice.cpp:248
direct_bt::BTAdapter::addDeviceToWhitelist
bool addDeviceToWhitelist(const BDAddressAndType &addressAndType, const HCIWhitelistConnectType ctype, const uint16_t conn_interval_min=12, const uint16_t conn_interval_max=12, const uint16_t conn_latency=0, const uint16_t supervision_timeout=getHCIConnSupervisorTimeout(0, 15))
Add the given device to the adapter's autoconnect whitelist.
Definition: BTAdapter.cpp:522
direct_bt::BTSecurityRegistry::Entry::NO_PASSKEY
static constexpr int NO_PASSKEY
Definition: BTSecurityRegistry.hpp:43
myChangedAdapterSetFunc
static bool myChangedAdapterSetFunc(const bool added, std::shared_ptr< BTAdapter > &adapter)
Definition: dbt_scanner10.cpp:668
direct_bt::BTDevice::getGattHandler
std::shared_ptr< BTGattHandler > getGattHandler() noexcept
Returns the connected GATTHandler or nullptr, see connectGATT(), getGattService() and disconnect().
Definition: BTDevice.cpp:1520
deviceReadyCount
static std::atomic< int > deviceReadyCount
Definition: dbt_scanner10.cpp:109
direct_bt::BTGattChar::value_type
std::unique_ptr< const uuid_t > value_type
Definition: BTGattChar.hpp:189
direct_bt::SMPKeyBin::createAndWrite
static bool createAndWrite(const BTDevice &device, const std::string &path, const bool overwrite, const bool verbose_)
Create a new SMPKeyBin instance on the fly based upon given BTDevice's BTSecurityLevel,...
Definition: SMPKeyBin.cpp:79
startDiscovery
static bool startDiscovery(BTAdapter *a, std::string msg)
Definition: dbt_scanner10.cpp:637
direct_bt::POctets::toString
std::string toString() const
Definition: OctetTypes.hpp:666
direct_bt::BTGattChar::writeValueNoResp
bool writeValueNoResp(const TROOctets &value)
BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.1 Write Characteristic Value Without Response.
Definition: BTGattChar.cpp:327
direct_bt::BTSecurityRegistry::Entry::passkey
int passkey
Definition: BTSecurityRegistry.hpp:51
direct_bt::BTGattChar::descriptorList
jau::darray< BTGattDescRef > descriptorList
List of Characteristic Descriptions as shared reference.
Definition: BTGattChar.hpp:192
direct_bt::BTDevice::getName
std::string const getName() const noexcept
Definition: BTDevice.cpp:124
deviceFound
std::shared_ptr< BTDevice > deviceFound
This C++ direct_bt scanner example is a TinyB backward compatible and not fully event driven.
Definition: dbt_scanner00.cpp:51
filter_policy
static const uint8_t filter_policy
Definition: dbt_scanner10.cpp:635
direct_bt::BTDeviceRegistry::isDeviceProcessed
bool isDeviceProcessed(const BDAddressAndType &a) noexcept
Definition: BTDeviceRegistry.cpp:84
direct_bt::BTDeviceRegistry::getWaitForDevicesCount
size_t getWaitForDevicesCount() noexcept
Definition: BTDeviceRegistry.cpp:59
direct_bt::POctets
Persistent octet data, i.e.
Definition: OctetTypes.hpp:451
direct_bt::BTAdapter::startDiscovery
HCIStatusCode startDiscovery(const bool keepAlive=true, const bool le_scan_active=false, const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint8_t filter_policy=0x00)
Starts a new discovery session.
Definition: BTAdapter.cpp:679
direct_bt::BTDevice::unpair
HCIStatusCode unpair() noexcept
Unpairs this device from the adapter while staying connected.
Definition: BTDevice.cpp:1772
direct_bt::AdapterSetting::POWERED
@ POWERED
direct_bt::SMPPairingState
SMPPairingState
SMP Pairing Process state definition.
Definition: SMPTypes.hpp:101
direct_bt::BTSecurityRegistry::Entry::getSecLevel
constexpr const BTSecurityLevel & getSecLevel() const noexcept
Definition: BTSecurityRegistry.hpp:62
KEEP_CONNECTED
static bool KEEP_CONNECTED
Definition: dbt_scanner10.cpp:113
direct_bt::BTGattHandler::number
static constexpr int number(const Defaults d)
Definition: BTGattHandler.hpp:149
direct_bt::isAdapterSettingBitSet
constexpr bool isAdapterSettingBitSet(const AdapterSetting mask, const AdapterSetting bit) noexcept
Definition: BTTypes1.hpp:177
resetAdapter
static void resetAdapter(BTAdapter *a, int mode)
Definition: dbt_scanner10.cpp:626
direct_bt::LE_PHYs
LE_PHYs
LE Transport PHY bit values.
Definition: BTTypes0.hpp:175
direct_bt::BDAddressType::BDADDR_LE_PUBLIC
@ BDADDR_LE_PUBLIC
Bluetooth LE public address.
direct_bt::BDAddressAndType
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BTAddress.hpp:417
test
void test()
Definition: dbt_scanner10.cpp:682
direct_bt::BTDevice::getAdapter
BTAdapter & getAdapter() const
Returns the managing adapter.
Definition: BTDevice.hpp:243
direct_bt::BTGattDesc
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3 Characteristic Descriptor.
Definition: BTGattDesc.hpp:62
direct_bt::BTMode
BTMode
Bluetooth adapter operating mode.
Definition: BTTypes0.hpp:56
direct_bt::GattTemperatureMeasurement::toString
std::string toString() const noexcept
Definition: GATTNumbers.cpp:453
direct_bt::SMPPairingState::COMPLETED
@ COMPLETED
Phase 3: Key & value distribution completed by responding (slave) device sending SMPIdentInfoMsg (#1)...
direct_bt::BTGattChar::Listener
BTGattChar event listener for notification and indication events.
Definition: BTGattChar.hpp:122
MyGATTEventListener::MyGATTEventListener
MyGATTEventListener(int i_, int j_)
Definition: dbt_scanner10.cpp:320
direct_bt::BTSecurityRegistry::Entry::isSecurityAutoEnabled
constexpr bool isSecurityAutoEnabled() const noexcept
Definition: BTSecurityRegistry.hpp:65
charIdentifier
static std::string charIdentifier
Definition: dbt_scanner10.cpp:120