wip: implementing functionality
This commit is contained in:
parent
e6bd99a5ee
commit
a76ad3415c
@ -240,7 +240,12 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
|
|||||||
self->advertising_timeout_msecs = 0;
|
self->advertising_timeout_msecs = 0;
|
||||||
|
|
||||||
// Reset list of known attributes.
|
// Reset list of known attributes.
|
||||||
|
// Indices into the list are handles. Handle 0x0000 designates an invalid handle,
|
||||||
|
// so store None there to skip it.
|
||||||
self->attributes = mp_obj_new_list(0, NULL);
|
self->attributes = mp_obj_new_list(0, NULL);
|
||||||
|
bleio_adapter_add_attribute(mp_const_none);
|
||||||
|
self->last_added_service_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
|
self->last_added_characteristic_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
|
bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
|
||||||
@ -683,6 +688,25 @@ void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
|
|||||||
//FIX bonding_erase_storage();
|
//FIX bonding_erase_storage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute) {
|
||||||
|
// The handle is the index of this attribute in the attributes list.
|
||||||
|
uint16_t handle = (uint16_t) adapter->attributes->len;
|
||||||
|
mp_obj_list_append(adapter->attributes, attribute);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle) {
|
||||||
|
if (handle == 0 || handle >= adapter->attributes->len) {
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
return adapter->attributes->items[handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) {
|
||||||
|
return adapter->attributes->len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) {
|
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) {
|
||||||
gc_collect_root((void**)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t));
|
gc_collect_root((void**)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t));
|
||||||
gc_collect_root((void**)bleio_connections, sizeof(bleio_connections) / sizeof(size_t));
|
gc_collect_root((void**)bleio_connections, sizeof(bleio_connections) / sizeof(size_t));
|
||||||
|
@ -68,8 +68,15 @@ typedef struct _bleio_adapter_obj_t {
|
|||||||
// All the local attributes for this device. The index into the list
|
// All the local attributes for this device. The index into the list
|
||||||
// corresponds to the handle.
|
// corresponds to the handle.
|
||||||
mp_obj_list_t *attributes;
|
mp_obj_list_t *attributes;
|
||||||
|
// Handle for last added service. Characteristics can only be added immediately after
|
||||||
|
// the service they belong to. This vets that.
|
||||||
|
uint16_t last_added_service_handle;
|
||||||
|
uint16_t last_added_characteristic_handle;
|
||||||
} bleio_adapter_obj_t;
|
} bleio_adapter_obj_t;
|
||||||
|
|
||||||
|
uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute);
|
||||||
|
mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle);
|
||||||
|
uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter);
|
||||||
void bleio_adapter_background(bleio_adapter_obj_t* adapter);
|
void bleio_adapter_background(bleio_adapter_obj_t* adapter);
|
||||||
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter);
|
void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter);
|
||||||
void bleio_adapter_reset(bleio_adapter_obj_t* adapter);
|
void bleio_adapter_reset(bleio_adapter_obj_t* adapter);
|
||||||
|
@ -25,10 +25,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "shared-bindings/_bleio/Attribute.h"
|
#include "shared-bindings/_bleio/Attribute.h"
|
||||||
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
|
||||||
// Return the type of the attribute
|
// Return the type of the attribute.
|
||||||
bleio_attribute_type_uuid(mp_obj_t *attribute) {
|
ble_attribute_type bleio_attribute_type_uuid(mp_obj_t *attribute) {
|
||||||
if mp_is_o
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||||
|
return BLE_TYPE_CHARACTERISTIC;
|
||||||
|
}
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_descriptor_type)) {
|
||||||
|
return BLE_TYPE_DESCRIPTOR;
|
||||||
|
}
|
||||||
|
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
|
||||||
|
bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute);
|
||||||
|
return service->is_secondary ? BLE_TYPE_SECONDARY_SERVICE : BLE_TYPE_PRIMARY_SERVICE;
|
||||||
|
}
|
||||||
|
return BLE_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting.
|
// Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting.
|
||||||
// void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) {
|
// void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
|
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -29,6 +29,15 @@
|
|||||||
|
|
||||||
#include "shared-module/_bleio/Attribute.h"
|
#include "shared-module/_bleio/Attribute.h"
|
||||||
|
|
||||||
|
// Types returned by attribute table lookups. These are UUIDs.
|
||||||
|
enum ble_attribute_type {
|
||||||
|
BLE_TYPE_UNKNOWN = 0x0000,
|
||||||
|
BLE_TYPE_PRIMARY_SERVICE = 0x2800,
|
||||||
|
BLE_TYPE_SECONDARY_SERVICE = 0x2801,
|
||||||
|
BLE_TYPE_CHARACTERISTIC = 0x2803,
|
||||||
|
BLE_TYPE_DESCRIPTOR = 0x2900
|
||||||
|
};
|
||||||
|
|
||||||
// typedef struct
|
// typedef struct
|
||||||
// {
|
// {
|
||||||
// uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */
|
// uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */
|
||||||
|
@ -34,58 +34,10 @@
|
|||||||
|
|
||||||
#include "common-hal/_bleio/Adapter.h"
|
#include "common-hal/_bleio/Adapter.h"
|
||||||
|
|
||||||
// STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) {
|
|
||||||
// uint16_t cccd;
|
|
||||||
// // ble_gatts_value_t value = {
|
|
||||||
// // .p_value = (uint8_t*) &cccd,
|
|
||||||
// // .len = 2,
|
|
||||||
// // };
|
|
||||||
|
|
||||||
// // const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value);
|
|
||||||
|
|
||||||
// // if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
|
|
||||||
// // // CCCD is not set, so say that neither Notify nor Indicate is enabled.
|
|
||||||
// // cccd = 0;
|
|
||||||
// // } else {
|
|
||||||
// // check_nrf_error(err_code);
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// return cccd;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
|
|
||||||
// uint16_t hvx_len = bufinfo->len;
|
|
||||||
|
|
||||||
// ble_gatts_hvx_params_t hvx_params = {
|
|
||||||
// .handle = handle,
|
|
||||||
// .type = hvx_type,
|
|
||||||
// .offset = 0,
|
|
||||||
// .p_len = &hvx_len,
|
|
||||||
// .p_data = bufinfo->buf,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// while (1) {
|
|
||||||
// const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
|
||||||
// if (err_code == NRF_SUCCESS) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // TX buffer is full
|
|
||||||
// // We could wait for an event indicating the write is complete, but just retrying is easier.
|
|
||||||
// if (err_code == NRF_ERROR_RESOURCES) {
|
|
||||||
// RUN_BACKGROUND_TASKS;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Some real error has occurred.
|
|
||||||
// check_nrf_error(err_code);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
self->service = service;
|
self->service = service;
|
||||||
self->uuid = uuid;
|
self->uuid = uuid;
|
||||||
//FIX self->handle = BLE_GATT_HANDLE_INVALID;
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
self->props = props;
|
self->props = props;
|
||||||
self->read_perm = read_perm;
|
self->read_perm = read_perm;
|
||||||
self->write_perm = write_perm;
|
self->write_perm = write_perm;
|
||||||
@ -153,30 +105,23 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
|
|||||||
// Always write the value locally even if no connections are active.
|
// Always write the value locally even if no connections are active.
|
||||||
// conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID.
|
// conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID.
|
||||||
common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo);
|
common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo);
|
||||||
// Check to see if we need to notify or indicate any active connections.
|
// Notify or indicate all active connections.
|
||||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
uint16_t cccd = 0;
|
||||||
bleio_connection_internal_t *connection = &bleio_connections[i];
|
|
||||||
uint16_t conn_handle = connection->conn_handle;
|
const bool notify = self->props & CHAR_PROP_NOTIFY;
|
||||||
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
const bool indicate = self->props & CHAR_PROP_INDICATE;
|
||||||
continue;
|
// Read the CCCD value, if there is one.
|
||||||
|
if ((notify | indicate) && self->cccd_handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
|
common_hal_bleio_gatts_read(self->cccd_handle, conn_handle, &cccd, sizeof(cccd));
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIX
|
// It's possible that both notify and indicate are set.
|
||||||
// uint16_t cccd = 0;
|
if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
|
||||||
|
att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
||||||
|
}
|
||||||
|
if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
|
||||||
|
att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
||||||
|
|
||||||
// const bool notify = self->props & CHAR_PROP_NOTIFY;
|
|
||||||
// const bool indicate = self->props & CHAR_PROP_INDICATE;
|
|
||||||
// if (notify | indicate) {
|
|
||||||
// cccd = characteristic_get_cccd(self->cccd_handle, conn_handle);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // It's possible that both notify and indicate are set.
|
|
||||||
// if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
|
|
||||||
// characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION);
|
|
||||||
// }
|
|
||||||
// if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
|
|
||||||
// characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,35 +136,16 @@ bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties
|
|||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
|
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
|
||||||
//FIX
|
if (self->handle != common_hal_bleio_adapter_obj->last_added_characteristic_handle) {
|
||||||
// ble_uuid_t desc_uuid;
|
mp_raise_bleio_BluetoothError(
|
||||||
// bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
|
translate("Descriptor can only be added to most recently added characteristic"));
|
||||||
|
}
|
||||||
|
|
||||||
// ble_gatts_attr_md_t desc_attr_md = {
|
descriptor->handle = bleio_adapter_add_attribute(common_hal_bleio_adapter_obj, descriptor);
|
||||||
// // Data passed is not in a permanent location and should be copied.
|
|
||||||
// .vloc = BLE_GATTS_VLOC_STACK,
|
|
||||||
// .vlen = !descriptor->fixed_length,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// bleio_attribute_gatts_set_security_mode(&desc_attr_md.read_perm, descriptor->read_perm);
|
// Link together all the descriptors for this characteristic.
|
||||||
// bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm);
|
descriptor->next = self->descriptor_list;
|
||||||
|
self->descriptor_list = descriptor;
|
||||||
// mp_buffer_info_t desc_value_bufinfo;
|
|
||||||
// mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
|
|
||||||
|
|
||||||
// ble_gatts_attr_t desc_attr = {
|
|
||||||
// .p_uuid = &desc_uuid,
|
|
||||||
// .p_attr_md = &desc_attr_md,
|
|
||||||
// .init_len = desc_value_bufinfo.len,
|
|
||||||
// .p_value = desc_value_bufinfo.buf,
|
|
||||||
// .init_offs = 0,
|
|
||||||
// .max_len = descriptor->max_length,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// check_nrf_error(sd_ble_gatts_descriptor_add(self->handle, &desc_attr, &descriptor->handle));
|
|
||||||
|
|
||||||
// descriptor->next = self->descriptor_list;
|
|
||||||
// self->descriptor_list = descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
|
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
|
||||||
@ -234,11 +160,12 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
|
|||||||
const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
common_hal_bleio_check_connected(conn_handle);
|
common_hal_bleio_check_connected(conn_handle);
|
||||||
|
|
||||||
//FIX
|
uint16_t cccd_value =
|
||||||
// uint16_t cccd_value =
|
(notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
|
||||||
// (notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
|
(indicate ? BLE_GATT_HVX_INDICATION : 0);
|
||||||
// (indicate ? BLE_GATT_HVX_INDICATION : 0);
|
|
||||||
|
|
||||||
|
(void) cccd_value;
|
||||||
|
//FIX call att_something to set remote CCCD
|
||||||
// ble_gattc_write_params_t write_params = {
|
// ble_gattc_write_params_t write_params = {
|
||||||
// .write_op = BLE_GATT_OP_WRITE_REQ,
|
// .write_op = BLE_GATT_OP_WRITE_REQ,
|
||||||
// .handle = self->cccd_handle,
|
// .handle = self->cccd_handle,
|
||||||
|
@ -43,6 +43,7 @@ typedef struct _bleio_characteristic_obj {
|
|||||||
uint16_t max_length;
|
uint16_t max_length;
|
||||||
bool fixed_length;
|
bool fixed_length;
|
||||||
uint16_t handle;
|
uint16_t handle;
|
||||||
|
uint16_t value_handle; // Should be handle+1.
|
||||||
bleio_characteristic_properties_t props;
|
bleio_characteristic_properties_t props;
|
||||||
bleio_attribute_security_mode_t read_perm;
|
bleio_attribute_security_mode_t read_perm;
|
||||||
bleio_attribute_security_mode_t write_perm;
|
bleio_attribute_security_mode_t write_perm;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||||
* Copyright (c) 2018 Artur Pacholec
|
* Copyright (c) 2018 Artur Pacholec
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -33,7 +33,6 @@
|
|||||||
#include "shared-bindings/_bleio/Adapter.h"
|
#include "shared-bindings/_bleio/Adapter.h"
|
||||||
|
|
||||||
uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list) {
|
uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list) {
|
||||||
self->handle = 0xFFFF;
|
|
||||||
self->uuid = uuid;
|
self->uuid = uuid;
|
||||||
self->characteristic_list = characteristic_list;
|
self->characteristic_list = characteristic_list;
|
||||||
self->is_remote = false;
|
self->is_remote = false;
|
||||||
@ -42,16 +41,18 @@ uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uu
|
|||||||
|
|
||||||
vm_used_ble = true;
|
vm_used_ble = true;
|
||||||
|
|
||||||
self->handle = bleio_adapter_add_attribute(
|
self->handle = bleio_adapter_add_attribute(common_hal_bleio_adapter_obj, self);
|
||||||
common_hal_bleio_adapter_obj,
|
if (self->handle = BLE_GATT_HANDLE_INVALID) {
|
||||||
is_secondary ? BLE_TYPE_SECONDARY_SERVICE : BLE_TYPE_PRIMARY_SERVICE,
|
return 1;
|
||||||
uuid, &status);
|
}
|
||||||
return status;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
|
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
|
||||||
check_hci_error(_common_hal_bleio_service_construct(self, uuid, is_secondary,
|
if (_common_hal_bleio_service_construct(self, uuid, is_secondary,
|
||||||
mp_obj_new_list(0, NULL)));
|
mp_obj_new_list(0, NULL)) != 0) {
|
||||||
|
mp_raise_RuntimeError(translate("Failed to add service"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) {
|
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) {
|
||||||
@ -83,83 +84,36 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
|||||||
bleio_characteristic_obj_t *characteristic,
|
bleio_characteristic_obj_t *characteristic,
|
||||||
mp_buffer_info_t *initial_value_bufinfo) {
|
mp_buffer_info_t *initial_value_bufinfo) {
|
||||||
|
|
||||||
//FIX how it's done by ArduinoBLE when a service is added.
|
if (self->handle != common_hal_bleio_adapter_obj->last_added_service_handle) {
|
||||||
// uint16_t startHandle = attributeCount();
|
mp_raise_bleio_BluetoothError(
|
||||||
uint16_t start_handle bleio_adapter_num_attributes(common_hal_bleio_adapter_obj);
|
translate("Characteristic can only be added to most recently added service"));
|
||||||
|
}
|
||||||
|
characteristic->decl_handle = bleio_adapter_add_attribute(common_hal_bleio_adapter_obj, characteristic);
|
||||||
|
// This is the value handle
|
||||||
|
characteristic->value_handle = bleio_adapter_add_attribute(common_hal_bleio_adapter_obj, characteristic);
|
||||||
|
|
||||||
// for (unsigned int i = 0; i < service->characteristicCount(); i++) {
|
if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) {
|
||||||
// BLELocalCharacteristic* characteristic = service->characteristic(i);
|
// We need a CCCD.
|
||||||
|
bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t);
|
||||||
|
cccd->base.type = &bleio_descriptor_type;
|
||||||
|
cccd->read_perm = SECURITY_MODE_OPEN;
|
||||||
|
// Make CCCD write permission match characteristic read permission.
|
||||||
|
cccd->write_perm = characteristic->read_perm;
|
||||||
|
characteristic->cccd_handle = common_hal_bleio_characteristic_add_descriptor(characteristic, cccd);
|
||||||
|
}
|
||||||
|
|
||||||
// characteristic->retain();
|
|
||||||
// _attributes.add(characteristic);
|
|
||||||
// characteristic->setHandle(attributeCount());
|
|
||||||
|
|
||||||
// // add the characteristic again to make space of the characteristic value handle
|
|
||||||
// _attributes.add(characteristic);
|
|
||||||
|
|
||||||
// for (unsigned int j = 0; j < characteristic->descriptorCount(); j++) {
|
|
||||||
// BLELocalDescriptor* descriptor = characteristic->descriptor(j);
|
|
||||||
|
|
||||||
// descriptor->retain();
|
|
||||||
// _attributes.add(descriptor);
|
|
||||||
// descriptor->setHandle(attributeCount());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
service->setHandles(startHandle, attributeCount());
|
|
||||||
// ble_gatts_char_md_t char_md = {
|
|
||||||
// .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0,
|
|
||||||
// .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0,
|
|
||||||
// .char_props.write_wo_resp = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0,
|
|
||||||
// .char_props.write = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0,
|
|
||||||
// .char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0,
|
|
||||||
// .char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// ble_gatts_attr_md_t cccd_md = {
|
|
||||||
// .vloc = BLE_GATTS_VLOC_STACK,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// ble_gatts_attr_md_t char_attr_md = {
|
|
||||||
// .vloc = BLE_GATTS_VLOC_STACK,
|
|
||||||
// .vlen = !characteristic->fixed_length,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if (char_md.char_props.notify || char_md.char_props.indicate) {
|
|
||||||
// BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
|
|
||||||
// // Make CCCD write permission match characteristic read permission.
|
|
||||||
// bleio_attribute_gatts_set_security_mode(&cccd_md.write_perm, characteristic->read_perm);
|
|
||||||
|
|
||||||
// char_md.p_cccd_md = &cccd_md;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm);
|
|
||||||
// bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm);
|
|
||||||
// #if CIRCUITPY_VERBOSE_BLE
|
// #if CIRCUITPY_VERBOSE_BLE
|
||||||
// // Turn on read authorization so that we receive an event to print on every read.
|
// // Turn on read authorization so that we receive an event to print on every read.
|
||||||
// char_attr_md.rd_auth = true;
|
// char_attr_md.rd_auth = true;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// ble_gatts_attr_t char_attr = {
|
// These are not supplied or available.
|
||||||
// .p_uuid = &char_uuid,
|
characteristic->user_desc_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
// .p_attr_md = &char_attr_md,
|
characteristic->sccd_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
// .init_len = 0,
|
|
||||||
// .p_value = NULL,
|
|
||||||
// .init_offs = 0,
|
|
||||||
// .max_len = characteristic->max_length,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// ble_gatts_char_handles_t char_handles;
|
|
||||||
|
|
||||||
// check_nrf_error(sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles));
|
|
||||||
|
|
||||||
// characteristic->user_desc_handle = char_handles.user_desc_handle;
|
|
||||||
// characteristic->cccd_handle = char_handles.cccd_handle;
|
|
||||||
// characteristic->sccd_handle = char_handles.sccd_handle;
|
|
||||||
// characteristic->handle = char_handles.value_handle;
|
|
||||||
// #if CIRCUITPY_VERBOSE_BLE
|
// #if CIRCUITPY_VERBOSE_BLE
|
||||||
// mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle);
|
// mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle);
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,10 @@ void check_hci_error(hci_result_t result) {
|
|||||||
mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter"));
|
mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter"));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case HCI_ATT_ERROR:
|
||||||
|
mp_raise_RuntimeError(translate("Error in ATT protocol code"));
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Should be an HCI status error, > 0.
|
// Should be an HCI status error, > 0.
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
|
@ -30,22 +30,15 @@
|
|||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "common-hal/_bleio/Adapter.h"
|
#include "common-hal/_bleio/Adapter.h"
|
||||||
|
#include "common-hal/_bleio/Attribute.h"
|
||||||
#include "supervisor/shared/tick.h"
|
#include "supervisor/shared/tick.h"
|
||||||
|
|
||||||
enum ble_attribute_type {
|
|
||||||
BLE_TYPE_UNKNOWN = 0x0000,
|
|
||||||
BLE_TYPE_PRIMARY_SERVICE = 0x2800,
|
|
||||||
BLE_TYPE_SECONDARY_SERVICE = 0x2801,
|
|
||||||
BLE_TYPE_CHARACTERISTIC = 0x2803,
|
|
||||||
BLE_TYPE_DESCRIPTOR = 0x2900
|
|
||||||
};
|
|
||||||
|
|
||||||
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23
|
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23
|
||||||
STATIC unsigned long timeout = 5000;
|
STATIC unsigned long timeout = 5000;
|
||||||
|
|
||||||
STATIC volatile bool confirm;
|
STATIC volatile bool confirm;
|
||||||
|
|
||||||
STATIC uint16_t long_write_handle = 0x0000;
|
STATIC uint16_t long_write_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
STATIC uint8_t* long_write_value = NULL;
|
STATIC uint8_t* long_write_value = NULL;
|
||||||
STATIC uint16_t long_write_value_length = 0;
|
STATIC uint16_t long_write_value_length = 0;
|
||||||
|
|
||||||
@ -123,7 +116,7 @@ STATIC void check_and_save_expected_rsp(uint16_t conn_handle, uint8_t opcode, ui
|
|||||||
void att_init(void) {
|
void att_init(void) {
|
||||||
max_mtu = BT_ATT_DEFAULT_LE_MTU;
|
max_mtu = BT_ATT_DEFAULT_LE_MTU;
|
||||||
timeout = 5000;
|
timeout = 5000;
|
||||||
long_write_handle = 0x0000;
|
long_write_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
long_write_value = NULL;
|
long_write_value = NULL;
|
||||||
long_write_value_length = 0;
|
long_write_value_length = 0;
|
||||||
|
|
||||||
@ -225,12 +218,12 @@ bool att_disconnect_from_address(bt_addr_le_t *addr) {
|
|||||||
|
|
||||||
// reqStart_handle = rawService->end_handle + 1;
|
// reqStart_handle = rawService->end_handle + 1;
|
||||||
|
|
||||||
// if (reqStart_handle == 0x0000) {
|
// if (reqStart_handle == BLE_GATT_HANDLE_INVALID) {
|
||||||
// reqEnd_handle = 0x0000;
|
// reqEnd_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
// reqEnd_handle = 0x0000;
|
// reqEnd_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -498,7 +491,7 @@ void att_remove_connection(uint16_t handle, uint8_t reason) {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
long_write_handle = 0x0000;
|
long_write_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
long_write_value_length = 0;
|
long_write_value_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +612,7 @@ bool att_disconnect_all(void) {
|
|||||||
// return BLEDevice();
|
// return BLEDevice();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
bool att_handle_notify(uint16_t handle, const uint8_t* value, int length) {
|
bool att_notify(uint16_t handle, const uint8_t* value, int length) {
|
||||||
int num_notifications = 0;
|
int num_notifications = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
@ -627,21 +620,20 @@ bool att_handle_notify(uint16_t handle, const uint8_t* value, int length) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIX This seems fishy. Why just .mtu instead of .mtu + 1 for opcode
|
typedef struct notify_t __packed {
|
||||||
uint8_t notification[bleio_connections[i].mtu];
|
struct bt_att_hdr hdr;
|
||||||
uint16_t notification_length = 0;
|
struct bt_att_notify ntf;
|
||||||
|
};
|
||||||
|
|
||||||
notification[0] = BT_ATT_OP_NOTIFY;
|
size_t allowed_length = MIN((uint16_t)(bleio_connections[i].mtu - sizeof(notify_t)), (uint16_t)length);
|
||||||
notification_length++;
|
|
||||||
|
|
||||||
memcpy(¬ification[1], &handle, sizeof(handle));
|
uint8_t notify_bytes[sizeof(cmd_s) + allowed_length];
|
||||||
notification_length += sizeof(handle);
|
notify_t *notify_p = (notify_t *) notify_bytes;
|
||||||
|
notify_p->hdr.code = BT_ATT_OP_NOTIFY;;
|
||||||
length = MIN((uint16_t)(bleio_connections[i].mtu - notification_length), (uint16_t)length);
|
notify_p->ntf.handle = handle;
|
||||||
memcpy(¬ification[notification_length], value, length);
|
memcpy(notify_p->ntf.value, data, allowed_length);
|
||||||
notification_length += length;
|
hci_send_acl_pkt(bleio_connections[i].conn_handle, BT_L2CAP_CID_ATT,
|
||||||
|
size_of(notify_bytes), notify_bytes);
|
||||||
hci_send_acl_pkt(bleio_connections[i].conn_handle, BT_L2CAP_CID_ATT, notification_length, notification);
|
|
||||||
|
|
||||||
num_notifications++;
|
num_notifications++;
|
||||||
}
|
}
|
||||||
@ -649,7 +641,7 @@ bool att_handle_notify(uint16_t handle, const uint8_t* value, int length) {
|
|||||||
return (num_notifications > 0);
|
return (num_notifications > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool att_handle_indicate(uint16_t handle, const uint8_t* value, int length) {
|
bool att_indicate(conn_handle, uint16_t handle, const uint8_t* value, int length) {
|
||||||
int num_indications = 0;
|
int num_indications = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
@ -657,22 +649,23 @@ bool att_handle_indicate(uint16_t handle, const uint8_t* value, int length) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t indication[bleio_connections[i].mtu];
|
typedef struct indicate_t __packed {
|
||||||
uint16_t indication_length = 0;
|
struct bt_att_hdr hdr;
|
||||||
|
struct bt_att_indicate ind;
|
||||||
|
};
|
||||||
|
|
||||||
indication[0] = BT_ATT_OP_INDICATE;
|
size_t allowed_length = MIN((uint16_t)(bleio_connections[i].mtu - sizeof(indicate_t)), (uint16_t)length);
|
||||||
indication_length++;
|
|
||||||
|
|
||||||
memcpy(&indication[1], &handle, sizeof(handle));
|
uint8_t indicate_bytes[sizeof(cmd_s) + allowed_length];
|
||||||
indication_length += sizeof(handle);
|
struct indicate_s *indicate_p = (indicate_s *) indicate_bytes;
|
||||||
|
indicate_p->hdr.code = BT_ATT_OP_INDICATE;;
|
||||||
length = MIN((uint16_t)(bleio_connections[i].mtu - indication_length), (uint16_t)length);
|
indicate_p->ind.handle = handle;
|
||||||
memcpy(&indication[indication_length], value, length);
|
memcpy(indicate->ind.value, data, allowed_length);
|
||||||
indication_length += length;
|
|
||||||
|
|
||||||
confirm = false;
|
confirm = false;
|
||||||
|
|
||||||
hci_send_acl_pkt(bleio_connections[i].conn_handle, BT_L2CAP_CID_ATT, indication_length, indication);
|
hci_send_acl_pkt(bleio_connections[i].conn_handle, BT_L2CAP_CID_ATT,
|
||||||
|
sizeof(indicate_bytes), indicate_bytes);
|
||||||
|
|
||||||
while (!confirm) {
|
while (!confirm) {
|
||||||
hci_poll_for_incoming_pkt();
|
hci_poll_for_incoming_pkt();
|
||||||
@ -706,7 +699,7 @@ STATIC void process_error(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
|||||||
STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
||||||
struct bt_att_exchange_mtu_req *req = (struct bt_att_exchange_mtu_req *) data;
|
struct bt_att_exchange_mtu_req *req = (struct bt_att_exchange_mtu_req *) data;
|
||||||
if (dlen != sizeof(req)) {
|
if (dlen != sizeof(req)) {
|
||||||
send_error(conn_handle, BT_ATT_OP_MTU_REQ, 0x0000, BT_ATT_ERR_INVALID_PDU);
|
send_error(conn_handle, BT_ATT_OP_MTU_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,7 +976,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
|
|||||||
|
|
||||||
if (opcode == BT_ATT_OP_READ_REQ) {
|
if (opcode == BT_ATT_OP_READ_REQ) {
|
||||||
if (dlen != sizeof(struct bt_att_read_req)) {
|
if (dlen != sizeof(struct bt_att_read_req)) {
|
||||||
send_error(conn_handle, BT_ATT_OP_READ_REQ, 0x0000, BT_ATT_ERR_INVALID_PDU);
|
send_error(conn_handle, BT_ATT_OP_READ_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -993,7 +986,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (dlen != sizeof(struct bt_att_read_blob_req)) {
|
if (dlen != sizeof(struct bt_att_read_blob_req)) {
|
||||||
send_error(conn_handle, BT_ATT_OP_READ_BLOB_REQ, 0x0000, BT_ATT_ERR_INVALID_PDU);
|
send_error(conn_handle, BT_ATT_OP_READ_BLOB_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1234,7 +1227,7 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
|
|||||||
|
|
||||||
if (dlen < sizeof(struct bt_att_write_req)) {
|
if (dlen < sizeof(struct bt_att_write_req)) {
|
||||||
if (with_response) {
|
if (with_response) {
|
||||||
send_error(conn_handle, BT_ATT_OP_WRITE_REQ, 0x0000, BT_ATT_ERR_INVALID_PDU);
|
send_error(conn_handle, BT_ATT_OP_WRITE_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1326,41 +1319,41 @@ STATIC void process_write_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void process_prepare_write_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) {
|
STATIC void process_prepare_write_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) {
|
||||||
//FIX struct bt_att_prepare_write_req *req = (struct bt_att_prepare_write_req *) data;
|
FIX struct bt_att_prepare_write_req *req = (struct bt_att_prepare_write_req *) data;
|
||||||
|
|
||||||
if (dlen < sizeof(struct bt_att_prepare_write_req)) {
|
if (dlen < sizeof(struct bt_att_prepare_write_req)) {
|
||||||
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, 0x0000, BT_ATT_ERR_INVALID_PDU);
|
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint16_t handle = req->handle;
|
uint16_t handle = req->handle;
|
||||||
// uint16_t offset = req->offset;
|
uint16_t offset = req->offset;
|
||||||
|
|
||||||
// if ((uint16_t)(handle - 1) > GATT.attributeCount()) {
|
if (handle > bleio_adapter_max_attribute_handle(common_hal_bleio_adapter_obj)) {
|
||||||
// send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTR_NOT_FOUND);
|
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTR_NOT_FOUND);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// BLELocalAttribute* attribute = GATT.attribute(handle - 1);
|
mp_obj_t *attribute = bleio_adapter_get_attribute(common_hal_bleio_adapter_obj, handle);
|
||||||
|
|
||||||
// if (attribute->type() != BLE_TYPE_CHARACTERISTIC) {
|
if (!MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||||
// send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTR_NOT_LONG);
|
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTR_NOT_LONG);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// BLELocalCharacteristic* characteristic = (BLELocalCharacteristic*)attribute;
|
bleio_characteristic_obj_t* characteristic = MP_OBJ_TO_PTR(attribute);
|
||||||
|
|
||||||
// if (handle != characteristic->value_handle()) {
|
if (handle != characteristic->value_handle) {
|
||||||
// send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTR_NOT_LONG);
|
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTR_NOT_LONG);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if ((characteristic->properties() & BLEWrqite) == 0) {
|
if (characteristic->props & CHAR_PROP_WRITE) {
|
||||||
// send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_WRITE_NOT_PERM);
|
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_WRITE_NOT_PERM);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (long_write_handle == 0) {
|
if (long_write_handle == BLE_GATT_HANDLE_INVALID)
|
||||||
// int valueSize = characteristic->valueSize();
|
// int valueSize = characteristic->valueSize();
|
||||||
|
|
||||||
// long_write_value = (uint8_t*)realloc(long_write_value, valueSize);
|
// long_write_value = (uint8_t*)realloc(long_write_value, valueSize);
|
||||||
@ -1398,7 +1391,7 @@ STATIC void process_exec_write_req(uint16_t conn_handle, uint16_t mtu, uint8_t d
|
|||||||
struct bt_att_exec_write_req *req = (struct bt_att_exec_write_req *) data;
|
struct bt_att_exec_write_req *req = (struct bt_att_exec_write_req *) data;
|
||||||
|
|
||||||
if (dlen != sizeof(struct bt_att_exec_write_req)) {
|
if (dlen != sizeof(struct bt_att_exec_write_req)) {
|
||||||
send_error(conn_handle, BT_ATT_OP_EXEC_WRITE_REQ, 0x0000, BT_ATT_ERR_INVALID_PDU);
|
send_error(conn_handle, BT_ATT_OP_EXEC_WRITE_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1413,7 +1406,7 @@ STATIC void process_exec_write_req(uint16_t conn_handle, uint16_t mtu, uint8_t d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long_write_handle = 0x0000;
|
long_write_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
long_write_value_length = 0;
|
long_write_value_length = 0;
|
||||||
|
|
||||||
uint8_t response[mtu];
|
uint8_t response[mtu];
|
||||||
@ -1515,33 +1508,35 @@ int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[
|
|||||||
}
|
}
|
||||||
|
|
||||||
int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]) {
|
int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]) {
|
||||||
struct __packed {
|
typedef struct write_req_t __packed {
|
||||||
struct bt_att_hdr h;
|
struct bt_att_hdr hdr;
|
||||||
struct bt_att_write_req r;
|
struct bt_att_write_req req;
|
||||||
} req = { {
|
|
||||||
.code = BT_ATT_OP_WRITE_REQ,
|
|
||||||
}, {
|
|
||||||
.handle = handle,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
memcpy(req.r.value, data, data_len);
|
|
||||||
|
|
||||||
return send_req_wait_for_rsp(conn_handle, sizeof(req) + data_len, (uint8_t *) &req, response_buffer);
|
uint8_t req_bytes[sizeof(write_req_t) + data_len];
|
||||||
|
struct write_req_t *write_req_P = (write_req_t *) req_bytes;
|
||||||
|
req_p->hdr.code = BT_ATT_OP_WRITE_REQ;
|
||||||
|
req_p->req.handle = handle;
|
||||||
|
memcpy(req_p->req.value, data, data_len);
|
||||||
|
|
||||||
|
memcpy(req.req.value, data, data_len);
|
||||||
|
|
||||||
|
return send_req_wait_for_rsp(conn_handle, sizeof(req_bytes), req, response_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len) {
|
void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len) {
|
||||||
struct __packed {
|
struct cmd_s __packed {
|
||||||
struct bt_att_hdr h;
|
struct bt_att_hdr h;
|
||||||
struct bt_att_write_cmd r;
|
struct bt_att_write_cmd r;
|
||||||
} req = { {
|
|
||||||
.code = BT_ATT_OP_WRITE_CMD,
|
|
||||||
}, {
|
|
||||||
.handle = handle,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
memcpy(req.r.value, data, data_len);
|
|
||||||
|
|
||||||
return send_req(conn_handle, sizeof(req) + data_len, (uint8_t *) &req);
|
uint8_t cmd_bytes[sizeof(cmd_s) + data_len];
|
||||||
|
struct cmd_s *cmd_p = (cmd_s *) cmd_bytes;
|
||||||
|
cmd_p->h.code = BT_ATT_OP_WRITE_CMD;
|
||||||
|
cmd_p->r.handle = handle;
|
||||||
|
memcpy(cmd_p->r.value, data, data_len);
|
||||||
|
|
||||||
|
return send_cmd(conn_handle, sizeof(cmd_bytes), cmd_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
||||||
|
@ -39,10 +39,10 @@ bool att_disconnect_all(void);
|
|||||||
bool att_disconnect_from_address(bt_addr_le_t *addr);
|
bool att_disconnect_from_address(bt_addr_le_t *addr);
|
||||||
bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter);
|
bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter);
|
||||||
bool att_exchange_mtu(uint16_t conn_handle);
|
bool att_exchange_mtu(uint16_t conn_handle);
|
||||||
bool att_handle_indicate(uint16_t handle, const uint8_t* value, int length);
|
|
||||||
bool att_handle_is_connected(uint16_t handle);
|
bool att_handle_is_connected(uint16_t handle);
|
||||||
bool att_handle_notify(uint16_t handle, const uint8_t* value, int length);
|
bool att_indicate(uint16_t handle, const uint8_t* value, int length);
|
||||||
bool att_is_connected(void);
|
bool att_is_connected(void);
|
||||||
|
bool att_notify(uint16_t handle, const uint8_t* value, int length);
|
||||||
int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]);
|
int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]);
|
||||||
int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]);
|
int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]);
|
||||||
uint16_t att_conn_handle(bt_addr_le_t *addr);
|
uint16_t att_conn_handle(bt_addr_le_t *addr);
|
||||||
|
@ -37,6 +37,7 @@ typedef int hci_result_t;
|
|||||||
#define HCI_WRITE_TIMEOUT (-3)
|
#define HCI_WRITE_TIMEOUT (-3)
|
||||||
#define HCI_READ_ERROR (-4)
|
#define HCI_READ_ERROR (-4)
|
||||||
#define HCI_WRITE_ERROR (-5)
|
#define HCI_WRITE_ERROR (-5)
|
||||||
|
#define HCI_ATT_ERROR (-6)
|
||||||
|
|
||||||
void hci_init(void);
|
void hci_init(void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user