mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-23 19:20:51 +00:00
start timer on handle value indication, assert only on indication is active, notify client about handle value indication completion, extend ble_peripheral
This commit is contained in:
parent
9e4b002b3d
commit
8a3fac4ff5
14
ble/att.h
14
ble/att.h
@ -73,8 +73,8 @@ extern "C" {
|
||||
#define ATT_EXECUTE_WRITE_RESPONSE 0x19
|
||||
|
||||
#define ATT_HANDLE_VALUE_NOTIFICATION 0x1b
|
||||
#define ATT_HANDLE_VALUE_CONFIRMATION 0x1c
|
||||
#define ATT_HANDLE_VALUE_INDICATION 0x1d
|
||||
#define ATT_HANDLE_VALUE_CONFIRMATION 0x1e
|
||||
|
||||
|
||||
#define ATT_WRITE_COMMAND 0x52
|
||||
@ -120,6 +120,14 @@ extern "C" {
|
||||
#define ATT_PROPERTY_AUTHORIZATION_REQUIRED 0x800
|
||||
// Encryption key size stored in upper 4 bits, 0 == no encryption, encryption key size - 1 otherwise
|
||||
|
||||
// ATT Transaxtion Timeout of 30 seconds for Command/Response or Incidationc/Confirmation
|
||||
#define ATT_TRANSACTION_TIMEOUT_MS 30000
|
||||
|
||||
#define ATT_TRANSACTION_MODE_NONE 0x0
|
||||
#define ATT_TRANSACTION_MODE_ACTIVE 0x1
|
||||
#define ATT_TRANSACTION_MODE_EXECUTE 0x2
|
||||
#define ATT_TRANSACTION_MODE_CANCEL 0x3
|
||||
|
||||
// MARK: GATT UUIDs
|
||||
#define GATT_PRIMARY_SERVICE_UUID 0x2800
|
||||
#define GATT_SECONDARY_SERVICE_UUID 0x2801
|
||||
@ -129,10 +137,6 @@ extern "C" {
|
||||
#define GAP_SERVICE_UUID 0x1800
|
||||
#define GAP_DEVICE_NAME_UUID 0x2a00
|
||||
|
||||
#define ATT_TRANSACTION_MODE_NONE 0x0
|
||||
#define ATT_TRANSACTION_MODE_ACTIVE 0x1
|
||||
#define ATT_TRANSACTION_MODE_EXECUTE 0x2
|
||||
#define ATT_TRANSACTION_MODE_CANCEL 0x3
|
||||
|
||||
typedef struct att_connection {
|
||||
uint16_t mtu;
|
||||
|
@ -81,8 +81,31 @@ static uint8_t att_request_buffer[28];
|
||||
static int att_ir_central_device_db_index = -1;
|
||||
static int att_ir_lookup_active = 0;
|
||||
|
||||
static int att_handle_value_indication_handle = 0;
|
||||
static timer_source_t att_handle_value_indication_timer;
|
||||
|
||||
static btstack_packet_handler_t att_client_packet_handler = NULL;
|
||||
|
||||
|
||||
static int att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){
|
||||
uint8_t event[7];
|
||||
int pos = 0;
|
||||
event[pos++] = ATT_HANDLE_VALUE_INDICATION_COMPLETE;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = status;
|
||||
bt_store_16(event, pos, client_handle);
|
||||
pos += 2;
|
||||
bt_store_16(event, pos, attribute_handle);
|
||||
pos += 2;
|
||||
(*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
|
||||
}
|
||||
|
||||
static void att_handle_value_indication_timeout(timer_source_t *ts){
|
||||
uint16_t att_handle = att_handle_value_indication_handle;
|
||||
att_handle_value_indication_handle = 0;
|
||||
att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_request_handle, att_handle);
|
||||
}
|
||||
|
||||
static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
switch (packet_type) {
|
||||
@ -255,6 +278,15 @@ static void att_run(void){
|
||||
static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
|
||||
if (packet_type != ATT_DATA_PACKET) return;
|
||||
|
||||
// handle value indication confirms
|
||||
if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){
|
||||
run_loop_remove_timer(&att_handle_value_indication_timer);
|
||||
uint16_t att_handle = att_handle_value_indication_handle;
|
||||
att_handle_value_indication_handle = 0;
|
||||
att_handle_value_indication_notify_client(0, att_request_handle, att_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// check size
|
||||
if (size > sizeof(att_request_buffer)) return;
|
||||
|
||||
@ -292,14 +324,24 @@ int att_server_can_send(){
|
||||
return hci_can_send_packet_now(HCI_ACL_DATA_PACKET);
|
||||
}
|
||||
|
||||
void att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len){
|
||||
int att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len){
|
||||
uint8_t packet_buffer[att_connection.mtu];
|
||||
uint16_t size = att_prepare_handle_value_notification(&att_connection, handle, value, value_len, packet_buffer);
|
||||
l2cap_send_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, packet_buffer, size);
|
||||
return l2cap_send_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, packet_buffer, size);
|
||||
}
|
||||
|
||||
void att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
|
||||
int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
|
||||
if (att_handle_value_indication_handle) return ATT_HANDLE_VALUE_INDICATION_IN_PORGRESS;
|
||||
if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) return BTSTACK_ACL_BUFFERS_FULL;
|
||||
|
||||
// track indication
|
||||
att_handle_value_indication_handle = handle;
|
||||
run_loop_set_timer_handler(&att_handle_value_indication_timer, att_handle_value_indication_timeout);
|
||||
run_loop_set_timer(&att_handle_value_indication_timer, ATT_TRANSACTION_TIMEOUT_MS);
|
||||
run_loop_add_timer(&att_handle_value_indication_timer);
|
||||
|
||||
uint8_t packet_buffer[att_connection.mtu];
|
||||
uint16_t size = att_prepare_handle_value_indication(&att_connection, handle, value, value_len, packet_buffer);
|
||||
l2cap_send_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, packet_buffer, size);
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,13 +65,15 @@ int att_server_can_send();
|
||||
|
||||
/*
|
||||
* @brief notify client about attribute value change
|
||||
* @ereturns 0 if ok, error otherwise
|
||||
*/
|
||||
void att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len);
|
||||
int att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len);
|
||||
|
||||
/*
|
||||
* @brief indicate value change to client. client is supposed to reply with an indication_response
|
||||
* @ereturns 0 if ok, error otherwise
|
||||
*/
|
||||
void att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len);
|
||||
int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
@ -83,11 +83,27 @@ static void heartbeat_handler(struct timer *ts){
|
||||
}
|
||||
|
||||
static void app_run(){
|
||||
if (!client_configuration || !update_client) return;
|
||||
if (!update_client) return;
|
||||
if (!att_server_can_send()) return;
|
||||
printf("Notify value %u\n", counter);
|
||||
|
||||
int result = -1;
|
||||
switch (client_configuration){
|
||||
case 0x01:
|
||||
printf("Notify value %u\n", counter);
|
||||
result = att_server_notify(0x0f, &counter, 1);
|
||||
break;
|
||||
case 0x02:
|
||||
printf("Indicate value %u\n", counter);
|
||||
result = att_server_indicate(0x0f, &counter, 1);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (result){
|
||||
printf("Error 0x%02x\n", result);
|
||||
return;
|
||||
}
|
||||
update_client = 0;
|
||||
att_server_notify(0x0f, &counter, 1);
|
||||
}
|
||||
|
||||
// write requests
|
||||
@ -177,6 +193,10 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
|
||||
sm_authorization_grant(event->addr_type, event->address);
|
||||
break;
|
||||
}
|
||||
case ATT_HANDLE_VALUE_INDICATION_COMPLETE:
|
||||
printf("ATT_HANDLE_VALUE_INDICATION_COMPLETE status %u\n", packet[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -228,6 +228,9 @@ extern "C" {
|
||||
#define GATT_CHARACTERISTIC_QUERY_RESULT 0xA4
|
||||
#define GATT_CHARACTERISTIC_QUERY_COMPLETE 0xA5
|
||||
|
||||
// data: event(8), len(8), status (8), hci_handle (16), attribute_handle (16)
|
||||
#define ATT_HANDLE_VALUE_INDICATION_COMPLETE 0xAF
|
||||
|
||||
// data: event(8), address_type(8), address (48), [number(32)]
|
||||
#define SM_JUST_WORKS_REQUEST 0xb0
|
||||
#define SM_JUST_WORKS_CANCEL 0xb1
|
||||
@ -241,6 +244,8 @@ extern "C" {
|
||||
#define SM_AUTHORIZATION_REQUEST 0xb9
|
||||
#define SM_AUTHORIZATION_RESULT 0xba
|
||||
|
||||
// ATT
|
||||
|
||||
// last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors
|
||||
|
||||
#define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED 0x50
|
||||
@ -278,6 +283,9 @@ extern "C" {
|
||||
#define SDP_HANDLE_ALREADY_REGISTERED 0x80
|
||||
#define SDP_QUERY_INCOMPLETE 0x81
|
||||
|
||||
#define ATT_HANDLE_VALUE_INDICATION_IN_PORGRESS 0x90
|
||||
#define ATT_HANDLE_VALUE_INDICATION_TIMEOUT 0x91
|
||||
|
||||
/**
|
||||
* Default INQ Mode
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user