2021-09-01 00:00:36 +02:00
|
|
|
/*
|
|
|
|
* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
|
|
|
|
*
|
2024-02-12 13:29:40 +01:00
|
|
|
* Copyright (c) 2021-2024, Olivier Martin <olivier@labapart.org>
|
2021-09-01 00:00:36 +02:00
|
|
|
*/
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
#ifndef __GATTLIB_INTERNAL_H__
|
|
|
|
#define __GATTLIB_INTERNAL_H__
|
2019-07-07 17:10:10 +02:00
|
|
|
|
2019-05-19 12:47:21 +02:00
|
|
|
#include <stdbool.h>
|
2024-02-12 13:29:40 +01:00
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#if defined(WITH_PYTHON)
|
|
|
|
#include <Python.h>
|
|
|
|
#endif
|
2019-05-19 12:47:21 +02:00
|
|
|
|
2019-07-07 17:10:10 +02:00
|
|
|
#include "gattlib.h"
|
2024-04-05 11:43:21 +02:00
|
|
|
#include "gattlib_backend.h"
|
2019-07-07 17:10:10 +02:00
|
|
|
|
2024-03-25 12:19:52 +01:00
|
|
|
#if defined(WITH_PYTHON)
|
2024-02-12 13:29:40 +01:00
|
|
|
struct gattlib_python_args {
|
|
|
|
PyObject* callback;
|
|
|
|
PyObject* args;
|
|
|
|
};
|
2024-03-25 12:19:52 +01:00
|
|
|
#endif
|
2019-07-07 17:10:10 +02:00
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
#define GATTLIB_SIGNAL_DEVICE_DISCONNECTION (1 << 0)
|
|
|
|
#define GATTLIB_SIGNAL_ADAPTER_STOP_SCANNING (1 << 1)
|
|
|
|
|
|
|
|
struct gattlib_signal {
|
|
|
|
// Used by gattlib_disconnection when we want to wait for the disconnection to be effective
|
|
|
|
GCond condition;
|
|
|
|
// Mutex for condition
|
|
|
|
GMutex mutex;
|
|
|
|
// Identify the gattlib signals
|
|
|
|
uint32_t signals;
|
|
|
|
};
|
|
|
|
|
2019-05-19 12:47:21 +02:00
|
|
|
struct gattlib_handler {
|
|
|
|
union {
|
2024-02-12 13:29:40 +01:00
|
|
|
gattlib_discovered_device_t discovered_device;
|
|
|
|
gatt_connect_cb_t connection_handler;
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_event_handler_t notification_handler;
|
|
|
|
gattlib_disconnection_handler_t disconnection_handler;
|
2024-02-12 13:29:40 +01:00
|
|
|
void (*callback)(void);
|
|
|
|
} callback;
|
|
|
|
|
2019-05-19 12:47:21 +02:00
|
|
|
void* user_data;
|
2024-02-12 13:29:40 +01:00
|
|
|
// We create a thread to ensure the callback is not blocking the mainloop
|
|
|
|
GThread *thread;
|
2024-02-14 14:08:48 +01:00
|
|
|
// Thread pool
|
|
|
|
GThreadPool *thread_pool;
|
2024-03-25 12:19:52 +01:00
|
|
|
#if defined(WITH_PYTHON)
|
2024-02-12 13:29:40 +01:00
|
|
|
// In case of Python callback and argument, we keep track to free it when we stopped to discover BLE devices
|
|
|
|
void* python_args;
|
2024-03-25 12:19:52 +01:00
|
|
|
#endif
|
2019-05-19 12:47:21 +02:00
|
|
|
};
|
2019-07-07 17:10:10 +02:00
|
|
|
|
2024-04-03 15:16:38 +02:00
|
|
|
enum _gattlib_device_state {
|
|
|
|
NOT_FOUND = 0,
|
|
|
|
CONNECTING,
|
|
|
|
CONNECTED,
|
|
|
|
DISCONNECTING,
|
|
|
|
DISCONNECTED
|
|
|
|
};
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
struct _gattlib_adapter {
|
2024-04-03 15:07:13 +02:00
|
|
|
// Context specific to the backend implementation (eg: dbus backend)
|
2024-04-05 11:43:21 +02:00
|
|
|
struct _gattlib_adapter_backend backend;
|
2019-07-07 17:10:10 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
// BLE adapter name
|
|
|
|
char* name;
|
2024-02-15 19:24:33 +01:00
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
// reference counter is used to know whether the adapter is still use by callback
|
|
|
|
// When the reference counter is 0 then the adapter is freed
|
|
|
|
uintptr_t reference_counter;
|
2024-04-05 11:43:21 +02:00
|
|
|
|
|
|
|
// List of `gattlib_device_t`. This list allows to know weither a device is
|
|
|
|
// discovered/disconnected/connecting/connected/disconnecting.
|
|
|
|
GSList *devices;
|
|
|
|
|
|
|
|
// Handler calls on discovered device
|
|
|
|
struct gattlib_handler discovered_device_callback;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _gattlib_connection {
|
|
|
|
struct _gattlib_device* device;
|
|
|
|
|
|
|
|
// Context specific to the backend implementation (eg: dbus backend)
|
|
|
|
struct _gattlib_connection_backend backend;
|
2024-04-03 15:16:38 +02:00
|
|
|
|
2024-02-12 13:29:40 +01:00
|
|
|
struct gattlib_handler on_connection;
|
2019-05-19 12:47:21 +02:00
|
|
|
struct gattlib_handler notification;
|
|
|
|
struct gattlib_handler indication;
|
2024-02-12 13:29:40 +01:00
|
|
|
struct gattlib_handler on_disconnection;
|
2019-07-07 17:10:10 +02:00
|
|
|
};
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
typedef struct _gattlib_device {
|
|
|
|
struct _gattlib_adapter* adapter;
|
|
|
|
// On some platform, the name could be a UUID, on others its the DBUS device path
|
|
|
|
char* device_id;
|
2024-04-05 13:25:51 +02:00
|
|
|
|
|
|
|
// reference counter is used to know whether the device is still use by callback
|
|
|
|
// When the reference counter is 0 then the device is freed
|
|
|
|
uintptr_t reference_counter;
|
2024-04-05 11:43:21 +02:00
|
|
|
|
|
|
|
// We keep the state to prevent concurrent connecting/connected/disconnecting operation
|
|
|
|
enum _gattlib_device_state state;
|
|
|
|
|
|
|
|
struct _gattlib_connection connection;
|
|
|
|
} gattlib_device_t;
|
|
|
|
|
2024-04-05 13:25:51 +02:00
|
|
|
// This recursive mutex ensures all gattlib objects can be accessed in a multi-threaded environment
|
|
|
|
// The recursive mutex allows a same thread to lock twice the mutex without being blocked by itself.
|
|
|
|
extern GRecMutex m_gattlib_mutex;
|
|
|
|
|
|
|
|
// Keep track of the allocated adapters to avoid an adapter to be freed twice.
|
|
|
|
// It could happen when using Python wrapper.
|
|
|
|
extern GSList *m_adapter_list;
|
|
|
|
|
|
|
|
// This structure is used for inter-thread communication
|
|
|
|
extern struct gattlib_signal m_gattlib_signal;
|
|
|
|
|
|
|
|
bool gattlib_adapter_is_valid(gattlib_adapter_t* adapter);
|
|
|
|
bool gattlib_adapter_is_scanning(gattlib_adapter_t* adapter);
|
|
|
|
int gattlib_adapter_ref(gattlib_adapter_t* adapter);
|
|
|
|
int gattlib_adapter_unref(gattlib_adapter_t* adapter);
|
|
|
|
|
|
|
|
bool gattlib_device_is_valid(gattlib_device_t* device);
|
|
|
|
int gattlib_device_ref(gattlib_device_t* device);
|
|
|
|
int gattlib_device_unref(gattlib_device_t* device);
|
|
|
|
bool gattlib_connection_is_connected(gattlib_connection_t* connection);
|
|
|
|
|
2024-02-12 13:29:40 +01:00
|
|
|
void gattlib_handler_dispatch_to_thread(struct gattlib_handler* handler, void (*python_callback)(),
|
|
|
|
GThreadFunc thread_func, const char* thread_name, void* (*thread_args_allocator)(va_list args), ...);
|
|
|
|
void gattlib_handler_free(struct gattlib_handler* handler);
|
|
|
|
bool gattlib_has_valid_handler(struct gattlib_handler* handler);
|
|
|
|
|
2024-02-14 14:08:48 +01:00
|
|
|
void gattlib_notification_device_thread(gpointer data, gpointer user_data);
|
|
|
|
|
2024-03-13 13:33:07 +01:00
|
|
|
/**
|
|
|
|
* Clean GATTLIB connection on disconnection
|
|
|
|
*
|
|
|
|
* This function is called by the disconnection callback to always be called on explicit
|
|
|
|
* and implicit disconnection.
|
|
|
|
*/
|
2024-04-05 11:43:21 +02:00
|
|
|
void gattlib_connection_free(gattlib_connection_t* connection);
|
2024-03-13 13:33:07 +01:00
|
|
|
|
2024-04-03 15:16:38 +02:00
|
|
|
extern const char* device_state_str[];
|
2024-04-05 11:43:21 +02:00
|
|
|
gattlib_device_t* gattlib_device_get_device(gattlib_adapter_t* adapter, const char* device_id);
|
|
|
|
enum _gattlib_device_state gattlib_device_get_state(gattlib_adapter_t* adapter, const char* device_id);
|
|
|
|
int gattlib_device_set_state(gattlib_adapter_t* adapter, const char* device_id, enum _gattlib_device_state new_state);
|
|
|
|
int gattlib_devices_are_disconnected(gattlib_adapter_t* adapter);
|
|
|
|
int gattlib_devices_free(gattlib_adapter_t* adapter);
|
2024-04-03 15:16:38 +02:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2024-04-05 11:43:21 +02:00
|
|
|
void gattlib_devices_dump_state(gattlib_adapter_t* adapter);
|
2024-04-03 15:16:38 +02:00
|
|
|
#endif
|
|
|
|
|
2024-02-12 13:29:40 +01:00
|
|
|
#if defined(WITH_PYTHON)
|
|
|
|
// Callback used by Python to create arguments used by native callback
|
|
|
|
void* gattlib_python_callback_args(PyObject* python_callback, PyObject* python_args);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* These functions are called by Python wrapper
|
|
|
|
*/
|
2024-04-05 11:43:21 +02:00
|
|
|
void gattlib_discovered_device_python_callback(gattlib_adapter_t* adapter, const char* addr, const char* name, void *user_data);
|
|
|
|
void gattlib_connected_device_python_callback(gattlib_adapter_t* adapter, const char *dst, gattlib_connection_t* connection, int error, void* user_data);
|
|
|
|
void gattlib_disconnected_device_python_callback(gattlib_connection_t* connection, void *user_data);
|
2024-02-12 13:29:40 +01:00
|
|
|
void gattlib_notification_device_python_callback(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data);
|
|
|
|
#endif
|
2019-05-19 12:47:21 +02:00
|
|
|
|
2019-07-07 17:10:10 +02:00
|
|
|
#endif
|