2021-09-01 00:00:36 +02:00
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
#
|
2024-02-07 17:26:12 +01:00
|
|
|
# Copyright (c) 2016-2024, Olivier Martin <olivier@labapart.org>
|
2021-09-01 00:00:36 +02:00
|
|
|
#
|
|
|
|
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Gattlib C types and functions"""
|
|
|
|
|
2019-05-19 12:47:21 +02:00
|
|
|
from ctypes import *
|
2022-05-13 16:10:55 +02:00
|
|
|
import logging
|
2024-02-22 22:26:43 +01:00
|
|
|
import pathlib
|
2022-05-13 16:10:55 +02:00
|
|
|
|
2024-03-26 13:16:51 +01:00
|
|
|
try:
|
|
|
|
# '_version.py' is generated by 'setup.py'
|
2024-04-24 13:10:55 +02:00
|
|
|
from ._version import __version__ #pylint: disable=import-error
|
|
|
|
except: #pylint: disable=bare-except
|
2024-03-26 13:16:51 +01:00
|
|
|
pass
|
|
|
|
|
2022-05-13 16:10:55 +02:00
|
|
|
logger = logging.getLogger(__name__)
|
2019-05-19 12:47:21 +02:00
|
|
|
|
2024-02-26 23:19:10 +01:00
|
|
|
try:
|
|
|
|
gattlib = cdll.LoadLibrary(str(pathlib.Path(__file__).with_name('libgattlib.so')))
|
|
|
|
except OSError:
|
|
|
|
# While in development, we might not have 'libgattlib.so' into the python directory
|
|
|
|
# We can define 'libgattlib.so' location using LD_LIBRARY_PATH
|
|
|
|
gattlib = CDLL('libgattlib.so')
|
2019-05-19 12:47:21 +02:00
|
|
|
|
2024-02-22 00:17:09 +01:00
|
|
|
def native_logging(level: int, string: str):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Convert Gattlib logging to Python logging."""
|
2024-02-22 00:17:09 +01:00
|
|
|
if level == 3:
|
|
|
|
logger.debug(string)
|
|
|
|
elif level == 2:
|
|
|
|
logger.info(string)
|
|
|
|
elif level == 1:
|
|
|
|
logger.warning(string)
|
|
|
|
elif level == 0:
|
|
|
|
logger.error(string)
|
|
|
|
else:
|
|
|
|
logger.debug(string)
|
|
|
|
|
|
|
|
try:
|
|
|
|
# void gattlib_log_init(PyObject* logging_func)
|
|
|
|
gattlib_log_init = gattlib.gattlib_log_init
|
|
|
|
gattlib_log_init.argtypes = [py_object]
|
|
|
|
|
|
|
|
# Declare Python function for logging native string
|
|
|
|
gattlib_log_init(native_logging)
|
|
|
|
except AttributeError:
|
|
|
|
# Excepted when using a Gattlib logging backend without 'gattlib_log_init'
|
|
|
|
pass
|
2019-05-19 12:47:21 +02:00
|
|
|
|
|
|
|
# typedef struct {
|
|
|
|
# uint8_t data[16];
|
|
|
|
# } uint128_t;
|
|
|
|
class GattlibUuid128(Structure):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure 'uint128_t'."""
|
2019-05-19 12:47:21 +02:00
|
|
|
_fields_ = [("data", c_byte * 16)]
|
|
|
|
|
|
|
|
|
|
|
|
# typedef struct {
|
|
|
|
# uint8_t type;
|
|
|
|
# union {
|
|
|
|
# uint16_t uuid16;
|
|
|
|
# uint32_t uuid32;
|
|
|
|
# uint128_t uuid128;
|
|
|
|
# } value;
|
|
|
|
# } uuid_t;
|
|
|
|
class GattlibUuidValue(Union):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure of the value of 'uuid_t'."""
|
2019-05-19 12:47:21 +02:00
|
|
|
_fields_ = [("uuid16", c_ushort), ("uuid32", c_uint), ("uuid128", GattlibUuid128)]
|
|
|
|
|
|
|
|
|
|
|
|
class GattlibUuid(Structure):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure 'uuid_t'."""
|
2019-05-19 12:47:21 +02:00
|
|
|
_fields_ = [("type", c_byte), ("value", GattlibUuidValue)]
|
|
|
|
|
|
|
|
|
|
|
|
# typedef struct {
|
|
|
|
# uint16_t attr_handle_start;
|
|
|
|
# uint16_t attr_handle_end;
|
|
|
|
# uuid_t uuid;
|
|
|
|
# } gattlib_primary_service_t;
|
|
|
|
class GattlibPrimaryService(Structure):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure 'gattlib_primary_service_t'."""
|
2019-05-19 12:47:21 +02:00
|
|
|
_fields_ = [("attr_handle_start", c_ushort),
|
|
|
|
("attr_handle_end", c_ushort),
|
|
|
|
("uuid", GattlibUuid)]
|
|
|
|
|
|
|
|
|
|
|
|
# typedef struct {
|
|
|
|
# uint16_t handle;
|
|
|
|
# uint8_t properties;
|
|
|
|
# uint16_t value_handle;
|
|
|
|
# uuid_t uuid;
|
|
|
|
# } gattlib_characteristic_t;
|
|
|
|
class GattlibCharacteristic(Structure):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure 'gattlib_characteristic_t'."""
|
2019-05-19 12:47:21 +02:00
|
|
|
_fields_ = [("handle", c_ushort),
|
|
|
|
("properties", c_byte),
|
|
|
|
("value_handle", c_ushort),
|
|
|
|
("uuid", GattlibUuid)]
|
|
|
|
|
|
|
|
|
2019-07-14 23:26:47 +02:00
|
|
|
# typedef struct {
|
|
|
|
# uuid_t uuid;
|
|
|
|
# uint8_t* data;
|
|
|
|
# size_t data_length;
|
|
|
|
# } gattlib_advertisement_data_t;
|
|
|
|
class GattlibAdvertisementData(Structure):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure 'gattlib_advertisement_data_t'."""
|
2019-07-14 23:26:47 +02:00
|
|
|
_fields_ = [("uuid", GattlibUuid),
|
|
|
|
("data", c_void_p),
|
|
|
|
("data_length", c_size_t)]
|
|
|
|
|
2024-04-11 22:00:24 +02:00
|
|
|
# typedef struct {
|
|
|
|
# uint16_t manufacturer_id;
|
|
|
|
# uint8_t* data;
|
|
|
|
# size_t data_size;
|
|
|
|
# } gattlib_manufacturer_data_t;
|
|
|
|
class GattlibManufacturerData(Structure):
|
2024-04-24 13:10:55 +02:00
|
|
|
"""Python class representing the C structure 'gattlib_manufacturer_data_t'."""
|
2024-04-11 22:00:24 +02:00
|
|
|
_fields_ = [("manufacturer_id", c_ushort),
|
|
|
|
("data", c_void_p),
|
|
|
|
("data_size", c_size_t)]
|
|
|
|
|
2019-07-14 23:26:47 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_adapter_open(const char* adapter_name, gattlib_adapter_t** adapter);
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_adapter_open = gattlib.gattlib_adapter_open
|
|
|
|
gattlib_adapter_open.argtypes = [c_char_p, POINTER(c_void_p)]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# const char *gattlib_adapter_get_name(gattlib_adapter_t* adapter)
|
2024-02-12 13:29:40 +01:00
|
|
|
gattlib_adapter_get_name = gattlib.gattlib_adapter_get_name
|
|
|
|
gattlib_adapter_get_name.argtypes = [c_void_p]
|
|
|
|
gattlib_adapter_get_name.restype = c_char_p
|
|
|
|
|
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)
|
2024-02-12 13:29:40 +01:00
|
|
|
gattlib_discovered_device_python_callback = gattlib.gattlib_discovered_device_python_callback
|
|
|
|
gattlib_discovered_device_python_callback.argtypes = [c_void_p, c_char_p, c_char_p, py_object]
|
|
|
|
gattlib_discovered_device_python_callback.restype = c_void_p
|
|
|
|
|
2024-04-24 13:10:55 +02:00
|
|
|
# void gattlib_connected_device_python_callback(gattlib_adapter_t* adapter, const char *dst, gattlib_connection_t* connection,
|
|
|
|
# int error, void* user_data);
|
2024-02-12 13:29:40 +01:00
|
|
|
gattlib_connected_device_python_callback = gattlib.gattlib_connected_device_python_callback
|
|
|
|
gattlib_connected_device_python_callback.argtypes = [c_void_p, c_char_p, c_void_p, c_int, py_object]
|
|
|
|
gattlib_connected_device_python_callback.restype = c_void_p
|
|
|
|
|
|
|
|
# void gattlib_disconnected_device_python_callback(void *user_data)
|
|
|
|
gattlib_disconnected_device_python_callback = gattlib.gattlib_disconnected_device_python_callback
|
|
|
|
gattlib_disconnected_device_python_callback.argtypes = [py_object]
|
|
|
|
gattlib_disconnected_device_python_callback.restype = c_void_p
|
|
|
|
|
|
|
|
# void gattlib_notification_device_python_callback(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data);
|
|
|
|
gattlib_notification_device_python_callback = gattlib.gattlib_notification_device_python_callback
|
|
|
|
gattlib_notification_device_python_callback.argtypes = [c_void_p, c_void_p, c_int, c_void_p]
|
|
|
|
gattlib_notification_device_python_callback.restype = c_void_p
|
|
|
|
|
|
|
|
# void* gattlib_python_callback_args(PyObject* python_callback, PyObject* python_args) {
|
|
|
|
gattlib_python_callback_args = gattlib.gattlib_python_callback_args
|
|
|
|
gattlib_python_callback_args.argtypes = [py_object, py_object]
|
|
|
|
gattlib_python_callback_args.restype = c_void_p
|
2019-05-19 12:47:21 +02:00
|
|
|
|
2024-04-24 13:10:55 +02:00
|
|
|
# int gattlib_adapter_scan_enable_with_filter_non_blocking(gattlib_adapter_t* adapter, uuid_t **uuid_list,
|
|
|
|
# int16_t rssi_threshold, uint32_t enabled_filters,
|
2020-04-09 11:37:59 +02:00
|
|
|
# gattlib_discovered_device_t discovered_device_cb, size_t timeout, void *user_data)
|
2022-05-13 16:10:55 +02:00
|
|
|
gattlib_adapter_scan_enable_with_filter_non_blocking = gattlib.gattlib_adapter_scan_enable_with_filter_non_blocking
|
2024-04-24 13:10:55 +02:00
|
|
|
gattlib_adapter_scan_enable_with_filter_non_blocking.argtypes = [c_void_p, POINTER(POINTER(GattlibUuid)),
|
|
|
|
c_int16, c_uint32, c_void_p, c_size_t, c_void_p]
|
2019-07-15 11:39:04 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_adapter_scan_eddystone(gattlib_adapter_t* adapter, int16_t rssi_threshold, uint32_t eddsytone_types,
|
2020-04-09 11:37:59 +02:00
|
|
|
# gattlib_discovered_device_with_data_t discovered_device_cb, size_t timeout, void *user_data)
|
2019-07-15 11:39:04 +02:00
|
|
|
gattlib_adapter_scan_eddystone = gattlib.gattlib_adapter_scan_eddystone
|
2024-03-17 15:24:32 +01:00
|
|
|
gattlib_adapter_scan_eddystone.argtypes = [c_void_p, c_int16, c_uint32, py_object, c_size_t, py_object]
|
2019-07-09 14:03:06 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_connect(gattlib_adapter_t* adapter, const char *dst, unsigned long options, gatt_connect_cb_t connect_cb, void* user_data)
|
2020-04-06 22:34:36 +02:00
|
|
|
gattlib_connect = gattlib.gattlib_connect
|
2024-02-22 19:52:48 +01:00
|
|
|
gattlib_connect.argtypes = [c_void_p, c_char_p, c_ulong, c_void_p, c_void_p]
|
2020-04-06 22:34:36 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_disconnect(gattlib_connection_t* connection, bool wait_disconnection);
|
2020-04-06 22:34:36 +02:00
|
|
|
gattlib_disconnect = gattlib.gattlib_disconnect
|
2024-03-28 11:52:57 +01:00
|
|
|
gattlib_disconnect.argtypes = [c_void_p, c_bool]
|
2020-04-06 22:34:36 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_discover_primary(gattlib_connection_t* connection, gattlib_primary_service_t** services, int* services_count);
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_discover_primary = gattlib.gattlib_discover_primary
|
|
|
|
gattlib_discover_primary.argtypes = [c_void_p, POINTER(POINTER(GattlibPrimaryService)), POINTER(c_int)]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_discover_char(gattlib_connection_t* connection, gattlib_characteristic_t** characteristics, int* characteristic_count);
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_discover_char = gattlib.gattlib_discover_char
|
|
|
|
gattlib_discover_char.argtypes = [c_void_p, POINTER(POINTER(GattlibCharacteristic)), POINTER(c_int)]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_read_char_by_uuid(gattlib_connection_t* connection, uuid_t* uuid, void** buffer, size_t* buffer_len);
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_read_char_by_uuid = gattlib.gattlib_read_char_by_uuid
|
|
|
|
gattlib_read_char_by_uuid.argtypes = [c_void_p, POINTER(GattlibUuid), POINTER(c_void_p), POINTER(c_size_t)]
|
|
|
|
|
2022-05-16 20:58:39 +02:00
|
|
|
# void gattlib_characteristic_free_value(void* buffer);
|
|
|
|
gattlib_characteristic_free_value = gattlib.gattlib_characteristic_free_value
|
|
|
|
gattlib_characteristic_free_value.argtypes = [c_void_p]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_write_char_by_uuid(gattlib_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len)
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_write_char_by_uuid = gattlib.gattlib_write_char_by_uuid
|
|
|
|
gattlib_write_char_by_uuid.argtypes = [c_void_p, POINTER(GattlibUuid), c_void_p, c_size_t]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_write_without_response_char_by_uuid(gattlib_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len)
|
2019-07-14 15:24:50 +02:00
|
|
|
gattlib_write_without_response_char_by_uuid = gattlib.gattlib_write_without_response_char_by_uuid
|
|
|
|
gattlib_write_without_response_char_by_uuid.argtypes = [c_void_p, POINTER(GattlibUuid), c_void_p, c_size_t]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_write_char_by_uuid_stream_open(gattlib_connection_t* connection, uuid_t* uuid, gattlib_stream_t **stream, uint16_t *mtu)
|
2019-07-09 21:56:51 +02:00
|
|
|
gattlib_write_char_by_uuid_stream_open = gattlib.gattlib_write_char_by_uuid_stream_open
|
|
|
|
gattlib_write_char_by_uuid_stream_open.argtypes = [c_void_p, POINTER(GattlibUuid), POINTER(c_void_p), POINTER(c_uint16)]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_notification_start(gattlib_connection_t* connection, const uuid_t* uuid);
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_notification_start = gattlib.gattlib_notification_start
|
|
|
|
gattlib_notification_start.argtypes = [c_void_p, POINTER(GattlibUuid)]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_notification_stop(gattlib_connection_t* connection, const uuid_t* uuid);
|
2019-05-19 12:47:21 +02:00
|
|
|
gattlib_notification_stop = gattlib.gattlib_notification_stop
|
|
|
|
gattlib_notification_stop.argtypes = [c_void_p, POINTER(GattlibUuid)]
|
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_register_notification(gattlib_connection_t* connection, gattlib_event_handler_t notification_handler, void* user_data);
|
2024-02-12 13:29:40 +01:00
|
|
|
gattlib_register_notification = gattlib.gattlib_register_notification
|
|
|
|
gattlib_register_notification.argtypes = [c_void_p, c_void_p, c_void_p]
|
2019-05-19 12:47:21 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_register_on_disconnect(gattlib_connection_t *connection, PyObject *handler, PyObject *user_data)
|
2024-02-12 13:29:40 +01:00
|
|
|
gattlib_register_on_disconnect = gattlib.gattlib_register_on_disconnect
|
|
|
|
gattlib_register_on_disconnect.argtypes = [c_void_p, c_void_p, c_void_p]
|
2019-07-09 12:16:48 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_get_rssi(gattlib_connection_t *connection, int16_t *rssi)
|
2022-05-13 22:38:06 +02:00
|
|
|
gattlib_get_rssi = gattlib.gattlib_get_rssi
|
|
|
|
gattlib_get_rssi.argtypes = [c_void_p, POINTER(c_int16)]
|
2019-07-09 18:17:28 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_get_rssi_from_mac(gattlib_adapter_t* adapter, const char *mac_address, int16_t *rssi)
|
2019-07-09 18:17:28 +02:00
|
|
|
gattlib_get_rssi_from_mac = gattlib.gattlib_get_rssi_from_mac
|
|
|
|
gattlib_get_rssi_from_mac.argtypes = [c_void_p, c_char_p, POINTER(c_int16)]
|
2019-07-14 23:26:47 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_get_advertisement_data(gattlib_connection_t *connection,
|
2020-04-08 22:51:29 +02:00
|
|
|
# gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
|
2024-04-10 10:33:10 +02:00
|
|
|
# gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
|
2020-04-08 22:51:29 +02:00
|
|
|
gattlib_get_advertisement_data = gattlib.gattlib_get_advertisement_data
|
2024-04-24 13:10:55 +02:00
|
|
|
gattlib_get_advertisement_data.argtypes = [c_void_p,
|
|
|
|
POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t),
|
|
|
|
POINTER(POINTER(GattlibManufacturerData)), POINTER(c_size_t)]
|
2020-04-08 22:51:29 +02:00
|
|
|
|
2024-04-05 11:43:21 +02:00
|
|
|
# int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
|
2019-07-14 23:26:47 +02:00
|
|
|
# gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_length,
|
2024-04-10 10:33:10 +02:00
|
|
|
# gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
|
2019-07-14 23:26:47 +02:00
|
|
|
gattlib_get_advertisement_data_from_mac = gattlib.gattlib_get_advertisement_data_from_mac
|
2024-04-24 13:10:55 +02:00
|
|
|
gattlib_get_advertisement_data_from_mac.argtypes = [c_void_p, c_char_p,
|
|
|
|
POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t),
|
|
|
|
POINTER(POINTER(GattlibManufacturerData)), POINTER(c_size_t)]
|
2024-02-09 09:54:12 +01:00
|
|
|
|
|
|
|
# int gattlib_mainloop_python(PyObject *handler, PyObject *user_data)
|
|
|
|
gattlib_mainloop = gattlib.gattlib_mainloop_python
|
|
|
|
gattlib_mainloop.argtypes = [py_object, py_object]
|
2024-03-13 13:49:13 +01:00
|
|
|
|
|
|
|
# void gattlib_free_mem(void *ptr])
|
|
|
|
gattlib_free_mem = gattlib.gattlib_free_mem
|
|
|
|
gattlib_free_mem.argtypes = [c_void_p]
|