mirror of https://github.com/labapart/gattlib
gattlib_disconnection: Added support to wait for the disconnection to be effective
parent
a85dd83015
commit
5f43addb8f
|
@ -483,7 +483,7 @@ gatt_connection_t *gattlib_connect(void* adapter, const char *dst, unsigned long
|
|||
return conn;
|
||||
}
|
||||
|
||||
int gattlib_disconnect(gatt_connection_t* connection) {
|
||||
int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection) {
|
||||
gattlib_context_t* conn_context = connection->context;
|
||||
|
||||
#if BLUEZ_VERSION_MAJOR == 4
|
||||
|
|
|
@ -48,6 +48,12 @@ void gattlib_on_disconnected_device(gatt_connection_t* connection) {
|
|||
g_rec_mutex_unlock(&connection->on_disconnection.mutex);
|
||||
}
|
||||
|
||||
// Signal the device is now disconnected
|
||||
g_mutex_lock(&connection->disconnection_wait.lock);
|
||||
connection->disconnection_wait.value = true;
|
||||
g_cond_broadcast(&connection->disconnection_wait.condition);
|
||||
g_mutex_unlock(&connection->disconnection_wait.lock);
|
||||
|
||||
// Clean GATTLIB connection on disconnection
|
||||
gattlib_connection_free(connection);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,15 @@ struct _gatt_connection_t {
|
|||
|
||||
GMutex connection_mutex;
|
||||
|
||||
struct {
|
||||
// Used by gattlib_disconnection when we want to wait for the disconnection to be effective
|
||||
GCond condition;
|
||||
// Mutex used for disconnection_condition synchronization
|
||||
GMutex lock;
|
||||
// Used to avoid spurious or stolen wakeup
|
||||
bool value;
|
||||
} disconnection_wait;
|
||||
|
||||
struct gattlib_handler on_connection;
|
||||
struct gattlib_handler notification;
|
||||
struct gattlib_handler indication;
|
||||
|
|
|
@ -241,7 +241,7 @@ int gattlib_connect(void *adapter, const char *dst,
|
|||
ret = GATTLIB_NOT_FOUND;
|
||||
} else if ((error->domain == 238) && (error->code == 60952)) {
|
||||
GATTLIB_LOG(GATTLIB_ERROR, "Device '%s': %s", dst, error->message);
|
||||
ret = GATTLIB_ERROR_TIMEOUT;
|
||||
ret = GATTLIB_TIMEOUT;
|
||||
} else {
|
||||
GATTLIB_LOG(GATTLIB_ERROR, "Device connected error (device:%s): %s",
|
||||
conn_context->device_object_path,
|
||||
|
@ -325,7 +325,7 @@ void gattlib_connection_free(gatt_connection_t* connection) {
|
|||
free(connection);
|
||||
}
|
||||
|
||||
int gattlib_disconnect(gatt_connection_t* connection) {
|
||||
int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection) {
|
||||
gattlib_context_t* conn_context;
|
||||
int ret = GATTLIB_SUCCESS;
|
||||
GError *error = NULL;
|
||||
|
@ -355,6 +355,22 @@ int gattlib_disconnect(gatt_connection_t* connection) {
|
|||
//Note: Signals and memory will be removed/clean on disconnction callback
|
||||
// See _gattlib_clean_on_disconnection()
|
||||
|
||||
if (wait_disconnection) {
|
||||
gint64 end_time;
|
||||
|
||||
g_mutex_lock(&connection->disconnection_wait.lock);
|
||||
|
||||
end_time = g_get_monotonic_time() + GATTLIB_DISCONNECTION_WAIT_TIMEOUT_SEC * G_TIME_SPAN_SECOND;
|
||||
|
||||
while (!connection->disconnection_wait.value) {
|
||||
if (!g_cond_wait_until(&connection->disconnection_wait.condition, &connection->disconnection_wait.lock, end_time)) {
|
||||
ret = GATTLIB_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock(&connection->disconnection_wait.lock);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
g_mutex_unlock(&connection->connection_mutex);
|
||||
return ret;
|
||||
|
|
|
@ -86,7 +86,7 @@ static void on_device_connect(void *adapter, const char *dst, gatt_connection_t*
|
|||
free(characteristics);
|
||||
|
||||
disconnect_exit:
|
||||
gattlib_disconnect(connection);
|
||||
gattlib_disconnect(connection, false /* wait_disconnection */);
|
||||
}
|
||||
|
||||
static void *ble_connect_device(void *arg) {
|
||||
|
|
|
@ -81,7 +81,7 @@ static void on_device_connect(void *adapter, const char *dst, gatt_connection_t*
|
|||
free(characteristics);
|
||||
|
||||
EXIT:
|
||||
gattlib_disconnect(connection);
|
||||
gattlib_disconnect(connection, false /* wait_disconnection */);
|
||||
|
||||
pthread_mutex_lock(&m_connection_terminated_lock);
|
||||
pthread_cond_signal(&m_connection_terminated);
|
||||
|
|
|
@ -129,7 +129,7 @@ static void disconnect_io()
|
|||
if (conn_state == STATE_DISCONNECTED)
|
||||
return;
|
||||
|
||||
gattlib_disconnect(g_connection);
|
||||
gattlib_disconnect(g_connection, false /* wait_disconnection */);
|
||||
opt_mtu = 0;
|
||||
|
||||
set_state(STATE_DISCONNECTED);
|
||||
|
|
|
@ -52,7 +52,7 @@ static void usage(char *argv[]) {
|
|||
}
|
||||
|
||||
void int_handler(int dummy) {
|
||||
gattlib_disconnect(m_connection);
|
||||
gattlib_disconnect(m_connection, false /* wait_disconnection */);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ int main(int argc, char *argv[]) {
|
|||
g_main_loop_unref(m_main_loop);
|
||||
|
||||
DISCONNECT:
|
||||
gattlib_disconnect(connection);
|
||||
gattlib_disconnect(connection, false /* wait_disconnection */);
|
||||
puts("Done");
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ static void on_device_connect(void *adapter, const char *dst, gatt_connection_t*
|
|||
}
|
||||
|
||||
EXIT:
|
||||
gattlib_disconnect(connection);
|
||||
gattlib_disconnect(connection, false /* wait_disconnection */);
|
||||
|
||||
pthread_mutex_lock(&m_connection_terminated_lock);
|
||||
pthread_cond_signal(&m_connection_terminated);
|
||||
|
|
|
@ -104,7 +104,7 @@ void *connect_ble(void *arg) {
|
|||
}
|
||||
|
||||
EXIT:
|
||||
gattlib_disconnect(connection);
|
||||
gattlib_disconnect(connection, false /* wait_disconnection */);
|
||||
g_main_loop_quit(m_main_loop);
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -152,9 +152,9 @@ gattlib_adapter_scan_eddystone.argtypes = [c_void_p, c_int16, c_uint32, py_objec
|
|||
gattlib_connect = gattlib.gattlib_connect
|
||||
gattlib_connect.argtypes = [c_void_p, c_char_p, c_ulong, c_void_p, c_void_p]
|
||||
|
||||
# int gattlib_disconnect(gatt_connection_t* connection);
|
||||
# int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection);
|
||||
gattlib_disconnect = gattlib.gattlib_disconnect
|
||||
gattlib_disconnect.argtypes = [c_void_p]
|
||||
gattlib_disconnect.argtypes = [c_void_p, c_bool]
|
||||
|
||||
# int gattlib_discover_primary(gatt_connection_t* connection, gattlib_primary_service_t** services, int* services_count);
|
||||
gattlib_discover_primary = gattlib.gattlib_discover_primary
|
||||
|
|
|
@ -138,11 +138,11 @@ class Device:
|
|||
gattlib_disconnected_device_python_callback,
|
||||
gattlib_python_callback_args(on_disconnection, user_data))
|
||||
|
||||
def disconnect(self):
|
||||
def disconnect(self, wait_disconnection: bool = False):
|
||||
self._connection_lock.acquire()
|
||||
try:
|
||||
if self._connection:
|
||||
ret = gattlib_disconnect(self.connection)
|
||||
ret = gattlib_disconnect(self.connection, wait_disconnection)
|
||||
handle_return(ret)
|
||||
self._connection = None
|
||||
finally:
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
GATTLIB_SUCCESS = 0
|
||||
GATTLIB_INVALID_PARAMETER = 1
|
||||
GATTLIB_NOT_FOUND = 2
|
||||
GATTLIB_ERROR_TIMEOUT = 3
|
||||
GATTLIB_TIMEOUT = 3
|
||||
GATTLIB_OUT_OF_MEMORY = 4
|
||||
GATTLIB_NOT_SUPPORTED = 5
|
||||
GATTLIB_DEVICE_ERROR = 6
|
||||
|
@ -74,7 +74,7 @@ def handle_return(ret):
|
|||
raise NotFound()
|
||||
elif ret == GATTLIB_OUT_OF_MEMORY:
|
||||
raise OutOfMemory()
|
||||
elif ret == GATTLIB_ERROR_TIMEOUT:
|
||||
elif ret == GATTLIB_TIMEOUT:
|
||||
raise TimeoutError()
|
||||
elif ret == GATTLIB_NOT_SUPPORTED:
|
||||
raise NotSupported()
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
@ -31,6 +32,11 @@ extern "C" {
|
|||
#define ATT_MAX_MTU ATT_MAX_VALUE_LEN
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gattlib constants
|
||||
*/
|
||||
#define GATTLIB_DISCONNECTION_WAIT_TIMEOUT_SEC 5
|
||||
|
||||
/**
|
||||
* @name Gattlib errors
|
||||
*/
|
||||
|
@ -38,7 +44,7 @@ extern "C" {
|
|||
#define GATTLIB_SUCCESS 0
|
||||
#define GATTLIB_INVALID_PARAMETER 1
|
||||
#define GATTLIB_NOT_FOUND 2
|
||||
#define GATTLIB_ERROR_TIMEOUT 3
|
||||
#define GATTLIB_TIMEOUT 3
|
||||
#define GATTLIB_OUT_OF_MEMORY 4
|
||||
#define GATTLIB_NOT_SUPPORTED 5
|
||||
#define GATTLIB_DEVICE_ERROR 6
|
||||
|
@ -132,7 +138,9 @@ extern "C" {
|
|||
#define EDDYSTONE_TYPE_EID 0x30
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* Log level
|
||||
*/
|
||||
#define GATTLIB_ERROR 0
|
||||
#define GATTLIB_WARNING 1
|
||||
#define GATTLIB_INFO 2
|
||||
|
@ -351,11 +359,18 @@ int gattlib_connect(void *adapter, const char *dst,
|
|||
/**
|
||||
* @brief Function to disconnect the GATT connection
|
||||
*
|
||||
* @param connection Active GATT connection
|
||||
* @note: If a callback has been registered by gattlib_register_on_disconnect() then it will be called
|
||||
* when the device will have signaled is disconnected.
|
||||
*
|
||||
* @param connection Active GATT connection
|
||||
* @param wait_disconnection If false gattlib_disconnect does not wait for the device to confirm it has been
|
||||
* disconnected and return immediately.
|
||||
*
|
||||
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
|
||||
* @return GATTLIB_TIMEOUT when wait_disconnection is true and the device has not been disconnected for
|
||||
* GATTLIB_DISCONNECTION_WAIT_TIMEOUT_SEC seconds
|
||||
*/
|
||||
int gattlib_disconnect(gatt_connection_t* connection);
|
||||
int gattlib_disconnect(gatt_connection_t* connection, bool wait_disconnection);
|
||||
|
||||
/**
|
||||
* @brief Function to register a callback on GATT disconnection
|
||||
|
|
Loading…
Reference in New Issue