summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/direct_bt/DBTDevice.hpp17
-rw-r--r--api/direct_bt/GATTHandler.hpp13
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java14
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx13
-rw-r--r--java/org/tinyb/BluetoothDevice.java15
-rw-r--r--java/tinyb/dbus/DBusDevice.java3
-rw-r--r--src/direct_bt/DBTDevice.cpp19
-rw-r--r--src/direct_bt/GATTHandler.cpp21
8 files changed, 115 insertions, 0 deletions
diff --git a/api/direct_bt/DBTDevice.hpp b/api/direct_bt/DBTDevice.hpp
index 6c8097d1..e01ecaab 100644
--- a/api/direct_bt/DBTDevice.hpp
+++ b/api/direct_bt/DBTDevice.hpp
@@ -326,6 +326,23 @@ namespace direct_bt {
std::shared_ptr<GenericAccess> getGATTGenericAccess();
/**
+ * Issues a GATT ping to the device, validating whether it is still reachable.
+ * <p>
+ * This method could be periodically utilized to shorten the underlying OS disconnect period
+ * after turning the device off, which lies within 7-13s.
+ * </p>
+ * <p>
+ * In case the device is no more reachable, the GATTHandler will initiate disconnect due to the occurring IO error.
+ * will issue a disconnect.
+ * </p>
+ * <p>
+ * See {@link #getGATTServices()} regarding GATT initialization.
+ * </p>
+ * @return {@code true} if successful, otherwise false in case no GATT services exists etc.
+ */
+ bool pingGATT();
+
+ /**
* Explicit disconnecting an open GATTHandler, which is usually performed via disconnect()
* <p>
* Implementation will also discard the GATTHandler reference.
diff --git a/api/direct_bt/GATTHandler.hpp b/api/direct_bt/GATTHandler.hpp
index 253077d0..92a79c38 100644
--- a/api/direct_bt/GATTHandler.hpp
+++ b/api/direct_bt/GATTHandler.hpp
@@ -374,6 +374,19 @@ namespace direct_bt {
std::shared_ptr<DeviceInformation> getDeviceInformation(std::vector<GATTServiceRef> & primServices);
std::shared_ptr<DeviceInformation> getDeviceInformation(std::vector<GATTCharacteristicRef> & deviceInfoCharDeclList);
+
+ /**
+ * Issues a ping to the device, validating whether it is still reachable.
+ * <p>
+ * This method could be periodically utilized to shorten the underlying OS disconnect period
+ * after turning the device off, which lies within 7-13s.
+ * </p>
+ * <p>
+ * In case the device is no more reachable, disconnect will be initiated due to the occurring IO error.
+ * </p>
+ * @return {@code true} if successful, otherwise false in case no GATT services exists etc.
+ */
+ bool ping();
};
} // namespace direct_bt
diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java
index e2390a51..6c1b6342 100644
--- a/java/direct_bt/tinyb/DBTDevice.java
+++ b/java/direct_bt/tinyb/DBTDevice.java
@@ -521,6 +521,20 @@ public class DBTDevice extends DBTObject implements BluetoothDevice
}
private native List<BluetoothGattService> getServicesImpl();
+ @Override
+ public boolean pingGATT() {
+ try {
+ return pingGATTImpl();
+ } catch (final Throwable t) {
+ if(DEBUG) {
+ System.err.println("Caught "+t.getMessage()+" on thread "+Thread.currentThread().toString());
+ t.printStackTrace();
+ }
+ }
+ return false;
+ }
+ private native boolean pingGATTImpl();
+
/* property accessors: */
@Override
diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx
index 465aa87d..958fdba2 100644
--- a/java/jni/direct_bt/DBTDevice.cxx
+++ b/java/jni/direct_bt/DBTDevice.cxx
@@ -378,6 +378,19 @@ jobject Java_direct_1bt_tinyb_DBTDevice_getServicesImpl(JNIEnv *env, jobject obj
return nullptr;
}
+jboolean Java_direct_1bt_tinyb_DBTDevice_pingGATTImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ DBTDevice *device = getInstance<DBTDevice>(env, obj);
+ JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
+
+ return device->pingGATT() ? JNI_TRUE : JNI_FALSE;
+ } catch(...) {
+ rethrow_and_raise_java_exception(env);
+ }
+ return JNI_FALSE;
+}
+
jstring Java_direct_1bt_tinyb_DBTDevice_getIcon(JNIEnv *env, jobject obj)
{
try {
diff --git a/java/org/tinyb/BluetoothDevice.java b/java/org/tinyb/BluetoothDevice.java
index c8035001..d693eb6b 100644
--- a/java/org/tinyb/BluetoothDevice.java
+++ b/java/org/tinyb/BluetoothDevice.java
@@ -140,6 +140,21 @@ public interface BluetoothDevice extends BluetoothObject
List<BluetoothGattService> getServices();
/**
+ * Issues a GATT ping to the device, validating whether it is still reachable.
+ * <p>
+ * This method could be periodically utilized to shorten the underlying OS disconnect period
+ * after turning the device off, which lies within 7-13s.
+ * </p>
+ * <p>
+ * In case the device is no more reachable, disconnect will be initiated due to the occurring IO error.
+ * </p>
+ *
+ * @return {@code true} if successful, otherwise false in case no GATT services exists etc.
+ * @since 2.0.0
+ */
+ boolean pingGATT();
+
+ /**
* Returns the timestamp in monotonic milliseconds when this device instance has been created,
* either via its initial discovery or its initial direct connection.
*
diff --git a/java/tinyb/dbus/DBusDevice.java b/java/tinyb/dbus/DBusDevice.java
index 9e523dd8..09524836 100644
--- a/java/tinyb/dbus/DBusDevice.java
+++ b/java/tinyb/dbus/DBusDevice.java
@@ -105,6 +105,9 @@ public class DBusDevice extends DBusObject implements BluetoothDevice
@Override
public native List<BluetoothGattService> getServices();
+ @Override
+ public boolean pingGATT() { return false; } // FIXME
+
/* D-Bus property accessors: */
@Override
diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp
index e5d32a1e..45a7c52c 100644
--- a/src/direct_bt/DBTDevice.cpp
+++ b/src/direct_bt/DBTDevice.cpp
@@ -490,6 +490,25 @@ std::vector<std::shared_ptr<GATTService>> DBTDevice::getGATTServices() {
return gattServices;
}
+bool DBTDevice::pingGATT() {
+ const std::lock_guard<std::recursive_mutex> lock(mtx_gatt); // RAII-style acquire and relinquish via destructor
+ if( nullptr == gattHandler || !gattHandler->isOpen() ) {
+ connectGATT();
+ if( nullptr == gattHandler || !gattHandler->isOpen() ) {
+ ERR_PRINT("DBTDevice::getServices: connectGATT failed");
+ return std::vector<std::shared_ptr<GATTService>>();
+ }
+ }
+ std::vector<std::shared_ptr<GATTService>> & gattServices = gattHandler->getServices(); // reference of the GATTHandler's list
+ if( gattServices.size() == 0 ) { // discover services
+ gattServices = gattHandler->discoverCompletePrimaryServices(); // same reference of the GATTHandler's list
+ if( gattServices.size() == 0 ) { // nothing discovered
+ return false;
+ }
+ }
+ return gattHandler->ping();
+}
+
std::shared_ptr<GenericAccess> DBTDevice::getGATTGenericAccess() {
const std::lock_guard<std::recursive_mutex> lock(mtx_gatt); // RAII-style acquire and relinquish via destructor
return gattGenericAccess;
diff --git a/src/direct_bt/GATTHandler.cpp b/src/direct_bt/GATTHandler.cpp
index e744f936..0a5ee71b 100644
--- a/src/direct_bt/GATTHandler.cpp
+++ b/src/direct_bt/GATTHandler.cpp
@@ -899,6 +899,27 @@ std::shared_ptr<GenericAccess> GATTHandler::getGenericAccess(std::vector<GATTSer
return res;
}
+bool GATTHandler::ping() {
+ std::shared_ptr<GenericAccess> res = nullptr;
+ for(size_t i=0; i<services.size() && nullptr == res; i++) {
+ std::vector<GATTCharacteristicRef> & genericAccessCharDeclList = services.at(i)->characteristicList;
+ POctets value(32, 0);
+
+ for(size_t i=0; i<genericAccessCharDeclList.size(); i++) {
+ const GATTCharacteristic & charDecl = *genericAccessCharDeclList.at(i);
+ if( _GENERIC_ACCESS != *charDecl.service->type ) {
+ continue;
+ }
+ if( _APPEARANCE == *charDecl.value_type ) {
+ if( readCharacteristicValue(charDecl, value.resize(0)) ) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
std::shared_ptr<DeviceInformation> GATTHandler::getDeviceInformation(std::vector<GATTCharacteristicRef> & characteristicDeclList) {
std::shared_ptr<DeviceInformation> res = nullptr;
POctets value(number(Defaults::MAX_ATT_MTU), 0);