gattlib: Add stream API

pull/118/head
Olivier Martin 2019-07-09 21:56:51 +02:00 committed by Olivier Martin
parent 2831cdf765
commit 4f8625cedf
5 changed files with 144 additions and 0 deletions

View File

@ -83,6 +83,7 @@ include_directories(. ${CMAKE_SOURCE_DIR}/common ${CMAKE_CURRENT_BINARY_DIR} ${G
set(gattlib_SRCS gattlib.c
gattlib_adapter.c
gattlib_char.c
gattlib_stream.c
bluez5/lib/uuid.c
${CMAKE_SOURCE_DIR}/common/gattlib_common.c
${CMAKE_CURRENT_BINARY_DIR}/org-bluez-adaptater1.c

96
dbus/gattlib_stream.c Normal file
View File

@ -0,0 +1,96 @@
/*
*
* GattLib - GATT Library
*
* Copyright (C) 2016-2019 Olivier Martin <olivier@labapart.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <gio/gunixfdlist.h>
#include "gattlib_internal.h"
#if BLUEZ_VERSION < BLUEZ_VERSIONS(5, 48)
int gattlib_write_char_by_uuid_stream_open(gatt_connection_t* connection, uuid_t* uuid, gatt_stream_t **stream, uint16_t *mtu)
{
return GATTLIB_NOT_SUPPORTED;
}
int gattlib_write_char_stream_write(gatt_stream_t *stream, const void *buffer, size_t buffer_len)
{
return GATTLIB_NOT_SUPPORTED;
}
int gattlib_write_char_stream_close(gatt_stream_t *stream)
{
return GATTLIB_NOT_SUPPORTED;
}
#else
int gattlib_write_char_by_uuid_stream_open(gatt_connection_t* connection, uuid_t* uuid, gatt_stream_t **stream, uint16_t *mtu)
{
struct dbus_characteristic dbus_characteristic = get_characteristic_from_uuid(connection, uuid);
GError *error = NULL;
GUnixFDList *fd_list;
GVariant *out_fd;
int fd;
GVariantBuilder *variant_options = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
org_bluez_gatt_characteristic1_call_acquire_write_sync(
dbus_characteristic.gatt,
g_variant_builder_end(variant_options),
NULL /* fd_list */,
&out_fd, mtu,
&fd_list,
NULL /* cancellable */, &error);
if (error != NULL) {
fprintf(stderr, "Failed to acquired write DBus GATT characteristic: %s\n", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
}
error = NULL;
fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(out_fd), &error);
if (error != NULL) {
fprintf(stderr, "Failed to retrieve Unix File Descriptor: %s\n", error->message);
g_error_free(error);
return GATTLIB_ERROR_DBUS;
}
// We abuse the pointer 'stream' to pass the 'File Descriptor'
*stream = (gatt_stream_t*)(unsigned long)fd;
return GATTLIB_SUCCESS;
}
int gattlib_write_char_stream_write(gatt_stream_t *stream, const void *buffer, size_t buffer_len)
{
write((unsigned long)stream, buffer, buffer_len);
return GATTLIB_SUCCESS;
}
int gattlib_write_char_stream_close(gatt_stream_t *stream)
{
close((unsigned long)stream);
return GATTLIB_SUCCESS;
}
#endif /* #if BLUEZ_VERSION < BLUEZ_VERSIONS(5, 48) */

View File

@ -78,6 +78,10 @@ gattlib_read_char_by_uuid.argtypes = [c_void_p, POINTER(GattlibUuid), POINTER(c_
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]
# int gattlib_write_char_by_uuid_stream_open(gatt_connection_t* connection, uuid_t* uuid, gatt_stream_t **stream, uint16_t *mtu)
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)]
# int gattlib_notification_start(gatt_connection_t* connection, const uuid_t* uuid);
gattlib_notification_start = gattlib.gattlib_notification_start
gattlib_notification_start.argtypes = [c_void_p, POINTER(GattlibUuid)]

View File

@ -3,6 +3,35 @@ from .uuid import gattlib_uuid_to_uuid, gattlib_uuid_to_int
from .exception import handle_return
class GattStream():
def __init__(self, fd, mtu):
self._fd = fd
self._mtu = mtu
@property
def mtu(self):
# Remove ATT Header (3 bytes)
return self._mtu - 3
def write(self, data, mtu=None):
if mtu is None:
mtu = self.mtu
while len(data) > 0:
frame = data[0:mtu]
data = data[mtu:]
buffer_type = c_char * len(frame)
buffer = frame
buffer_len = len(frame)
gattlib.gattlib_write_char_stream_write(self._fd, buffer_type.from_buffer_copy(buffer), buffer_len)
def close(self):
gattlib.gattlib_write_char_stream_close(self._fd)
class GattService():
def __init__(self, device, gattlib_primary_service):
@ -62,6 +91,15 @@ class GattCharacteristic():
ret = gattlib_write_char_by_uuid(self.connection, self._gattlib_characteristic.uuid, buffer_type.from_buffer_copy(buffer), buffer_len)
handle_return(ret)
def stream_open(self):
_stream = c_void_p(None)
_mtu = c_uint16(0)
ret = gattlib_write_char_by_uuid_stream_open(self.connection, self._gattlib_characteristic.uuid, byref(_stream), byref(_mtu))
handle_return(ret)
return GattStream(_stream, _mtu.value)
def register_notification(self, callback, user_data=None):
self._device._notification_add_gatt_characteristic_callback(self, callback, user_data)

View File

@ -94,6 +94,7 @@ extern "C" {
#define GATTLIB_DISCOVER_FILTER_USE_RSSI (1 << 1)
typedef struct _gatt_connection_t gatt_connection_t;
typedef struct _gatt_stream_t gatt_stream_t;
typedef void (*gattlib_event_handler_t)(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data);
@ -336,6 +337,10 @@ int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle,
*/
int gattlib_write_without_response_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len);
int gattlib_write_char_by_uuid_stream_open(gatt_connection_t* connection, uuid_t* uuid, gatt_stream_t **stream, uint16_t *mtu);
int gattlib_write_char_stream_write(gatt_stream_t *stream, const void *buffer, size_t buffer_len);
int gattlib_write_char_stream_close(gatt_stream_t *stream);
/**
* @brief Function to write without response to the GATT characteristic handle
*