Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
DBTDevice.java
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
26package jau.direct_bt;
27
28import java.lang.ref.WeakReference;
29import java.nio.ByteOrder;
30import java.util.ArrayList;
31import java.util.List;
32import java.util.Locale;
33import java.util.concurrent.atomic.AtomicBoolean;
34
35import org.direct_bt.AdapterStatusListener;
36import org.direct_bt.BDAddressAndType;
37import org.direct_bt.BDAddressType;
38import org.direct_bt.BTSecurityLevel;
39import org.direct_bt.BTDevice;
40import org.direct_bt.BTException;
41import org.direct_bt.BTGattChar;
42import org.direct_bt.BTGattService;
43import org.direct_bt.BTRole;
44import org.direct_bt.EInfoReport;
45import org.direct_bt.BTGattCharListener;
46import org.direct_bt.HCIStatusCode;
47import org.direct_bt.LE_PHYs;
48import org.direct_bt.PairingMode;
49import org.direct_bt.SMPIOCapability;
50import org.direct_bt.SMPIdentityResolvingKey;
51import org.direct_bt.SMPKeyBin;
52import org.direct_bt.SMPKeyMask;
53import org.direct_bt.SMPLinkKey;
54import org.direct_bt.SMPLongTermKey;
55import org.direct_bt.SMPPairingState;
56import org.direct_bt.SMPSignatureResolvingKey;
57import org.jau.io.PrintUtil;
58import org.jau.net.EUI48;
59
60public class DBTDevice extends DBTObject implements BTDevice
61{
62 private static final boolean DEBUG = DBTManager.DEBUG;
63
64 /** Device's adapter weak back-reference */
65 private final WeakReference<DBTAdapter> wbr_adapter;
66
67 private BDAddressAndType addressAndType;
68 private final BDAddressAndType visibleAddressAndType;
69 private final long ts_creation;
70 volatile long ts_last_discovery;
71 volatile long ts_last_update;
72 volatile short hciConnHandle;
73 private volatile String name_cached;
74 /* pp */ final List<WeakReference<DBTGattService>> serviceCache = new ArrayList<WeakReference<DBTGattService>>();
75 private final EInfoReport eir_ = new EInfoReport();
76 private final EInfoReport eir_ind_ = new EInfoReport();
77 private final EInfoReport eir_scan_rsp_ = new EInfoReport();
78
79 private final AtomicBoolean isClosing = new AtomicBoolean(false);
80
81 /* pp */ final AtomicBoolean isConnected = new AtomicBoolean(false);
82
83 /* pp */ DBTDevice(final long nativeInstance, final DBTAdapter adptr,
84 final byte byteAddress[/*6*/],
85 final byte byteAddressType,
86 final long ts_creation, final String name)
87 {
88 super(nativeInstance, compHash(java.util.Arrays.hashCode(byteAddress), 31+byteAddressType));
89 this.wbr_adapter = new WeakReference<DBTAdapter>(adptr);
90 this.visibleAddressAndType = new BDAddressAndType(byteAddress, 0, byteAddressType);
91 this.addressAndType = new BDAddressAndType(this.visibleAddressAndType);
92 if( BDAddressType.BDADDR_UNDEFINED == addressAndType.type ) {
93 throw new IllegalArgumentException("Unsupported given native addresstype "+byteAddressType);
94 }
95 this.ts_creation = ts_creation;
96 ts_last_discovery = ts_creation;
97 ts_last_update = ts_creation;
98 hciConnHandle = 0;
99 name_cached = name;
100 initImpl();
101 // FIXME enableTrustedNotificationsImpl(trustedNotificationsCB);
102 }
103
104 /* pp */ void updateAddress() {
105 final byte byteAddress[/*6*/] = getAddressImpl();
106 final byte byteAddressType = getAddressTypeImpl();
107 if( null != byteAddress && 0 != byteAddressType ) {
108 addressAndType = new BDAddressAndType(byteAddress, 0, byteAddressType);
109 }
110 }
111 private native byte[] getAddressImpl();
112 private native byte getAddressTypeImpl();
113
114 @Override
115 public void close() {
116 if( !isValid() ) {
117 return;
118 }
119 if( !isClosing.compareAndSet(false, true) ) {
120 return;
121 }
122 clearServiceCache();
123
124 final DBTAdapter a = getAdapter();
125 if( null != a ) {
126 a.removeDiscoveredDevice(this);
127 }
128 super.close();
129 }
130
131 @Override
132 public final long getCreationTimestamp() { return ts_creation; }
133
134 @Override
135 public final long getLastDiscoveryTimestamp() { return ts_last_discovery; }
136
137 @Override
138 public final long getLastUpdateTimestamp() { return ts_last_update; }
139
140 @Override
141 public DBTAdapter getAdapter() { return wbr_adapter.get(); }
142
143 @Override
144 public final BTRole getRole() {
145 return BTRole.get(getRoleImpl());
146 }
147 private native byte getRoleImpl();
148
149 @Override
150 public boolean equals(final Object obj)
151 {
152 if(this == obj) {
153 return true;
154 }
155 if (obj == null || !(obj instanceof DBTDevice)) {
156 return false;
157 }
158 final DBTDevice other = (DBTDevice)obj;
159 return addressAndType.equals(other.addressAndType) ||
160 visibleAddressAndType.equals(other.visibleAddressAndType); // FIXME: Evaluate if OK w/o collisions
161 }
162
163 @Override
164 public BDAddressAndType getAddressAndType() { return addressAndType; }
165
166 @Override
167 public BDAddressAndType getVisibleAddressAndType() { return visibleAddressAndType; }
168
169 @Override
170 public String getName() {
171 if( !isValid() ) {
172 return name_cached;
173 } else {
174 final String v = getNameImpl();
175 name_cached = v;
176 return v;
177 }
178 }
179 private native String getNameImpl();
180
181 @Override
182 public BTGattService findGattService(final String service_uuid) {
183 synchronized(serviceCache) {
184 if( !checkServiceCache(true) ) {
185 return null;
186 }
187 for(int srvIdx = serviceCache.size() - 1; srvIdx >= 0; srvIdx-- ) {
188 final DBTGattService service = serviceCache.get(srvIdx).get();
189 if( null == service ) {
190 serviceCache.remove(srvIdx); // remove dead ref
191 continue; // cont w/ next service
192 }
193 if( service.getUUID().equals(service_uuid) ) {
194 return service;
195 }
196 }
197 return null;
198 }
199 }
200
201 @Override
202 public BTGattChar findGattChar(final String service_uuid, final String char_uuid) {
203 final BTGattService s = findGattService(service_uuid);
204 if( null == s ) {
205 return null;
206 }
207 return s.findGattChar(char_uuid);
208 }
209
210 @Override
211 public BTGattChar findGattChar(final String char_uuid) {
212 synchronized(serviceCache) {
213 if( !checkServiceCache(true) ) {
214 return null;
215 }
216 for(int srvIdx = serviceCache.size() - 1; srvIdx >= 0; srvIdx-- ) {
217 final DBTGattService s = serviceCache.get(srvIdx).get();
218 if( null == s ) {
219 serviceCache.remove(srvIdx); // remove dead ref
220 continue; // cont w/ next service
221 }
222 final BTGattChar c = s.findGattChar(char_uuid);
223 if( null != c ) {
224 return c;
225 }
226 }
227 return null;
228 }
229 }
230
231 /* internal */
232
233 private native void initImpl();
234
235 /* DBT method calls: Connection */
236
237 @Override
238 public final boolean addStatusListener(final AdapterStatusListener l) {
239 return getAdapter().addStatusListenerImpl(this, l);
240 }
241
242 @Override
244 return getAdapter().removeStatusListenerImpl(l);
245 }
246
247 @Override
248 public final boolean getConnected() { return isConnected.get(); }
249
250 @Override
251 public final short getConnectionHandle() { return hciConnHandle; }
252
253 @Override
254 public HCIStatusCode getConnectedLE_PHY(final LE_PHYs[] resTx, final LE_PHYs[] resRx) {
255 // pre-init
256 resTx[0] = new LE_PHYs(LE_PHYs.PHY.LE_1M);
257 resRx[0] = new LE_PHYs(LE_PHYs.PHY.LE_1M);
258 final byte[] t = { resTx[0].mask };
259 final byte[] r = { resRx[0].mask };
260 final HCIStatusCode res = HCIStatusCode.get( getConnectedLE_PHYImpl(t, r) );
261 resTx[0] = new LE_PHYs(t[0]);
262 resRx[0] = new LE_PHYs(r[0]);
263 return res;
264 }
265 private native byte getConnectedLE_PHYImpl(byte[] resTx, byte[] resRx);
266
267 @Override
268 public HCIStatusCode setConnectedLE_PHY(final LE_PHYs Tx, final LE_PHYs Rx) {
269 return HCIStatusCode.get( setConnectedLE_PHYImpl(Tx.mask, Rx.mask) );
270 }
271 private native byte setConnectedLE_PHYImpl(final byte Tx, final byte Rx);
272
273 @Override
274 public final LE_PHYs getTxPhys() {
275 return new LE_PHYs( getTxPhysImpl() );
276 }
277 private native byte getTxPhysImpl();
278
279 @Override
280 public final LE_PHYs getRxPhys() {
281 return new LE_PHYs( getRxPhysImpl() );
282 }
283 private native byte getRxPhysImpl();
284
285 @Override
286 public final HCIStatusCode disconnect() {
287 if( isConnected.get() ) {
288 return HCIStatusCode.get( disconnectImpl() ); // event callbacks will be generated by implementation
289 }
291 }
292 private native byte disconnectImpl();
293
294 @Override
295 public native boolean isPrePaired();
296
297 @Override
298 public native int getResponderSMPPassKey();
299
300 @Override
301 public final String getResponderSMPPassKeyString() {
302 return String.format((Locale)null, "%06d", getResponderSMPPassKey());
303 }
304
305 @Override
307 if( !isConnected.get() ) {
308 return HCIStatusCode.get( connectDefaultImpl() ); // event callbacks will be generated by implementation
309 }
311 }
312 private native byte connectDefaultImpl();
313
314 @Override
315 public HCIStatusCode connectLE(final short le_scan_interval, final short le_scan_window,
316 final short conn_interval_min, final short conn_interval_max,
317 final short conn_latency, final short timeout) {
318 if( !isConnected.get() ) {
319 // event callbacks will be generated by implementation
320 if( 0 > le_scan_interval || 0 > le_scan_window || 0 > conn_interval_min ||
321 0 > conn_interval_max || 0 > conn_latency || 0 > timeout ) {
322 return HCIStatusCode.get( connectLEImpl0() );
323 } else {
324 return HCIStatusCode.get( connectLEImpl1(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, timeout) );
325 }
326 }
328 }
329 private native byte connectLEImpl0();
330 private native byte connectLEImpl1(final short le_scan_interval, final short le_scan_window,
331 final short conn_interval_min, final short conn_interval_max,
332 final short conn_latency, final short timeout);
333
334 /* SC SMP */
335
336 @Override
337 public final SMPKeyMask getAvailableSMPKeys(final boolean responder) {
338 return new SMPKeyMask(getAvailableSMPKeysImpl(responder));
339 }
340 private final native byte getAvailableSMPKeysImpl(final boolean responder);
341
342 @Override
343 public final boolean setSMPKeyBin(final SMPKeyBin bin) {
344 if( !isValid() ) {
345 if( DEBUG ) {
346 PrintUtil.fprintf_td(System.err, "BTDevice::setSMPKeyBin(): Apply SMPKeyBin failed, device invalid: %s, %s",
347 bin.toString(), toString());
348 }
349 return false;
350 }
351
353 if( DEBUG ) {
354 PrintUtil.println(System.err, "SMPKeyBin::readAndApply: Local address mismatch: Has "+getAdapter().getAddressAndType().toString()+
355 ", read "+bin.getLocalAddrAndType().toString()+": "+bin.toString());
356 }
357 return false;
358 }
360 if( DEBUG ) {
361 PrintUtil.println(System.err, "SMPKeyBin::readAndApply: Remote address mismatch: Has "+getAddressAndType().toString()+
362 ", read "+bin.getRemoteAddrAndType().toString()+": "+bin.toString());
363 }
364 return false;
365 }
366
367 // Must be a valid SMPKeyBin instance and at least one LTK key if using encryption.
368 // Also validates IRKs' id_address, if contained
369 if( !bin.isValid() || ( BTSecurityLevel.NONE != bin.getSecLevel() && !bin.hasLTKInit() && !bin.hasLTKResp() ) ) {
370 if( DEBUG ) {
371 PrintUtil.fprintf_td(System.err, "BTDevice::setSMPKeyBin(): Apply SMPKeyBin failed, all invalid or sec level w/o LTK: %s, %s",
372 bin.toString(), toString());
373 }
374 return false;
375 }
376
377 final BTRole btRoleAdapter = getRole().reverse();
378 if( btRoleAdapter != bin.getLocalRole() ) {
379 if( DEBUG ) {
380 PrintUtil.fprintf_td(System.err, "BTDevice::setSMPKeyBin(): Apply SMPKeyBin failed, local adapter role %s mismatch: %s, %s",
381 btRoleAdapter.toString(), bin.toString(), toString());
382 }
383 return false;
384 }
385
386 {
387 /**
388 *
389 if( SMPIOCapability::UNSET != pairing_data.ioCap_auto ||
390 ( SMPPairingState::COMPLETED != pairing_data.state &&
391 SMPPairingState::NONE != pairing_data.state ) )
392 {
393 DBG_PRINT("BTDevice::setSMPKeyBin: Failure, pairing in progress: %s", pairing_data.toString(addressAndType, btRole).c_str());
394 return false;
395 }
396 */
397 if( getConnected() ) {
398 if( DEBUG ) {
399 PrintUtil.println(System.err, "BTDevice::setSMPKeyBin: Failure, device connected: "+toString());
400 }
401 return false;
402 }
403
404 // Allow no encryption at all, i.e. BTSecurityLevel::NONE
405 final BTSecurityLevel applySecLevel = BTSecurityLevel.NONE.value == bin.getSecLevel().value ?
406 BTSecurityLevel.NONE : BTSecurityLevel.ENC_ONLY;
407
408 if( !setConnSecurity(applySecLevel, SMPIOCapability.NO_INPUT_NO_OUTPUT) ) {
409 if( DEBUG ) {
410 PrintUtil.println(System.err, "BTDevice::setSMPKeyBin: Setting security failed: Device Connected/ing: "+bin.toString()+", "+toString());
411 }
412 return false;
413 }
414 }
415 if( bin.hasLTKInit() ) {
416 setLongTermKey( bin.getLTKInit() );
417 }
418 if( bin.hasLTKResp() ) {
419 setLongTermKey( bin.getLTKResp() );
420 }
421
422 if( bin.hasIRKInit() ) {
424 }
425 if( bin.hasIRKResp() ) {
427 }
428
429 if( bin.hasCSRKInit() ) {
431 }
432 if( bin.hasCSRKResp() ) {
434 }
435
436 if( bin.hasLKInit() ) {
437 setLinkKey( bin.getLKInit() );
438 }
439 if( bin.hasLKResp() ) {
440 setLinkKey( bin.getLKResp() );
441 }
442 return true;
443 }
444
445 @Override
446 public final HCIStatusCode uploadKeys() {
447 return HCIStatusCode.get( uploadKeysImpl() );
448 }
449 private final native byte uploadKeysImpl();
450
451 @Override
452 public final HCIStatusCode uploadKeys(final SMPKeyBin bin, final BTSecurityLevel req_min_level) {
453 if( bin.isValid() && bin.getSecLevel().value >= req_min_level.value && setSMPKeyBin(bin) ) {
454 return uploadKeys();
455 } else {
457 }
458 }
459
460 @Override
461 public final HCIStatusCode uploadKeys(final String smp_key_bin_path, final BTSecurityLevel req_min_level, final boolean verbose_) {
462 return uploadKeys(SMPKeyBin.read(smp_key_bin_path, this, verbose_), req_min_level);
463 }
464
465
466 @Override
467 public final SMPLongTermKey getLongTermKey(final boolean responder) {
468 final byte[] stream = new byte[SMPLongTermKey.byte_size];
469 getLongTermKeyImpl(responder, stream);
470 return new SMPLongTermKey(stream, 0);
471 }
472 private final native void getLongTermKeyImpl(final boolean responder, final byte[] sink);
473
474 @Override
475 public final void setLongTermKey(final SMPLongTermKey ltk) {
476 final byte[] stream = new byte[SMPLongTermKey.byte_size];
477 ltk.put(stream, 0);
478 setLongTermKeyImpl(stream);
479 }
480 private final native void setLongTermKeyImpl(final byte[] source);
481
482 @Override
483 public final SMPIdentityResolvingKey getIdentityResolvingKey(final boolean responder) {
484 final byte[] stream = new byte[SMPIdentityResolvingKey.byte_size];
485 getIdentityResolvingKeyImpl(responder, stream);
486 return new SMPIdentityResolvingKey(stream, 0);
487 }
488 private final native void getIdentityResolvingKeyImpl(final boolean responder, final byte[] sink);
489
490 @Override
492 final byte[] stream = new byte[SMPIdentityResolvingKey.byte_size];
493 irk.put(stream, 0);
494 setIdentityResolvingKeyImpl(stream);
495 }
496 private final native void setIdentityResolvingKeyImpl(final byte[] source);
497
498 @Override
499 public final SMPSignatureResolvingKey getSignatureResolvingKey(final boolean responder) {
500 final byte[] stream = new byte[SMPSignatureResolvingKey.byte_size];
501 getSignatureResolvingKeyImpl(responder, stream);
502 return new SMPSignatureResolvingKey(stream, 0);
503 }
504 private final native void getSignatureResolvingKeyImpl(final boolean responder, final byte[] sink);
505
506 @Override
508 final byte[] stream = new byte[SMPSignatureResolvingKey.byte_size];
509 irk.put(stream, 0);
510 setSignatureResolvingKeyImpl(stream);
511 }
512 private final native void setSignatureResolvingKeyImpl(final byte[] source);
513
514 @Override
515 public final SMPLinkKey getLinkKey(final boolean responder) {
516 final byte[] stream = new byte[SMPLinkKey.byte_size];
517 getLinkKeyImpl(responder, stream);
518 return new SMPLinkKey(stream, 0);
519 }
520 private final native void getLinkKeyImpl(final boolean responder, final byte[] sink);
521
522 @Override
523 public final void setLinkKey(final SMPLinkKey lk) {
524 final byte[] stream = new byte[SMPLinkKey.byte_size];
525 lk.put(stream, 0);
526 setLinkKeyImpl(stream);
527 }
528 private final native void setLinkKeyImpl(final byte[] source);
529
530 @Override
531 public final HCIStatusCode unpair() {
532 return HCIStatusCode.get( unpairImpl() );
533 }
534 private final native byte unpairImpl();
535
536 @Override
538 return BTSecurityLevel.get( getConnSecurityLevelImpl() );
539 }
540 private final native byte getConnSecurityLevelImpl();
541
542 @Override
544 return SMPIOCapability.get( getConnIOCapabilityImpl() );
545 }
546 private final native byte getConnIOCapabilityImpl();
547
548 @Override
549 public final boolean setConnSecurity(final BTSecurityLevel sec_level, final SMPIOCapability io_cap) {
550 return setConnSecurityImpl(sec_level.value, io_cap.value);
551 }
552 private final native boolean setConnSecurityImpl(final byte sec_level, final byte io_cap);
553
554 @Override
555 public final boolean setConnSecurityAuto(final SMPIOCapability iocap_auto) {
556 return setConnSecurityAutoImpl( iocap_auto.value );
557 }
558 private final native boolean setConnSecurityAutoImpl(final byte io_cap);
559
560 @Override
561 public final native boolean isConnSecurityAutoEnabled();
562
563 @Override
564 public HCIStatusCode setPairingPasskey(final int passkey) {
565 return HCIStatusCode.get( setPairingPasskeyImpl(passkey) );
566 }
567 private native byte setPairingPasskeyImpl(final int passkey) throws BTException;
568
569 @Override
571 return HCIStatusCode.get( setPairingPasskeyNegativeImpl() );
572 }
573 private native byte setPairingPasskeyNegativeImpl() throws BTException;
574
575 @Override
576 public HCIStatusCode setPairingNumericComparison(final boolean equal) {
577 return HCIStatusCode.get( setPairingNumericComparisonImpl(equal) );
578 }
579 private native byte setPairingNumericComparisonImpl(final boolean equal);
580
581 @Override
583 return PairingMode.get( getPairingModeImpl() );
584 }
585 private native byte getPairingModeImpl();
586
587 @Override
589 return SMPPairingState.get( getPairingStateImpl() );
590 }
591 private native byte getPairingStateImpl();
592
593 @Override
594 public final String toString() {
595 if( !isValid() ) {
596 // UTF-8 271D = Cross
597 return "Device" + "\u271D" + "[address"+addressAndType+", '"+name_cached+
598 "', connected["+isConnected.get()+", 0x"+Integer.toHexString(hciConnHandle)+"]]";
599 }
600 return toStringImpl();
601 }
602 private native String toStringImpl();
603
604 /**
605 * {@inheritDoc}
606 */
607 @Override
608 public final boolean remove() throws BTException {
609 // close: clear java-listener, super.close()
610 // -> DBTNativeDownlink.delete(): deleteNativeJavaObject(..), deleteImpl(..) -> DBTDevice::remove()
611 close();
612 // return removeImpl();
613 if( DBTAdapter.PRINT_DEVICE_LISTS || DEBUG ) {
614 PrintUtil.fprintf_td(System.err, "BTDevice::remove: %s", toString());
616 }
617 return true;
618 }
619 private native boolean removeImpl() throws BTException;
620
621 @Override
622 public final boolean isValid() { return super.isNativeValid() /* && isValidImpl() */; }
623 // private native boolean isValidImpl();
624
625 @Override
626 public List<BTGattService> getGattServices() {
627 try {
628 List<BTGattService> services = getGattServicesImpl();
629 if( null == services ) {
630 services = new ArrayList<BTGattService>();
631 }
632 updateServiceCache(services);
633 return services;
634 } catch (final Throwable t) {
635 System.err.println("DBTDevice.getServices(): Caught "+t.getMessage()+" on thread "+Thread.currentThread().toString()+" on "+toString());
636 if(DEBUG) {
637 t.printStackTrace();
638 }
639 }
640 return new ArrayList<BTGattService>();
641 }
642 private native List<BTGattService> getGattServicesImpl();
643
644 @Override
645 public native boolean sendNotification(final short char_value_handle, final byte[] value);
646
647 @Override
648 public native boolean sendIndication(final short char_value_handle, final byte[] value);
649
650 @Override
651 public boolean pingGATT() {
652 try {
653 return pingGATTImpl();
654 } catch (final Throwable t) {
655 System.err.println("DBTDevice.pingGATT(): Caught "+t.getMessage()+" on thread "+Thread.currentThread().toString()+" on "+toString());
656 if(DEBUG) {
657 t.printStackTrace();
658 }
659 }
660 return false;
661 }
662 private native boolean pingGATTImpl();
663
664 /* property accessors: */
665
666 @Override
667 public native short getRSSI();
668
669 @Override
670 public final EInfoReport getEIR() {
671 synchronized( eir_ ) {
672 getEIRImpl(eir_);
673 return eir_;
674 }
675 }
676 private native void getEIRImpl(final EInfoReport eir);
677
678 @Override
680 synchronized( eir_ind_ ) {
681 getEIRIndImpl(eir_ind_);
682 return eir_ind_;
683 }
684 }
685 private native void getEIRIndImpl(final EInfoReport eir);
686
687 @Override
689 synchronized( eir_scan_rsp_ ) {
690 getEIRScanRspImpl(eir_scan_rsp_);
691 return eir_scan_rsp_;
692 }
693 }
694 private native void getEIRScanRspImpl(final EInfoReport eir);
695
696 @Override
697 public native short getTxPower ();
698
699 /**
700 * {@inheritDoc}
701 * <p>
702 * Native implementation calls DBTDevice::remove()
703 * </p>
704 */
705 @Override
706 protected native void deleteImpl(long nativeInstance);
707
708 @Override
709 public boolean addCharListener(final BTGattCharListener listener) {
710 return addCharListenerImpl(listener, null);
711 }
712
713 @Override
714 public boolean addCharListener(final BTGattCharListener listener, final BTGattChar associatedCharacteristic) {
715 return addCharListenerImpl(listener, associatedCharacteristic);
716 }
717 private native boolean addCharListenerImpl(final BTGattCharListener listener, final BTGattChar associatedCharacteristic);
718
719 @Override
720 public native boolean removeCharListener(final BTGattCharListener l);
721
722 @Override
723 public native int removeAllAssociatedCharListener(final BTGattChar associatedCharacteristic);
724
725 @Override
726 public native int removeAllCharListener();
727
728 /* local functionality */
729
730 /* pp */ final void clearServiceCache() {
731 synchronized(serviceCache) {
732 for(int i = serviceCache.size() - 1; i >= 0; i-- ) {
733 serviceCache.get(i).clear();
734 serviceCache.remove(i);
735 }
736 }
737 }
738 private void updateServiceCache(final List<BTGattService> services) {
739 synchronized(serviceCache) {
740 clearServiceCache();
741 if( null != services ) {
742 for(final BTGattService service : services) {
743 serviceCache.add( new WeakReference<DBTGattService>( (DBTGattService)service ) );
744 }
745 }
746 }
747 }
748
749 private final boolean checkServiceCache(final boolean retrieveGattServices) {
750 synchronized(serviceCache) {
751 if( serviceCache.isEmpty() ) {
752 if( retrieveGattServices ) {
754 if( serviceCache.isEmpty() ) {
755 return false;
756 }
757 } else {
758 return false;
759 }
760 }
761 return true;
762 }
763 }
764}
final void printDeviceLists()
Print the internally maintained BTDevice lists to stderr:
HCIStatusCode setPairingNumericComparison(final boolean equal)
Method sets the numeric comparison result, see PairingMode#NUMERIC_COMPARE_ini.
Definition: DBTDevice.java:576
final EInfoReport getEIR()
Return the merged advertised EInfoReport for this remote device.
Definition: DBTDevice.java:670
BDAddressAndType getVisibleAddressAndType()
Returns the devices' visible BDAddressAndType, i.e.
Definition: DBTDevice.java:167
HCIStatusCode connectLE(final short le_scan_interval, final short le_scan_window, final short conn_interval_min, final short conn_interval_max, final short conn_latency, final short timeout)
Establish a HCI BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM connection to this device.
Definition: DBTDevice.java:315
SMPPairingState getPairingState()
Returns the current SMPPairingState.
Definition: DBTDevice.java:588
final HCIStatusCode connectDefault()
jau.direct_bt: Establish a default HCI connection to this device, using certain default parameter.
Definition: DBTDevice.java:306
final long getLastUpdateTimestamp()
Returns the timestamp in monotonic milliseconds when this device instance underlying data has been up...
Definition: DBTDevice.java:138
final SMPLinkKey getLinkKey(final boolean responder)
Returns a copy of the Link Key (LK), valid after connection and SMP pairing has been completed.
Definition: DBTDevice.java:515
native int getResponderSMPPassKey()
Returns the responder SMP passkey, ranging from [0..999999].
final HCIStatusCode disconnect()
jau.direct_bt: Disconnect the LE or BREDR peer's GATT and HCI connection.
Definition: DBTDevice.java:286
final SMPIdentityResolvingKey getIdentityResolvingKey(final boolean responder)
Returns a copy of the Identity Resolving Key (IRK), valid after connection and SMP pairing has been c...
Definition: DBTDevice.java:483
boolean addCharListener(final BTGattCharListener listener, final BTGattChar associatedCharacteristic)
Please use BTGattChar#addCharListener(BTGattCharListener) for clarity.
Definition: DBTDevice.java:714
final SMPSignatureResolvingKey getSignatureResolvingKey(final boolean responder)
Returns a copy of the Signature Resolving Key (CSRK), valid after connection and SMP pairing has been...
Definition: DBTDevice.java:499
final String toString()
Definition: DBTDevice.java:594
final HCIStatusCode uploadKeys(final String smp_key_bin_path, final BTSecurityLevel req_min_level, final boolean verbose_)
Convenient combination of SMPKeyBin::read(), setSMPKeyBin() and uploadKeys() after validating given S...
Definition: DBTDevice.java:461
final LE_PHYs getTxPhys()
Return the Tx LE_PHYs as notified via LE_PHY_UPDATE_COMPLETE or retrieved via getConnectedLE_PHY(LE_P...
Definition: DBTDevice.java:274
HCIStatusCode setPairingPasskeyNegative()
Method replies with a negative passkey response, i.e.
Definition: DBTDevice.java:570
HCIStatusCode getConnectedLE_PHY(final LE_PHYs[] resTx, final LE_PHYs[] resRx)
Request and return LE_PHYs bit for the given connection.
Definition: DBTDevice.java:254
final BTRole getRole()
Return the fixed BTRole of this remote BTDevice.
Definition: DBTDevice.java:144
boolean pingGATT()
Issues a GATT ping to the device, validating whether it is still reachable.
Definition: DBTDevice.java:651
final long getCreationTimestamp()
Returns the timestamp in monotonic milliseconds when this device instance has been created,...
Definition: DBTDevice.java:132
final HCIStatusCode uploadKeys(final SMPKeyBin bin, final BTSecurityLevel req_min_level)
Convenient combination of setSMPKeyBin() and uploadKeys() after validating given SMPKeyBin file and S...
Definition: DBTDevice.java:452
BTGattChar findGattChar(final String char_uuid)
Find a BTGattChar by its char_uuid only.
Definition: DBTDevice.java:211
final HCIStatusCode unpair()
Unpair this device from the adapter while staying connected.
Definition: DBTDevice.java:531
String getName()
Returns the remote device name.
Definition: DBTDevice.java:170
final boolean isValid()
Returns whether the device is valid, i.e.
Definition: DBTDevice.java:622
BTGattService findGattService(final String service_uuid)
Find a BTGattService by its service_uuid.
Definition: DBTDevice.java:182
native short getRSSI()
Returns Received Signal Strength Indicator (RSSI) in dBm with ±6 dB accuracy of device as recognized ...
final boolean setConnSecurityAuto(final SMPIOCapability iocap_auto)
Set automatic security negotiation of BTSecurityLevel and SMPIOCapability pairing mode.
Definition: DBTDevice.java:555
List< BTGattService > getGattServices()
Returns a complete list of shared BTGattService available on this device, initially retrieved via GAT...
Definition: DBTDevice.java:626
final HCIStatusCode uploadKeys()
Upload all set keys to the adapter for pre-pairing.
Definition: DBTDevice.java:446
final BTSecurityLevel getConnSecurityLevel()
Return the BTSecurityLevel, determined when the connection is established.
Definition: DBTDevice.java:537
final boolean setSMPKeyBin(final SMPKeyBin bin)
Copy all keys from the given SMPKeyBin into this BTDevice.
Definition: DBTDevice.java:343
final long getLastDiscoveryTimestamp()
Returns the timestamp in monotonic milliseconds when this device instance has discovered or connected...
Definition: DBTDevice.java:135
final String getResponderSMPPassKeyString()
Returns getResponderSMPPassKey() as a canonical string, e.g.
Definition: DBTDevice.java:301
final void setIdentityResolvingKey(final SMPIdentityResolvingKey irk)
Sets the Identity Resolving Key (IRK) of this device for pre-paired encryption.
Definition: DBTDevice.java:491
EInfoReport getEIRInd()
Return the latest advertised EInfoReport AD_IND variant for this remote device.
Definition: DBTDevice.java:679
native boolean sendIndication(final short char_value_handle, final byte[] value)
Send an indication event consisting out of the given value representing the given characteristic valu...
final boolean getConnected()
Returns the connected state of the device.
Definition: DBTDevice.java:248
BDAddressAndType getAddressAndType()
Returns the devices' unique EUI48 address and BDAddressType type tuple, might be its initially report...
Definition: DBTDevice.java:164
native boolean removeCharListener(final BTGattCharListener l)
Remove the given BTGattCharListener from the listener list.
DBTAdapter getAdapter()
Returns the adapter on which this device was discovered or connected.
Definition: DBTDevice.java:141
native void deleteImpl(long nativeInstance)
Deletes the native instance.Called via delete() and at this point this java reference has been remove...
final SMPLongTermKey getLongTermKey(final boolean responder)
Returns a copy of the long term key (LTK), valid after connection and SMP pairing has been completed.
Definition: DBTDevice.java:467
native int removeAllAssociatedCharListener(final BTGattChar associatedCharacteristic)
Remove all BTGattCharListener from the list, which are associated to the given BTGattChar.
native int removeAllCharListener()
Remove all BTGattCharListener from the list.
void close()
Release the native memory associated with this object The object should not be used following a call ...
Definition: DBTDevice.java:115
final boolean addStatusListener(final AdapterStatusListener l)
Add the given AdapterStatusListener to the list if not already present, listening only for events mat...
Definition: DBTDevice.java:238
EInfoReport getEIRScanRsp()
Return the latest advertised EInfoReport AD_SCAN_RSP for this remote device.
Definition: DBTDevice.java:688
boolean removeStatusListener(final AdapterStatusListener l)
Remove the given AdapterStatusListener from the list.
Definition: DBTDevice.java:243
final void setLinkKey(final SMPLinkKey lk)
Sets the Link Key (LK) of this device for pre-paired encryption.
Definition: DBTDevice.java:523
native short getTxPower()
Return Tx Power Level in dBm with ±6 dB accuracy of device as recognized at discovery and connect.
final SMPIOCapability getConnIOCapability()
Return the SMPIOCapability value, determined when the connection is established.
Definition: DBTDevice.java:543
native boolean sendNotification(final short char_value_handle, final byte[] value)
Send a notification event consisting out of the given value representing the given characteristic val...
final void setSignatureResolvingKey(final SMPSignatureResolvingKey irk)
Sets the Signature Resolving Key (CSRK) of this device for pre-paired encryption.
Definition: DBTDevice.java:507
BTGattChar findGattChar(final String service_uuid, final String char_uuid)
Find a BTGattChar by its service_uuid and char_uuid.
Definition: DBTDevice.java:202
final boolean setConnSecurity(final BTSecurityLevel sec_level, final SMPIOCapability io_cap)
Sets the given BTSecurityLevel and SMPIOCapability used to connect to this device on the upcoming con...
Definition: DBTDevice.java:549
final SMPKeyMask getAvailableSMPKeys(final boolean responder)
Returns the available SMPKeyMask.KeyType SMPKeyMask for the responder (LL slave) or initiator (LL mas...
Definition: DBTDevice.java:337
final short getConnectionHandle()
Return the HCI connection handle to the LE or BREDR peer, zero if not connected.
Definition: DBTDevice.java:251
final LE_PHYs getRxPhys()
Return the Rx LE_PHYs as notified via LE_PHY_UPDATE_COMPLETE or retrieved via getConnectedLE_PHY(LE_P...
Definition: DBTDevice.java:280
final native boolean isConnSecurityAutoEnabled()
Returns true if automatic security negotiation has been enabled via setConnSecurityAuto(SMPIOCapabili...
boolean equals(final Object obj)
Definition: DBTDevice.java:150
final void setLongTermKey(final SMPLongTermKey ltk)
Sets the Long Term Key (LTK) of this device for pre-paired encryption.
Definition: DBTDevice.java:475
PairingMode getPairingMode()
Returns the current PairingMode used by the device.
Definition: DBTDevice.java:582
HCIStatusCode setConnectedLE_PHY(final LE_PHYs Tx, final LE_PHYs Rx)
Sets preference of used LE_PHYs for the given connection.
Definition: DBTDevice.java:268
boolean addCharListener(final BTGattCharListener listener)
Add the given BTGattCharListener to the listener list if not already present.
Definition: DBTDevice.java:709
native boolean isPrePaired()
Returns true if this device has completed SMP pairing or keys are set via uploadKeys()
HCIStatusCode setPairingPasskey(final int passkey)
Method sets the given passkey entry, see PairingMode#PASSKEY_ENTRY_ini.
Definition: DBTDevice.java:564
String getUUID()
Get the UUID of this service.
BTGattChar findGattChar(final String char_uuid)
Find a BTGattChar by its char_uuid.
static final boolean DEBUG
Definition: DBTManager.java:43
BTAdapter status listener for remote BTDevice discovery events: Added, updated and removed; as well a...
Unique Bluetooth EUI48 address and BDAddressType tuple.
final boolean equals(final Object obj)
If both types are of BDAddressAndType, it compares their EUI48 address and BDAddressType.
BTGattChar event listener for notification and indication events.
Collection of 'Extended Advertising Data' (EAD), 'Advertising Data' (AD) or 'Extended Inquiry Respons...
LE Transport PHY bit values (bitmask)
Definition: LE_PHYs.java:36
SMP Identity Resolving Key, used for platform agnostic persistence.
static final int byte_size
Size of the byte stream representation in bytes.
final void put(final byte[] sink, int pos)
Method transfers all bytes representing this instance into the given destination array at the given p...
Storage for SMP keys including required connection parameter per local adapter and remote device.
Definition: SMPKeyBin.java:75
static SMPKeyBin read(final String fname, final boolean verbose_)
Create a new SMPKeyBin instance based upon stored file denoted by fname.
Definition: SMPKeyBin.java:258
final boolean hasIRKInit()
Definition: SMPKeyBin.java:369
final BDAddressAndType getRemoteAddrAndType()
Return the remote device address.
Definition: SMPKeyBin.java:357
final BDAddressAndType getLocalAddrAndType()
Return the local adapter address.
Definition: SMPKeyBin.java:354
final boolean hasLKResp()
Definition: SMPKeyBin.java:400
final SMPLongTermKey getLTKResp()
Definition: SMPKeyBin.java:401
final boolean hasCSRKResp()
Definition: SMPKeyBin.java:399
final SMPSignatureResolvingKey getCSRKResp()
Definition: SMPKeyBin.java:403
final boolean hasLTKResp()
Definition: SMPKeyBin.java:397
final boolean hasLKInit()
Definition: SMPKeyBin.java:371
final boolean hasLTKInit()
Definition: SMPKeyBin.java:368
final SMPSignatureResolvingKey getCSRKInit()
Definition: SMPKeyBin.java:374
final BTRole getLocalRole()
Return the local adapter BTRole.
Definition: SMPKeyBin.java:351
final SMPLinkKey getLKInit()
Definition: SMPKeyBin.java:375
final SMPLinkKey getLKResp()
Definition: SMPKeyBin.java:404
final BTSecurityLevel getSecLevel()
Definition: SMPKeyBin.java:365
final SMPIdentityResolvingKey getIRKResp()
Definition: SMPKeyBin.java:402
final SMPLongTermKey getLTKInit()
Definition: SMPKeyBin.java:372
final boolean hasCSRKInit()
Definition: SMPKeyBin.java:370
final boolean isValid()
Definition: SMPKeyBin.java:428
final String toString()
Definition: SMPKeyBin.java:470
final SMPIdentityResolvingKey getIRKInit()
Definition: SMPKeyBin.java:373
final boolean hasIRKResp()
Definition: SMPKeyBin.java:398
SMP Key Type for Distribution, indicates keys distributed in the Transport Specific Key Distribution ...
Definition: SMPKeyMask.java:44
Local SMP Link Key, used for platform agnostic persistence, mapping to platform specific link keys fo...
Definition: SMPLinkKey.java:42
static final int byte_size
Size of the byte stream representation in bytes.
final void put(final byte[] sink, int pos)
Method transfers all bytes representing this instance into the given destination array at the given p...
SMP Long Term Key, used for platform agnostic persistence.
static final int byte_size
Size of the byte stream representation in bytes (28)
final void put(final byte[] sink, int pos)
Method transfers all bytes representing this instance into the given destination array at the given p...
SMP Signature Resolving Key, used for platform agnostic persistence.
final void put(final byte[] sink, int pos)
Method transfers all bytes representing this instance into the given destination array at the given p...
static final int byte_size
Size of the byte stream representation in bytes.
Bluetooth address type constants.
Bluetooth roles from the perspective of the link layer (connection initiator).
Definition: BTRole.java:36
static BTRole get(final String name)
Maps the specified name to a constant of BTRole.
Definition: BTRole.java:57
final BTRole reverse()
Returns reversed roled.
Definition: BTRole.java:79
Bluetooth Security Level.
NONE
No encryption and no authentication.
ENC_ONLY
Encryption and no authentication (no MITM).
static BTSecurityLevel get(final String name)
Maps the specified name to a constant of BTSecurityLevel.
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
static HCIStatusCode get(final String name)
Maps the specified name to a constant of HCIStatusCode.
Each enum represents a 'LE Transport PHY' bit value.
Definition: LE_PHYs.java:43
Bluetooth secure pairing mode.
static PairingMode get(final String name)
Maps the specified name to a constant of PairingMode.
SMP IO Capability value.
NO_INPUT_NO_OUTPUT
No input not output, value 3.
static SMPIOCapability get(final String name)
Maps the specified name to a constant of SMPIOCapability.
SMP Pairing Process state definition.
static SMPPairingState get(final String name)
Maps the specified name to a constant of SMPPairingState.
BTDevice represents one remote Bluetooth device.
Definition: BTDevice.java:47
Representing a Gatt Characteristic object from the GATT client perspective.
Definition: BTGattChar.java:49
Representing a Gatt Service object from the GATT client perspective.
BTGattChar findGattChar(String char_uuid)
Find a BTGattChar by its char_uuid.