Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
DBTDevice.cxx
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 "jau_direct_bt_DBTDevice.h"
27#include "org_direct_bt_BTGattCharListener.h"
28
29// #define VERBOSE_ON 1
30#include <jau/debug.hpp>
31
32#include "helper_base.hpp"
33#include "helper_dbt.hpp"
34
39
40using namespace direct_bt;
41using namespace jau::jni;
42
43static const std::string _notificationReceivedMethodArgs("(Lorg/direct_bt/BTGattChar;[BJ)V");
44static const std::string _indicationReceivedMethodArgs("(Lorg/direct_bt/BTGattChar;[BJZ)V");
45
47 private:
48 /**
49 public abstract class BTGattCharListener {
50 public void notificationReceived(final BTGattChar charDecl,
51 final byte[] value, final long timestamp) {
52 }
53
54 public void indicationReceived(final BTGattChar charDecl,
55 final byte[] value, final long timestamp,
56 final boolean confirmationSent) {
57 }
58
59 };
60 */
61 JNIGlobalRef listenerObj; // keep listener instance alive
62 jmethodID mNotificationReceived = nullptr;
63 jmethodID mIndicationReceived = nullptr;
64
65 public:
66
67 JNIGattCharListener(JNIEnv *env, jobject listener)
68 : listenerObj(listener)
69 {
70 jclass listenerClazz = search_class(env, listenerObj.getObject());
72 if( nullptr == listenerClazz ) {
73 throw jau::InternalError("BTGattCharListener not found", E_FILE_LINE);
74 }
75
76 mNotificationReceived = search_method(env, listenerClazz, "notificationReceived", _notificationReceivedMethodArgs.c_str(), false);
78
79 mIndicationReceived = search_method(env, listenerClazz, "indicationReceived", _indicationReceivedMethodArgs.c_str(), false);
81 }
82
84 const jau::TROOctets& charValue, const uint64_t timestamp) override {
85 JavaAnonRef jCharDeclRef = charDecl->getJavaObject();
86 if( !JavaGlobalObj::isValid(jCharDeclRef) ) {
87 return; // java object has been pulled
88 }
89 JNIEnv *env = *jni_env;
90 jobject jCharDecl = JavaGlobalObj::GetObject(jCharDeclRef);
91
92 const size_t value_size = charValue.size();
93 jbyteArray jval = env->NewByteArray((jsize)value_size);
94 env->SetByteArrayRegion(jval, 0, (jsize)value_size, (const jbyte *)charValue.get_ptr());
96
97 env->CallVoidMethod(listenerObj.getObject(), mNotificationReceived,
98 jCharDecl, jval, (jlong)timestamp);
100 env->DeleteLocalRef(jval);
101 }
102
104 const jau::TROOctets& charValue, const uint64_t timestamp,
105 const bool confirmationSent) override {
106 JavaAnonRef jCharDeclRef = charDecl->getJavaObject();
107 if( !JavaGlobalObj::isValid(jCharDeclRef) ) {
108 return; // java object has been pulled
109 }
110 JNIEnv *env = *jni_env;
111 jobject jCharDecl = JavaGlobalObj::GetObject(jCharDeclRef);
112
113 const size_t value_size = charValue.size();
114 jbyteArray jval = env->NewByteArray((jsize)value_size);
115 env->SetByteArrayRegion(jval, 0, (jsize)value_size, (const jbyte *)charValue.get_ptr());
117
118 env->CallVoidMethod(listenerObj.getObject(), mIndicationReceived,
119 jCharDecl, jval, (jlong)timestamp, (jboolean)confirmationSent);
121 env->DeleteLocalRef(jval);
122 }
123};
124
125/*
126 * Class: org_direct_bt_BTGattCharListener
127 * Method: ctorImpl
128 * Signature: ()J
129 */
130jlong Java_org_direct_1bt_BTGattCharListener_ctorImpl(JNIEnv *env, jobject obj) {
131 try {
132 // new instance
134
135 return ref.release_to_jlong();
136 } catch(...) {
138 }
139 return (jlong) (intptr_t) nullptr;
140}
141
142
143/*
144 * Class: org_direct_bt_BTGattCharListener
145 * Method: deleteImpl
146 * Signature: (J)V
147 */
148void Java_org_direct_1bt_BTGattCharListener_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance) {
149 (void)obj;
150 try {
151 shared_ptr_ref<JNIGattCharListener> sref(nativeInstance, false /* throw_on_nullptr */); // hold copy until done
152 if( nullptr != sref.pointer() ) {
153 std::shared_ptr<JNIGattCharListener>* sref_ptr = castInstance<JNIGattCharListener>(nativeInstance);
154 delete sref_ptr;
155 }
156 } catch(...) {
158 }
159}
160
161void Java_jau_direct_1bt_DBTDevice_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
162{
163 (void)obj;
164 try {
165 shared_ptr_ref<BTDevice> sref(nativeInstance, false /* throw_on_nullptr */); // hold copy until done
166 if( nullptr != sref.pointer() ) {
167 if( !sref.is_null() ) {
168 DBG_PRINT("Java_jau_direct_1bt_DBTDevice_deleteImpl (w/ remove) %s", sref->toString().c_str());
169 sref->remove();
170 } else {
171 DBG_PRINT("Java_jau_direct_1bt_DBTDevice_deleteImpl null reference");
172 }
173 std::shared_ptr<BTDevice>* sref_ptr = castInstance<BTDevice>(nativeInstance);
174 delete sref_ptr;
175 } else {
176 DBG_PRINT("Java_jau_direct_1bt_DBTDevice_deleteImpl null reference store");
177 }
178 } catch(...) {
180 }
181}
182
183void Java_jau_direct_1bt_DBTDevice_initImpl(JNIEnv *env, jobject obj)
184{
185 try {
186 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
187 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
188 JavaGlobalObj::check(device_java, E_FILE_LINE);
189 } catch(...) {
191 }
192}
193
194jstring Java_jau_direct_1bt_DBTDevice_getNameImpl(JNIEnv *env, jobject obj) {
195 try {
196 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
197 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
198 JavaGlobalObj::check(device_java, E_FILE_LINE);
199 return from_string_to_jstring(env, device->getName());
200 } catch(...) {
202 }
203 return nullptr;
204}
205
206jstring Java_jau_direct_1bt_DBTDevice_toStringImpl(JNIEnv *env, jobject obj) {
207 try {
208 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
209 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
210 JavaGlobalObj::check(device_java, E_FILE_LINE);
211 return from_string_to_jstring(env, device->toString());
212 } catch(...) {
214 }
215 return nullptr;
216}
217
218jbyteArray Java_jau_direct_1bt_DBTDevice_getAddressImpl(JNIEnv *env, jobject obj) {
219 try {
220 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
221 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
222 JavaGlobalObj::check(device_java, E_FILE_LINE);
223 const EUI48 & addr = device->getAddressAndType().address;
224 jbyteArray jaddr = env->NewByteArray(sizeof(addr));
225 env->SetByteArrayRegion(jaddr, 0, sizeof(addr), (const jbyte*)(addr.b));
226 return jaddr;
227 } catch(...) {
229 }
230 return nullptr;
231}
232
234 try {
235 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
236 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
237 JavaGlobalObj::check(device_java, E_FILE_LINE);
238 return static_cast<jbyte>( number( device->getAddressAndType().type ) );
239 } catch(...) {
241 }
242 return 0;
243}
244
245/*
246 * Class: jau_direct_bt_DBTDevice
247 * Method: addCharListenerImpl
248 * Signature: (Lorg/direct_bt/BTGattCharListener;Lorg/direct_bt/BTGattChar;)Z
249 */
250jboolean Java_jau_direct_1bt_DBTDevice_addCharListenerImpl(JNIEnv *env, jobject obj, jobject jlistener, jobject jAssociatedCharacteristic) {
251 try {
252 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
253 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
254 JavaGlobalObj::check(device_java, E_FILE_LINE);
255
256 shared_ptr_ref<JNIGattCharListener> gcl(env, jlistener); // hold until done
257 JavaAnonRef gcl_java = gcl->getJavaObject(); // hold until done!
258 JavaGlobalObj::check(gcl_java, E_FILE_LINE);
259
260 shared_ptr_ref<BTGattChar> charMatchRef(env, jAssociatedCharacteristic, false /* throw_on_nullptr */);
261 if( !charMatchRef.is_null() ) {
262 JavaGlobalObj::check(charMatchRef->getJavaObject(), E_FILE_LINE);
263 }
264
265 std::shared_ptr<BTGattHandler> gatt = device->getGattHandler();
266 if( nullptr == gatt ) {
267 ERR_PRINT("BTGattChar's device GATTHandle not connected: %s", device->toString().c_str());
268 return false;
269 }
270
271 bool addRes;
272 if( !charMatchRef.is_null() ) {
273 addRes = gatt->addCharListener( gcl.shared_ptr(), charMatchRef.shared_ptr() );
274 } else {
275 addRes = gatt->addCharListener( gcl.shared_ptr() );
276 }
277 if( addRes ) {
278 return JNI_TRUE;
279 }
280 ERR_PRINT("BTDevice::addCharListener: FAILED: %s", gcl->toString().c_str());
281 } catch(...) {
283 }
284 return JNI_FALSE;
285}
286
287jboolean Java_jau_direct_1bt_DBTDevice_removeCharListener(JNIEnv *env, jobject obj, jobject jlistener) {
288 try {
289 shared_ptr_ref<BTDevice> device(env, obj, false /* throw_on_nullptr */); // hold until done
290 if( device.is_null() ) {
291 // OK to have device being deleted already @ shutdown
292 return JNI_FALSE;
293 }
294 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
295 JavaGlobalObj::check(device_java, E_FILE_LINE);
296
297 shared_ptr_ref<JNIGattCharListener> gcl(env, jlistener); // hold until done
298 JavaAnonRef gcl_java = gcl->getJavaObject(); // hold until done!
299 JavaGlobalObj::check(gcl_java, E_FILE_LINE);
300
301 std::shared_ptr<BTGattHandler> gatt = device->getGattHandler();
302 if( nullptr == gatt ) {
303 // OK to have BTGattHandler being shutdown @ disable
304 DBG_PRINT("BTGattChar's device GATTHandle not connected: %s", device->toString().c_str());
305 return false;
306 }
307
308 if( ! gatt->removeCharListener(gcl.shared_ptr()) ) {
309 WARN_PRINT("Failed to remove BTGattCharListener with nativeInstance: %p at %s", gcl.shared_ptr().get(), device->toString().c_str());
310 return false;
311 }
312 return true;
313 } catch(...) {
315 }
316 return JNI_FALSE;
317}
318
319jint Java_jau_direct_1bt_DBTDevice_removeAllAssociatedCharListener(JNIEnv *env, jobject obj, jobject jAssociatedCharacteristic) {
320 try {
321 shared_ptr_ref<BTDevice> device(env, obj, false /* throw_on_nullptr */); // hold until done
322 if( device.is_null() ) {
323 // OK to have device being deleted already @ shutdown
324 return 0;
325 }
326 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
327 JavaGlobalObj::check(device_java, E_FILE_LINE);
328
329 shared_ptr_ref<BTGattChar> associatedCharacteristicRef(env, jAssociatedCharacteristic);
330 JavaAnonRef device_gattchar = associatedCharacteristicRef->getJavaObject(); // hold until done!
331 JavaGlobalObj::check(device_gattchar, E_FILE_LINE);
332
333 std::shared_ptr<BTGattHandler> gatt = device->getGattHandler();
334 if( nullptr == gatt ) {
335 // OK to have BTGattHandler being shutdown @ disable
336 DBG_PRINT("BTGattChar's device GATTHandle not connected: %s", device->toString().c_str());
337 return 0;
338 }
339
340 return (jint) gatt->removeAllAssociatedCharListener(associatedCharacteristicRef.shared_ptr());
341 } catch(...) {
343 }
344 return 0;
345}
346
348 try {
349 shared_ptr_ref<BTDevice> device(env, obj, false /* throw_on_nullptr */); // hold until done
350 if( device.is_null() ) {
351 // OK to have device being deleted already @ shutdown
352 return 0;
353 }
354 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
355 JavaGlobalObj::check(device_java, E_FILE_LINE);
356
357 std::shared_ptr<BTGattHandler> gatt = device->getGattHandler();
358 if( nullptr == gatt ) {
359 // OK to have BTGattHandler being shutdown @ disable
360 DBG_PRINT("BTGattChar's device GATTHandle not connected: %s", device->toString().c_str());
361 return 0;
362 }
363 return (jint) gatt->removeAllCharListener();
364 } catch(...) {
366 }
367 return 0;
368}
369
370jbyte Java_jau_direct_1bt_DBTDevice_getRoleImpl(JNIEnv *env, jobject obj)
371{
372 try {
373 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
374 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
375 JavaGlobalObj::check(device_java, E_FILE_LINE);
376 return (jbyte) number( device->getRole() );
377 } catch(...) {
379 }
380 return (jbyte) number( BTRole::None );
381}
382
384 jbyteArray jresTx, jbyteArray jresRx) {
385 try {
386 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
387 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
388 JavaGlobalObj::check(device_java, E_FILE_LINE);
389
390 if( nullptr == jresTx ) {
391 throw jau::IllegalArgumentException("resTx byte array null", E_FILE_LINE);
392 }
393 if( nullptr == jresRx ) {
394 throw jau::IllegalArgumentException("resRx byte array null", E_FILE_LINE);
395 }
396
397 const size_t resTx_size = env->GetArrayLength(jresTx);
398 if( 1 > resTx_size ) {
399 throw jau::IllegalArgumentException("resTx byte array "+std::to_string(resTx_size)+" < 1", E_FILE_LINE);
400 }
401 const size_t resRx_size = env->GetArrayLength(jresRx);
402 if( 1 > resRx_size ) {
403 throw jau::IllegalArgumentException("resRx byte array "+std::to_string(resRx_size)+" < 1", E_FILE_LINE);
404 }
405
406 JNICriticalArray<uint8_t, jbyteArray> criticalArrayTx(env); // RAII - release
407 uint8_t * resTx_ptr = criticalArrayTx.get(jresTx, criticalArrayTx.Mode::UPDATE_AND_RELEASE);
408 if( nullptr == resTx_ptr ) {
409 throw jau::InternalError("GetPrimitiveArrayCritical(resTx byte array) is null", E_FILE_LINE);
410 }
411 JNICriticalArray<uint8_t, jbyteArray> criticalArrayRx(env); // RAII - release
412 uint8_t * resRx_ptr = criticalArrayRx.get(jresRx, criticalArrayTx.Mode::UPDATE_AND_RELEASE);
413 if( nullptr == resRx_ptr ) {
414 throw jau::InternalError("GetPrimitiveArrayCritical(resRx byte array) is null", E_FILE_LINE);
415 }
416
417 LE_PHYs& resTx = *reinterpret_cast<LE_PHYs *>(resTx_ptr);
418 LE_PHYs& resRx = *reinterpret_cast<LE_PHYs *>(resRx_ptr);
419
420 return (jbyte) number( device->getConnectedLE_PHY(resTx, resRx) );
421 } catch(...) {
423 }
424 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
425}
426
428 jbyte jTx, jbyte jRx) {
429 try {
430 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
431 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
432 JavaGlobalObj::check(device_java, E_FILE_LINE);
433
434 const LE_PHYs Tx = static_cast<LE_PHYs>(jTx);
435 const LE_PHYs Rx = static_cast<LE_PHYs>(jRx);
436
437 return (jbyte)number ( device->setConnectedLE_PHY(Tx, Rx) );
438 } catch(...) {
440 }
441 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
442}
443
444jbyte Java_jau_direct_1bt_DBTDevice_getTxPhysImpl(JNIEnv *env, jobject obj) {
445 try {
446 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
447 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
448 JavaGlobalObj::check(device_java, E_FILE_LINE);
449
450 return (jbyte) number( device->getTxPhys() );
451 } catch(...) {
453 }
454 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
455}
456
457jbyte Java_jau_direct_1bt_DBTDevice_getRxPhysImpl(JNIEnv *env, jobject obj) {
458 try {
459 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
460 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
461 JavaGlobalObj::check(device_java, E_FILE_LINE);
462
463 return (jbyte) number( device->getRxPhys() );
464 } catch(...) {
466 }
467 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
468}
469
470jbyte Java_jau_direct_1bt_DBTDevice_disconnectImpl(JNIEnv *env, jobject obj)
471{
472 try {
473 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
474 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
475 JavaGlobalObj::check(device_java, E_FILE_LINE);
476 return (jbyte) number( device->disconnect() );
477 } catch(...) {
479 }
480 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
481}
482
483jboolean Java_jau_direct_1bt_DBTDevice_isPrePaired(JNIEnv *env, jobject obj) {
484 try {
485 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
486 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
487 JavaGlobalObj::check(device_java, E_FILE_LINE);
488
489 return device->isPrePaired() ? JNI_TRUE : JNI_FALSE;
490 } catch(...) {
492 }
493 return JNI_FALSE;
494}
495
497 try {
498 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
499 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
500 JavaGlobalObj::check(device_java, E_FILE_LINE);
501
502 return static_cast<jint>( device->getResponderSMPPassKey() );
503 } catch(...) {
505 }
506 return 999999;
507}
508
509jboolean Java_jau_direct_1bt_DBTDevice_removeImpl(JNIEnv *env, jobject obj)
510{
511 try {
512 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
513 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
514 JavaGlobalObj::check(device_java, E_FILE_LINE);
515 device->remove();
516 } catch(...) {
518 }
519 return JNI_TRUE;
520}
521
523{
524 try {
525 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
526 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
527 JavaGlobalObj::check(device_java, E_FILE_LINE);
528 return (jbyte) number( device->connectDefault() );
529 } catch(...) {
531 }
532 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
533}
534
535jbyte Java_jau_direct_1bt_DBTDevice_connectLEImpl0(JNIEnv *env, jobject obj)
536{
537 try {
538 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
539 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
540 JavaGlobalObj::check(device_java, E_FILE_LINE);
541 HCIStatusCode res = device->connectLE();
542 return (jbyte) number(res);
543 } catch(...) {
545 }
546 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
547}
548
549jbyte Java_jau_direct_1bt_DBTDevice_connectLEImpl1(JNIEnv *env, jobject obj,
550 jshort interval, jshort window,
551 jshort min_interval, jshort max_interval,
552 jshort latency, jshort timeout)
553{
554 try {
555 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
556 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
557 JavaGlobalObj::check(device_java, E_FILE_LINE);
558 HCIStatusCode res = device->connectLE(interval, window, min_interval, max_interval, latency, timeout);
559 return (jbyte) number(res);
560 } catch(...) {
562 }
563 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
564}
565
566jbyte Java_jau_direct_1bt_DBTDevice_getAvailableSMPKeysImpl(JNIEnv *env, jobject obj, jboolean responder) {
567 try {
568 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
569 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
570 JavaGlobalObj::check(device_java, E_FILE_LINE);
571
572 return (jbyte) number( device->getAvailableSMPKeys(JNI_TRUE == responder) );
573 } catch(...) {
575 }
576 return 0;
577}
578
579jbyte Java_jau_direct_1bt_DBTDevice_uploadKeysImpl(JNIEnv *env, jobject obj) {
580 try {
581 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
582 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
583 JavaGlobalObj::check(device_java, E_FILE_LINE);
584
585 return (jbyte) number( device->uploadKeys() );
586 } catch(...) {
588 }
589 return 0;
590}
591
592void Java_jau_direct_1bt_DBTDevice_getLongTermKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink) {
593 try {
594 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
595 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
596 JavaGlobalObj::check(device_java, E_FILE_LINE);
597
598 if( nullptr == jsink ) {
599 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
600 }
601 const size_t sink_size = env->GetArrayLength(jsink);
602 if( sizeof(SMPLongTermKey) > sink_size ) {
603 throw jau::IllegalArgumentException("byte array "+std::to_string(sink_size)+" < "+std::to_string(sizeof(SMPLongTermKey)), E_FILE_LINE);
604 }
605 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
606 uint8_t * sink_ptr = criticalArray.get(jsink, criticalArray.Mode::UPDATE_AND_RELEASE);
607 if( nullptr == sink_ptr ) {
608 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
609 }
610 SMPLongTermKey& ltk_sink = *reinterpret_cast<SMPLongTermKey *>(sink_ptr);
611 ltk_sink = device->getLongTermKey(JNI_TRUE == responder); // assign data of new key copy to JNI critical-array
612 } catch(...) {
614 }
615}
616
617void Java_jau_direct_1bt_DBTDevice_setLongTermKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource) {
618 try {
619 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
620 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
621 JavaGlobalObj::check(device_java, E_FILE_LINE);
622
623 if( nullptr == jsource ) {
624 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
625 }
626 const size_t source_size = env->GetArrayLength(jsource);
627 if( sizeof(SMPLongTermKey) > source_size ) {
628 throw jau::IllegalArgumentException("byte array "+std::to_string(source_size)+" < "+std::to_string(sizeof(SMPLongTermKey)), E_FILE_LINE);
629 }
630 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
631 uint8_t * source_ptr = criticalArray.get(jsource, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
632 if( nullptr == source_ptr ) {
633 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
634 }
635 const SMPLongTermKey& ltk = *reinterpret_cast<SMPLongTermKey *>(source_ptr);
636
637 device->setLongTermKey(ltk);
638 } catch(...) {
640 }
641}
642
643void Java_jau_direct_1bt_DBTDevice_getIdentityResolvingKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink) {
644 try {
645 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
646 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
647 JavaGlobalObj::check(device_java, E_FILE_LINE);
648
649 if( nullptr == jsink ) {
650 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
651 }
652 const size_t sink_size = env->GetArrayLength(jsink);
653 if( sizeof(SMPIdentityResolvingKey) > sink_size ) {
655 }
656 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
657 uint8_t * sink_ptr = criticalArray.get(jsink, criticalArray.Mode::UPDATE_AND_RELEASE);
658 if( nullptr == sink_ptr ) {
659 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
660 }
661 SMPIdentityResolvingKey& irk_sink = *reinterpret_cast<SMPIdentityResolvingKey *>(sink_ptr);
662 irk_sink = device->getIdentityResolvingKey(JNI_TRUE == responder); // assign data of new key copy to JNI critical-array
663 } catch(...) {
665 }
666}
667
668void Java_jau_direct_1bt_DBTDevice_setIdentityResolvingKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource) {
669 try {
670 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
671 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
672 JavaGlobalObj::check(device_java, E_FILE_LINE);
673
674 if( nullptr == jsource ) {
675 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
676 }
677 const size_t source_size = env->GetArrayLength(jsource);
678 if( sizeof(SMPIdentityResolvingKey) > source_size ) {
680 }
681 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
682 uint8_t * source_ptr = criticalArray.get(jsource, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
683 if( nullptr == source_ptr ) {
684 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
685 }
686 const SMPIdentityResolvingKey& irk = *reinterpret_cast<SMPIdentityResolvingKey *>(source_ptr);
687
688 device->setIdentityResolvingKey(irk);
689 } catch(...) {
691 }
692}
693
694void Java_jau_direct_1bt_DBTDevice_getSignatureResolvingKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink) {
695 try {
696 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
697 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
698 JavaGlobalObj::check(device_java, E_FILE_LINE);
699
700 if( nullptr == jsink ) {
701 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
702 }
703 const size_t sink_size = env->GetArrayLength(jsink);
704 if( sizeof(SMPSignatureResolvingKey) > sink_size ) {
706 }
707 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
708 uint8_t * sink_ptr = criticalArray.get(jsink, criticalArray.Mode::UPDATE_AND_RELEASE);
709 if( nullptr == sink_ptr ) {
710 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
711 }
712 SMPSignatureResolvingKey& irk_sink = *reinterpret_cast<SMPSignatureResolvingKey *>(sink_ptr);
713 irk_sink = device->getSignatureResolvingKey(JNI_TRUE == responder); // assign data of new key copy to JNI critical-array
714 } catch(...) {
716 }
717}
718
719void Java_jau_direct_1bt_DBTDevice_setSignatureResolvingKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource) {
720 try {
721 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
722 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
723 JavaGlobalObj::check(device_java, E_FILE_LINE);
724
725 if( nullptr == jsource ) {
726 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
727 }
728 const size_t source_size = env->GetArrayLength(jsource);
729 if( sizeof(SMPSignatureResolvingKey) > source_size ) {
731 }
732 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
733 uint8_t * source_ptr = criticalArray.get(jsource, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
734 if( nullptr == source_ptr ) {
735 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
736 }
737 const SMPSignatureResolvingKey& irk = *reinterpret_cast<SMPSignatureResolvingKey *>(source_ptr);
738
739 device->setSignatureResolvingKey(irk);
740 } catch(...) {
742 }
743}
744
745void Java_jau_direct_1bt_DBTDevice_getLinkKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink) {
746 try {
747 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
748 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
749 JavaGlobalObj::check(device_java, E_FILE_LINE);
750
751 if( nullptr == jsink ) {
752 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
753 }
754 const size_t sink_size = env->GetArrayLength(jsink);
755 if( sizeof(SMPLinkKey) > sink_size ) {
756 throw jau::IllegalArgumentException("byte array "+std::to_string(sink_size)+" < "+std::to_string(sizeof(SMPLinkKey)), E_FILE_LINE);
757 }
758 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
759 uint8_t * sink_ptr = criticalArray.get(jsink, criticalArray.Mode::UPDATE_AND_RELEASE);
760 if( nullptr == sink_ptr ) {
761 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
762 }
763 SMPLinkKey& lk_sink = *reinterpret_cast<SMPLinkKey *>(sink_ptr);
764 lk_sink = device->getLinkKey(JNI_TRUE == responder); // assign data of new key copy to JNI critical-array
765 } catch(...) {
767 }
768}
769
770void Java_jau_direct_1bt_DBTDevice_setLinkKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource) {
771 try {
772 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
773 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
774 JavaGlobalObj::check(device_java, E_FILE_LINE);
775
776 if( nullptr == jsource ) {
777 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
778 }
779 const size_t source_size = env->GetArrayLength(jsource);
780 if( sizeof(SMPLinkKey) > source_size ) {
781 throw jau::IllegalArgumentException("byte array "+std::to_string(source_size)+" < "+std::to_string(sizeof(SMPLinkKey)), E_FILE_LINE);
782 }
783 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
784 uint8_t * source_ptr = criticalArray.get(jsource, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
785 if( nullptr == source_ptr ) {
786 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
787 }
788 const SMPLinkKey& lk = *reinterpret_cast<SMPLinkKey *>(source_ptr);
789
790 device->setLinkKey(lk);
791 } catch(...) {
793 }
794}
795
796jbyte Java_jau_direct_1bt_DBTDevice_unpairImpl(JNIEnv *env, jobject obj) {
797 try {
798 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
799 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
800 JavaGlobalObj::check(device_java, E_FILE_LINE);
801 HCIStatusCode res = device->unpair();
802 return (jbyte) number(res);
803 } catch(...) {
805 }
806 return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
807}
808
810 try {
811 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
812 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
813 JavaGlobalObj::check(device_java, E_FILE_LINE);
814
815 return (jbyte) number( device->getConnSecurityLevel() );
816 } catch(...) {
818 }
819 return number( BTSecurityLevel::UNSET );
820}
821
823 try {
824 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
825 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
826 JavaGlobalObj::check(device_java, E_FILE_LINE);
827
828 return (jbyte) number( device->getConnIOCapability() );
829 } catch(...) {
831 }
832 return (jbyte) number( SMPIOCapability::UNSET );
833}
834
835jboolean Java_jau_direct_1bt_DBTDevice_setConnSecurityImpl(JNIEnv *env, jobject obj, jbyte jsec_level, jbyte jio_cap) {
836 try {
837 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
838 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
839 JavaGlobalObj::check(device_java, E_FILE_LINE);
840
841 return device->setConnSecurity( to_BTSecurityLevel( static_cast<uint8_t>(jsec_level) ),
842 to_SMPIOCapability( static_cast<uint8_t>(jio_cap) ) );
843 } catch(...) {
845 }
846 return JNI_FALSE;
847}
848
849jboolean Java_jau_direct_1bt_DBTDevice_setConnSecurityAutoImpl(JNIEnv *env, jobject obj, jbyte jio_cap) {
850 try {
851 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
852 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
853 JavaGlobalObj::check(device_java, E_FILE_LINE);
854
855 return device->setConnSecurityAuto( to_SMPIOCapability( static_cast<uint8_t>(jio_cap) ) );
856 } catch(...) {
858 }
859 return JNI_FALSE;
860}
861
863 try {
864 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
865 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
866 JavaGlobalObj::check(device_java, E_FILE_LINE);
867
868 return device->isConnSecurityAutoEnabled();
869 } catch(...) {
871 }
872 return JNI_FALSE;
873}
874
876 try {
877 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
878 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
879 JavaGlobalObj::check(device_java, E_FILE_LINE);
880
881 return (jbyte) number( device->getPairingMode() );
882 } catch(...) {
884 }
885 return number( PairingMode::NONE );
886}
887
889 try {
890 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
891 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
892 JavaGlobalObj::check(device_java, E_FILE_LINE);
893
894 return (jbyte) static_cast<uint8_t>( device->getPairingState() );
895 } catch(...) {
897 }
898 return static_cast<uint8_t>( SMPPairingState::NONE );
899}
900
901jbyte Java_jau_direct_1bt_DBTDevice_setPairingPasskeyImpl(JNIEnv *env, jobject obj, jint jpasskey) {
902 try {
903 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
904 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
905 JavaGlobalObj::check(device_java, E_FILE_LINE);
906
907 return (jbyte) number( device->setPairingPasskey( static_cast<uint32_t>(jpasskey) ) );
908 } catch(...) {
910 }
911 return (jbyte) static_cast<uint8_t>( HCIStatusCode::INTERNAL_FAILURE );
912}
913
915 try {
916 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
917 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
918 JavaGlobalObj::check(device_java, E_FILE_LINE);
919
920 return (jbyte) number( device->setPairingPasskeyNegative() );
921 } catch(...) {
923 }
924 return (jbyte) static_cast<uint8_t>( HCIStatusCode::INTERNAL_FAILURE );
925}
926
927jbyte Java_jau_direct_1bt_DBTDevice_setPairingNumericComparisonImpl(JNIEnv *env, jobject obj, jboolean jequal) {
928 try {
929 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
930 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
931 JavaGlobalObj::check(device_java, E_FILE_LINE);
932
933 return (jbyte) number( device->setPairingNumericComparison( JNI_TRUE == jequal ? true : false ) );
934 } catch(...) {
936 }
937 return (jbyte) static_cast<uint8_t>( HCIStatusCode::INTERNAL_FAILURE );
938}
939
940//
941// getter
942//
943
944static const std::string _serviceClazzCtorArgs("(JLjau/direct_bt/DBTDevice;ZLjava/lang/String;SS)V");
945
946jobject Java_jau_direct_1bt_DBTDevice_getGattServicesImpl(JNIEnv *env, jobject obj) {
947 try {
948 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
949 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
950 JavaGlobalObj::check(device_java, E_FILE_LINE);
951
952 jau::darray<BTGattServiceRef> services = device->getGattServices(); // implicit GATT connect and discovery if required incl GenericAccess retrieval
953 if( services.size() == 0 ) {
954 return nullptr;
955 }
956
957 // BTGattService(final long nativeInstance, final BTDevice device, final boolean isPrimary,
958 // final String type_uuid, final short handleStart, final short handleEnd)
959
960 jau::function<jobject(JNIEnv*, jclass, jmethodID, const BTGattServiceRef&)> ctor_service =
961 [](JNIEnv *env_, jclass clazz, jmethodID clazz_ctor, const BTGattServiceRef& service)->jobject {
962 // prepare adapter ctor
963 std::shared_ptr<BTDevice> _device = service->getDeviceUnchecked();
964 if( nullptr == _device ) {
965 throw jau::RuntimeException("Service's device null: "+service->toString(), E_FILE_LINE);
966 }
967 JavaAnonRef _device_java = _device->getJavaObject(); // hold until done!
968 JavaGlobalObj::check(_device_java, E_FILE_LINE);
969 jobject jdevice = JavaGlobalObj::GetObject(_device_java);
970
971 const jboolean isPrimary = service->primary;
972 const jstring juuid = from_string_to_jstring(env_, service->type->toUUID128String());
974
975 shared_ptr_ref<BTGattService> service_sref(service); // new instance to be released into new jobject
976 jobject jservice = env_->NewObject(clazz, clazz_ctor, service_sref.release_to_jlong(), jdevice, isPrimary,
977 juuid, service->handle, service->end_handle);
979 JNIGlobalRef::check(jservice, E_FILE_LINE);
980 JavaAnonRef jServiceRef = service->getJavaObject(); // GlobalRef
981 JavaGlobalObj::check(jServiceRef, E_FILE_LINE);
982 env_->DeleteLocalRef(juuid);
983 env_->DeleteLocalRef(jservice);
984 return JavaGlobalObj::GetObject(jServiceRef);
985 };
986 return convert_vector_sharedptr_to_jarraylist<jau::darray<BTGattServiceRef>, BTGattService>(
987 env, services, _serviceClazzCtorArgs.c_str(), ctor_service);
988 } catch(...) {
990 }
991 return nullptr;
992}
993
994jboolean Java_jau_direct_1bt_DBTDevice_sendNotification(JNIEnv *env, jobject obj, jshort char_value_handle, jbyteArray jval) {
995 try {
996 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
997 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
998 JavaGlobalObj::check(device_java, E_FILE_LINE);
999
1000 if( nullptr == jval ) {
1001 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
1002 }
1003 const size_t value_size = env->GetArrayLength(jval);
1004 if( 0 >= value_size ) {
1005 return JNI_TRUE; // no data is OK
1006 }
1007 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
1008 uint8_t * value_ptr = criticalArray.get(jval, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
1009 if( nullptr == value_ptr ) {
1010 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
1011 }
1012 const jau::TROOctets value(value_ptr, value_size, jau::lb_endian_t::little);
1013 return device->sendNotification(char_value_handle, value) ? JNI_TRUE : JNI_FALSE;
1014 } catch(...) {
1016 }
1017 return JNI_FALSE;
1018}
1019
1020jboolean Java_jau_direct_1bt_DBTDevice_sendIndication(JNIEnv *env, jobject obj, jshort char_value_handle, jbyteArray jval) {
1021 try {
1022 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1023 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1024 JavaGlobalObj::check(device_java, E_FILE_LINE);
1025
1026 if( nullptr == jval ) {
1027 throw jau::IllegalArgumentException("byte array null", E_FILE_LINE);
1028 }
1029 const size_t value_size = env->GetArrayLength(jval);
1030 if( 0 >= value_size ) {
1031 return JNI_TRUE; // no data is OK
1032 }
1033 JNICriticalArray<uint8_t, jbyteArray> criticalArray(env); // RAII - release
1034 uint8_t * value_ptr = criticalArray.get(jval, criticalArray.Mode::NO_UPDATE_AND_RELEASE);
1035 if( nullptr == value_ptr ) {
1036 throw jau::InternalError("GetPrimitiveArrayCritical(byte array) is null", E_FILE_LINE);
1037 }
1038 const jau::TROOctets value(value_ptr, value_size, jau::lb_endian_t::little);
1039 return device->sendIndication(char_value_handle, value) ? JNI_TRUE : JNI_FALSE;
1040 } catch(...) {
1042 }
1043 return JNI_FALSE;
1044}
1045
1046jboolean Java_jau_direct_1bt_DBTDevice_pingGATTImpl(JNIEnv *env, jobject obj)
1047{
1048 try {
1049 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1050 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1051 JavaGlobalObj::check(device_java, E_FILE_LINE);
1052
1053 return device->pingGATT() ? JNI_TRUE : JNI_FALSE;
1054 } catch(...) {
1056 }
1057 return JNI_FALSE;
1058}
1059
1060jshort Java_jau_direct_1bt_DBTDevice_getRSSI(JNIEnv *env, jobject obj)
1061{
1062 try {
1063 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1064 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1065 JavaGlobalObj::check(device_java, E_FILE_LINE);
1066 return (jshort) device->getRSSI();
1067 } catch(...) {
1069 }
1070 return 0;
1071}
1072
1073void Java_jau_direct_1bt_DBTDevice_getEIRImpl(JNIEnv *env, jobject obj, jobject jeir_sink) {
1074 try {
1075 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1076 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1077 JavaGlobalObj::check(device_java, E_FILE_LINE);
1078
1079 shared_ptr_ref<EInfoReport> eir_sink(env, jeir_sink);
1080
1081 // replace the shared managed object
1082 eir_sink = device->getEIR();
1083 eir_sink.release_into_object(env, jeir_sink);
1084 } catch(...) {
1086 }
1087}
1088
1089void Java_jau_direct_1bt_DBTDevice_getEIRIndImpl(JNIEnv *env, jobject obj, jobject jeir_sink) {
1090 try {
1091 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1092 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1093 JavaGlobalObj::check(device_java, E_FILE_LINE);
1094
1095 shared_ptr_ref<EInfoReport> eir_sink(env, jeir_sink);
1096
1097 // replace the shared managed object
1098 eir_sink = device->getEIRInd();
1099 eir_sink.release_into_object(env, jeir_sink);
1100 } catch(...) {
1102 }
1103}
1104
1105void Java_jau_direct_1bt_DBTDevice_getEIRScanRspImpl(JNIEnv *env, jobject obj, jobject jeir_sink) {
1106 try {
1107 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1108 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1109 JavaGlobalObj::check(device_java, E_FILE_LINE);
1110
1111 shared_ptr_ref<EInfoReport> eir_sink(env, jeir_sink);
1112
1113 // replace the shared managed object
1114 eir_sink = device->getEIRScanRsp();
1115 eir_sink.release_into_object(env, jeir_sink);
1116 } catch(...) {
1118 }
1119}
1120
1121jshort Java_jau_direct_1bt_DBTDevice_getTxPower(JNIEnv *env, jobject obj)
1122{
1123 try {
1124 shared_ptr_ref<BTDevice> device(env, obj); // hold until done
1125 JavaAnonRef device_java = device->getJavaObject(); // hold until done!
1126 JavaGlobalObj::check(device_java, E_FILE_LINE);
1127 return (jshort) device->getTxPower();
1128 } catch(...) {
1130 }
1131 return 0;
1132}
1133
1134#if 0
1135//
1136// Leave below code 'in' disabled, as an example of how to bind Java callback functions to C++ callback functions ad-hoc.
1137
1138//
1139// BooleanDeviceCBContext
1140//
1141
1142struct BooleanDeviceCBContext {
1143 BDAddressAndType addressAndType;
1144 JNIGlobalRef javaCallback_ref;
1145 jmethodID mRun;
1146 JNIGlobalRef boolean_cls_ref;
1147 jmethodID boolean_ctor;
1148
1149 BooleanDeviceCBContext(
1150 BDAddressAndType addressAndType_,
1151 JNIGlobalRef javaCallback_ref_,
1152 jmethodID mRun_,
1153 JNIGlobalRef boolean_cls_ref_,
1154 jmethodID boolean_ctor_)
1155 : addressAndType(addressAndType_), javaCallback_ref(javaCallback_ref_),
1156 mRun(mRun_), boolean_cls_ref(boolean_cls_ref_), boolean_ctor(boolean_ctor_)
1157 { }
1158
1159
1160 bool operator==(const BooleanDeviceCBContext& rhs) const
1161 {
1162 if( &rhs == this ) {
1163 return true;
1164 }
1165 return rhs.addressAndType == addressAndType &&
1166 rhs.javaCallback_ref == javaCallback_ref;
1167 }
1168
1169 bool operator!=(const BooleanDeviceCBContext& rhs) const
1170 { return !( *this == rhs ); }
1171
1172};
1173typedef std::shared_ptr<BooleanDeviceCBContext> BooleanDeviceCBContextRef;
1174
1175
1176//
1177// Paired
1178//
1179static void disablePairedNotifications(JNIEnv *env, jobject obj, BTManager &mgmt)
1180{
1181 InvocationFunc<bool, const MgmtEvent&> * funcptr =
1182 getObjectRef<InvocationFunc<bool, const MgmtEvent&>>(env, obj, "pairedNotificationRef");
1183 if( nullptr != funcptr ) {
1184 FunctionDef<bool, const MgmtEvent&> funcDef( funcptr );
1185 funcptr = nullptr;
1186 setObjectRef(env, obj, funcptr, "pairedNotificationRef"); // clear java ref
1187 int count;
1188 if( 1 != ( count = mgmt.removeMgmtEventCallback(MgmtEvent::Opcode::DEVICE_UNPAIRED, funcDef) ) ) {
1189 throw InternalError(std::string("removeMgmtEventCallback of ")+funcDef.toString()+" not 1 but "+std::to_string(count), E_FILE_LINE);
1190 }
1191 }
1192}
1193void Java_jau_direct_1bt_DBTDevice_disablePairedNotificationsImpl(JNIEnv *env, jobject obj)
1194{
1195 try {
1196 BTDevice *device = getJavaUplinkObject<BTDevice>(env, obj);
1197 JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
1198 BTManager & mgmt = device->getAdapter().getManager();
1199
1200 disablePairedNotifications(env, obj, mgmt);
1201 } catch(...) {
1203 }
1204}
1205void Java_jau_direct_1bt_DBTDevice_enablePairedNotificationsImpl(JNIEnv *env, jobject obj, jobject javaCallback)
1206{
1207 try {
1208 BTDevice *device= getJavaUplinkObject<BTDevice>(env, obj);
1209 JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
1210 BTAdapter & adapter = device->getAdapter();
1211 BTManager & mgmt = adapter.getManager();
1212
1213 disablePairedNotifications(env, obj, mgmt);
1214
1215 bool(*nativeCallback)(BooleanDeviceCBContextRef&, const MgmtEvent&) =
1216 [](BooleanDeviceCBContextRef& ctx_ref, const MgmtEvent& e)->bool {
1217 const MgmtEvtDeviceUnpaired &event = *static_cast<const MgmtEvtDeviceUnpaired *>(&e);
1218 if( event.getAddress() != ctx_ref->addressAndType.address || event.getAddressType() != ctx_ref->addressAndType.type ) {
1219 return false; // not this device
1220 }
1221 jobject result = jni_env->NewObject(ctx_ref->boolean_cls_ref.getClass(), ctx_ref->boolean_ctor, JNI_FALSE);
1222 jni_env->CallVoidMethod(*(ctx_ref->javaCallback_ref), ctx_ref->mRun, result);
1223 jni_env->DeleteLocalRef(result);
1224 return true;
1225 };
1226 jclass notification = search_class(*jni_env, javaCallback);
1227 jmethodID mRun = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false);
1229 jni_env->DeleteLocalRef(notification);
1230
1231 jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean");
1232 jmethodID boolean_ctor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false);
1234
1235 BooleanDeviceCBContext * ctx = new BooleanDeviceCBContext{
1236 device->getAddressAndType(), JNIGlobalRef(javaCallback), mRun, JNIGlobalRef(boolean_cls), boolean_ctor };
1237 jni_env->DeleteLocalRef(boolean_cls);
1238
1239 // move BooleanDeviceCBContextRef into CaptureInvocationFunc and operator== includes javaCallback comparison
1240 FunctionDef<bool, const MgmtEvent&> funcDef = bindCaptureFunc(BooleanDeviceCBContextRef(ctx), nativeCallback);
1241 setObjectRef(env, obj, funcDef.cloneFunction(), "pairedNotificationRef"); // set java ref
1242 // Note that this is only called natively for unpaired, i.e. paired:=false. Using deviceConnected for paired:=true on Java side
1243 mgmt.addMgmtEventCallback(adapter.dev_id, MgmtEvent::Opcode::DEVICE_UNPAIRED, funcDef);
1244 } catch(...) {
1246 }
1247}
1248#endif
jint Java_jau_direct_1bt_DBTDevice_getResponderSMPPassKey(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:496
jboolean Java_jau_direct_1bt_DBTDevice_addCharListenerImpl(JNIEnv *env, jobject obj, jobject jlistener, jobject jAssociatedCharacteristic)
Definition: DBTDevice.cxx:250
void Java_jau_direct_1bt_DBTDevice_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
Definition: DBTDevice.cxx:161
jbyte Java_jau_direct_1bt_DBTDevice_getTxPhysImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:444
jbyte Java_jau_direct_1bt_DBTDevice_unpairImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:796
jboolean Java_jau_direct_1bt_DBTDevice_sendIndication(JNIEnv *env, jobject obj, jshort char_value_handle, jbyteArray jval)
Definition: DBTDevice.cxx:1020
jlong Java_org_direct_1bt_BTGattCharListener_ctorImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:130
jboolean Java_jau_direct_1bt_DBTDevice_removeCharListener(JNIEnv *env, jobject obj, jobject jlistener)
Definition: DBTDevice.cxx:287
jbyte Java_jau_direct_1bt_DBTDevice_getRoleImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:370
jbyte Java_jau_direct_1bt_DBTDevice_setPairingPasskeyNegativeImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:914
void Java_jau_direct_1bt_DBTDevice_getEIRIndImpl(JNIEnv *env, jobject obj, jobject jeir_sink)
Definition: DBTDevice.cxx:1089
void Java_jau_direct_1bt_DBTDevice_setIdentityResolvingKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource)
Definition: DBTDevice.cxx:668
static const std::string _indicationReceivedMethodArgs("(Lorg/direct_bt/BTGattChar;[BJZ)V")
jbyte Java_jau_direct_1bt_DBTDevice_getAddressTypeImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:233
jbyte Java_jau_direct_1bt_DBTDevice_getAvailableSMPKeysImpl(JNIEnv *env, jobject obj, jboolean responder)
Definition: DBTDevice.cxx:566
jbyte Java_jau_direct_1bt_DBTDevice_connectLEImpl1(JNIEnv *env, jobject obj, jshort interval, jshort window, jshort min_interval, jshort max_interval, jshort latency, jshort timeout)
Definition: DBTDevice.cxx:549
jboolean Java_jau_direct_1bt_DBTDevice_setConnSecurityImpl(JNIEnv *env, jobject obj, jbyte jsec_level, jbyte jio_cap)
Definition: DBTDevice.cxx:835
void Java_jau_direct_1bt_DBTDevice_initImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:183
jobject Java_jau_direct_1bt_DBTDevice_getGattServicesImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:946
jboolean Java_jau_direct_1bt_DBTDevice_pingGATTImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:1046
void Java_jau_direct_1bt_DBTDevice_setSignatureResolvingKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource)
Definition: DBTDevice.cxx:719
jbyte Java_jau_direct_1bt_DBTDevice_uploadKeysImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:579
jstring Java_jau_direct_1bt_DBTDevice_getNameImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:194
void Java_org_direct_1bt_BTGattCharListener_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
Definition: DBTDevice.cxx:148
static const std::string _serviceClazzCtorArgs("(JLjau/direct_bt/DBTDevice;ZLjava/lang/String;SS)V")
jbyte Java_jau_direct_1bt_DBTDevice_connectDefaultImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:522
jbyte Java_jau_direct_1bt_DBTDevice_getRxPhysImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:457
void Java_jau_direct_1bt_DBTDevice_getEIRScanRspImpl(JNIEnv *env, jobject obj, jobject jeir_sink)
Definition: DBTDevice.cxx:1105
void Java_jau_direct_1bt_DBTDevice_getEIRImpl(JNIEnv *env, jobject obj, jobject jeir_sink)
Definition: DBTDevice.cxx:1073
jboolean Java_jau_direct_1bt_DBTDevice_removeImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:509
jint Java_jau_direct_1bt_DBTDevice_removeAllAssociatedCharListener(JNIEnv *env, jobject obj, jobject jAssociatedCharacteristic)
Definition: DBTDevice.cxx:319
jboolean Java_jau_direct_1bt_DBTDevice_setConnSecurityAutoImpl(JNIEnv *env, jobject obj, jbyte jio_cap)
Definition: DBTDevice.cxx:849
jbyte Java_jau_direct_1bt_DBTDevice_getConnIOCapabilityImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:822
jshort Java_jau_direct_1bt_DBTDevice_getRSSI(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:1060
void Java_jau_direct_1bt_DBTDevice_setLongTermKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource)
Definition: DBTDevice.cxx:617
void Java_jau_direct_1bt_DBTDevice_getSignatureResolvingKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink)
Definition: DBTDevice.cxx:694
static const std::string _notificationReceivedMethodArgs("(Lorg/direct_bt/BTGattChar;[BJ)V")
jstring Java_jau_direct_1bt_DBTDevice_toStringImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:206
jbyteArray Java_jau_direct_1bt_DBTDevice_getAddressImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:218
jint Java_jau_direct_1bt_DBTDevice_removeAllCharListener(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:347
jboolean Java_jau_direct_1bt_DBTDevice_isConnSecurityAutoEnabled(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:862
void Java_jau_direct_1bt_DBTDevice_getLinkKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink)
Definition: DBTDevice.cxx:745
void Java_jau_direct_1bt_DBTDevice_getIdentityResolvingKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink)
Definition: DBTDevice.cxx:643
jbyte Java_jau_direct_1bt_DBTDevice_getPairingModeImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:875
jbyte Java_jau_direct_1bt_DBTDevice_disconnectImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:470
jbyte Java_jau_direct_1bt_DBTDevice_getPairingStateImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:888
jboolean Java_jau_direct_1bt_DBTDevice_sendNotification(JNIEnv *env, jobject obj, jshort char_value_handle, jbyteArray jval)
Definition: DBTDevice.cxx:994
jbyte Java_jau_direct_1bt_DBTDevice_setPairingNumericComparisonImpl(JNIEnv *env, jobject obj, jboolean jequal)
Definition: DBTDevice.cxx:927
void Java_jau_direct_1bt_DBTDevice_getLongTermKeyImpl(JNIEnv *env, jobject obj, jboolean responder, jbyteArray jsink)
Definition: DBTDevice.cxx:592
jshort Java_jau_direct_1bt_DBTDevice_getTxPower(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:1121
jbyte Java_jau_direct_1bt_DBTDevice_connectLEImpl0(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:535
jbyte Java_jau_direct_1bt_DBTDevice_getConnSecurityLevelImpl(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:809
jbyte Java_jau_direct_1bt_DBTDevice_getConnectedLE_1PHYImpl(JNIEnv *env, jobject obj, jbyteArray jresTx, jbyteArray jresRx)
Definition: DBTDevice.cxx:383
jbyte Java_jau_direct_1bt_DBTDevice_setPairingPasskeyImpl(JNIEnv *env, jobject obj, jint jpasskey)
Definition: DBTDevice.cxx:901
void Java_jau_direct_1bt_DBTDevice_setLinkKeyImpl(JNIEnv *env, jobject obj, jbyteArray jsource)
Definition: DBTDevice.cxx:770
jbyte Java_jau_direct_1bt_DBTDevice_setConnectedLE_1PHYImpl(JNIEnv *env, jobject obj, jbyte jTx, jbyte jRx)
Definition: DBTDevice.cxx:427
jboolean Java_jau_direct_1bt_DBTDevice_isPrePaired(JNIEnv *env, jobject obj)
Definition: DBTDevice.cxx:483
#define E_FILE_LINE
JNIGattCharListener(JNIEnv *env, jobject listener)
Definition: DBTDevice.cxx:67
void notificationReceived(BTGattCharRef charDecl, const jau::TROOctets &charValue, const uint64_t timestamp) override
Called from native BLE stack, initiated by a received notification associated with the given BTGattCh...
Definition: DBTDevice.cxx:83
void indicationReceived(BTGattCharRef charDecl, const jau::TROOctets &charValue, const uint64_t timestamp, const bool confirmationSent) override
Called from native BLE stack, initiated by a received indication associated with the given BTGattChar...
Definition: DBTDevice.cxx:103
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BTAddress.hpp:175
BTAdapter represents one local Bluetooth Controller.
Definition: BTAdapter.hpp:324
const uint16_t dev_id
Adapter's internal temporary device id.
Definition: BTAdapter.hpp:363
const BTManagerRef & getManager() const noexcept
Returns a reference to the used singleton BTManager instance, used to create this adapter.
Definition: BTAdapter.hpp:932
BTDevice represents one remote Bluetooth device.
Definition: BTDevice.hpp:81
constexpr BDAddressAndType const & getAddressAndType() const noexcept
Returns the devices' unique EUI48 address and type tuple, might be its initially reported (resolvable...
Definition: BTDevice.hpp:388
BTAdapter & getAdapter() const
Returns the managing adapter.
Definition: BTDevice.hpp:332
BTGattChar event listener for notification and indication events.
Definition: BTGattChar.hpp:450
Representing a Gatt Service object from the GATTRole::Client perspective.
A thread safe singleton handler of the BTAdapter manager, e.g.
Definition: BTManager.hpp:204
size_type removeMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
Returns count of removed given MgmtEventCallback from the named MgmtEvent::Opcode list.
Definition: BTManager.cpp:1172
bool addMgmtEventCallback(const int dev_id, const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
MgmtEventCallback handling
Definition: BTManager.cpp:1163
uint16_t opcode, uint16_t dev-id, uint16_t param_size
Definition: MgmtTypes.hpp:1402
mgmt_addr_info { EUI48, uint8_t type },
Definition: MgmtTypes.hpp:2234
Transient read only and endian aware octet data, i.e.
Definition: octets.hpp:67
constexpr nsize_t size() const noexcept
Returns the used memory size for read and write operations, may be zero.
Definition: octets.hpp:162
constexpr uint8_t const * get_ptr() const noexcept
Definition: octets.hpp:272
Implementation of a dynamic linear array storage, aka vector.
Definition: darray.hpp:148
constexpr size_type size() const noexcept
Like std::vector::size().
Definition: darray.hpp:763
Class template jau::function is a general-purpose static-polymorphic function wrapper.
T * get(U jarray_val, Mode mode_val=UPDATE_AND_RELEASE)
Acquired the primitive array.
Definition: jni_mem.hpp:193
jobject getObject() const noexcept
A std::shared_ptr<T> storage instance to be copied from and released into a java object's long native...
Definition: helper_jni.hpp:393
bool is_null() const noexcept
Returns true if either this instances shared_ptr<T> storage or the managed object reference is nullpt...
Definition: helper_jni.hpp:614
const std::shared_ptr< T > & shared_ptr() const
Provides access to const reference of shared_ptr<T>, r-value.
Definition: helper_jni.hpp:630
std::shared_ptr< T > * pointer() noexcept
Provides access to the shared_ptr<T> pointer, l-value of storage.
Definition: helper_jni.hpp:621
std::string toString() const noexcept
Definition: helper_jni.hpp:657
jlong release_to_jlong() noexcept
Release ownership and return the jlong representation of the shared_ptr<T> storage.
Definition: helper_jni.hpp:574
void release_into_object(JNIEnv *env, jobject obj)
Deletes the std::shared_ptr<T> storage of the target java object if exists first and writes this inst...
Definition: helper_jni.hpp:593
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
Definition: debug.hpp:109
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition: debug.hpp:52
#define WARN_PRINT(...)
Use for unconditional warning messages, prefix '[elapsed_time] Warning @ FILE:LINE FUNC: '.
Definition: debug.hpp:123
@ little
Identifier for little endian, equivalent to endian::little.
bool operator!=(const alphabet &lhs, const alphabet &rhs) noexcept
Definition: base_codec.hpp:99
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
bool operator==(const alphabet &lhs, const alphabet &rhs) noexcept
Definition: base_codec.hpp:103
constexpr SMPIOCapability to_SMPIOCapability(const uint8_t v) noexcept
Definition: SMPTypes.hpp:223
constexpr BTSecurityLevel to_BTSecurityLevel(const uint8_t v) noexcept
Definition: BTTypes0.hpp:300
LE_PHYs
LE Transport PHY bit values.
Definition: BTTypes0.hpp:231
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Definition: HCITypes.hpp:138
std::shared_ptr< BTGattChar > BTGattCharRef
Definition: BTGattChar.hpp:410
std::shared_ptr< BTGattService > BTGattServiceRef
Definition: BTGattChar.hpp:67
constexpr uint32_t number(const iostate rhs) noexcept
Definition: byte_stream.hpp:72
void java_exception_check_and_throw(JNIEnv *env, const char *file, int line)
Throws a C++ exception if a java exception occurred, otherwise do nothing.
thread_local JNIEnvContainer jni_env
jstring from_string_to_jstring(JNIEnv *env, const std::string &str)
void setObjectRef(JNIEnv *env, jobject obj, T *t, const char *field_name)
Definition: helper_jni.hpp:268
jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, const char *prototype, bool is_static)
std::shared_ptr< JavaAnon > JavaAnonRef
Definition: java_uplink.hpp:55
jclass search_class(JNIEnv *env, const char *clazz_name)
#define rethrow_and_raise_java_exception(E)
Re-throw current exception and raise respective java exception using any matching function above.
Definition: helper_base.hpp:52
SMP Identity Resolving Key, used for platform agnostic persistence.
Definition: SMPTypes.hpp:636
Local SMP Link Key, used for platform agnostic persistence, mapping to platform specific MgmtLoadLink...
Definition: SMPTypes.hpp:824
SMP Long Term Key, used for platform agnostic persistence.
Definition: SMPTypes.hpp:552
SMP Signature Resolving Key, used for platform agnostic persistence.
Definition: SMPTypes.hpp:712
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: eui48.hpp:324
uint8_t b[6]
Definition: eui48.hpp:324