mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 13:20:39 +00:00
gatt-service/bas-client: use request to send
This commit is contained in:
parent
b60c168034
commit
814908c5a4
@ -61,6 +61,8 @@
|
||||
|
||||
#define BATTERY_SERVICE_INVALID_INDEX 0xFF
|
||||
|
||||
static btstack_context_callback_registration_t battery_service_handle_can_send_now;
|
||||
|
||||
static btstack_linked_list_t clients;
|
||||
static uint16_t battery_service_cid_counter = 0;
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
@ -73,6 +75,12 @@ static uint16_t battery_service_get_next_cid(void){
|
||||
return battery_service_cid_counter;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t battery_service_client_request_send_gatt_query(battery_service_client_t * client){
|
||||
battery_service_handle_can_send_now.context = (void *)(uintptr_t)client->cid;
|
||||
return gatt_client_request_to_send_gatt_query(&battery_service_handle_can_send_now, client->con_handle);
|
||||
}
|
||||
|
||||
static battery_service_client_t * battery_service_create_client(hci_con_handle_t con_handle, uint16_t cid){
|
||||
battery_service_client_t * client = btstack_memory_battery_service_client_get();
|
||||
if (!client){
|
||||
@ -191,14 +199,23 @@ static bool battery_service_registered_notification(battery_service_client_t * c
|
||||
return status;
|
||||
}
|
||||
|
||||
static void battery_service_start_polling_if_needed(battery_service_client_t * client){
|
||||
if (client->poll_interval_ms > 0){
|
||||
client->need_poll_bitmap = client->poll_bitmap;
|
||||
battery_service_poll_timer_start(client);
|
||||
}
|
||||
static bool battery_service_is_polling_needed(battery_service_client_t * client){
|
||||
return (client->poll_bitmap > 0u) && (client->poll_interval_ms > 0u);
|
||||
}
|
||||
|
||||
static void battery_service_run_for_client(battery_service_client_t * client){
|
||||
static void battery_service_start_polling(battery_service_client_t * client){
|
||||
client->need_poll_bitmap = client->poll_bitmap;
|
||||
battery_service_poll_timer_start(client);
|
||||
}
|
||||
|
||||
static void battery_service_send_next_query(void * context){
|
||||
uint16_t cid = (uint16_t)(uintptr_t)context;
|
||||
battery_service_client_t * client = battery_service_get_client_for_cid(cid);
|
||||
|
||||
if (client == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t status;
|
||||
uint8_t i;
|
||||
gatt_client_characteristic_t characteristic;
|
||||
@ -207,10 +224,14 @@ static void battery_service_run_for_client(battery_service_client_t * client){
|
||||
case BATTERY_SERVICE_CLIENT_STATE_CONNECTED:
|
||||
for (i = 0; i < client->num_instances; i++){
|
||||
if ( ((client->need_poll_bitmap >> i) & 0x01) == 0x01 ){
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_VALUE_READ;
|
||||
// clear bit of polled service
|
||||
client->need_poll_bitmap &= ~(1u << i);
|
||||
client->polled_service_index = i;
|
||||
|
||||
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
printf("Poll value [%d]\n", i);
|
||||
#endif
|
||||
// poll value of characteristic
|
||||
characteristic.value_handle = client->services[i].value_handle;
|
||||
characteristic.properties = client->services[i].properties;
|
||||
@ -286,13 +307,16 @@ static void battery_service_run_for_client(battery_service_client_t * client){
|
||||
#endif
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_CONNECTED;
|
||||
battery_service_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||
battery_service_start_polling_if_needed(client);
|
||||
if (battery_service_is_polling_needed(client)){
|
||||
battery_service_start_polling(client);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void battery_service_poll_timer_timeout_handler(btstack_timer_source_t * timer){
|
||||
uint16_t battery_service_cid = (uint16_t)(uintptr_t) btstack_run_loop_get_timer_context(timer);
|
||||
|
||||
@ -300,15 +324,15 @@ static void battery_service_poll_timer_timeout_handler(btstack_timer_source_t *
|
||||
btstack_assert(client != NULL);
|
||||
|
||||
client->need_poll_bitmap = client->poll_bitmap;
|
||||
battery_service_poll_timer_start(client);
|
||||
battery_service_run_for_client(client);
|
||||
battery_service_client_request_send_gatt_query(client);
|
||||
}
|
||||
|
||||
static void battery_service_poll_timer_start(battery_service_client_t * client){
|
||||
btstack_run_loop_set_timer_handler(&client->poll_timer, battery_service_poll_timer_timeout_handler);
|
||||
btstack_run_loop_set_timer_context(&client->poll_timer, (void *)(uintptr_t)client->cid);
|
||||
|
||||
btstack_run_loop_set_timer(&client->poll_timer, client->poll_interval_ms);
|
||||
btstack_run_loop_set_timer(&client->poll_timer, client->poll_interval_ms);
|
||||
btstack_run_loop_remove_timer(&client->poll_timer);
|
||||
btstack_run_loop_add_timer(&client->poll_timer);
|
||||
}
|
||||
|
||||
@ -328,7 +352,7 @@ static void battery_service_client_validate_service(battery_service_client_t * c
|
||||
}
|
||||
|
||||
// @return true if client valid / run function should be called
|
||||
static bool battery_service_client_handle_query_complete(battery_service_client_t * client, uint8_t status){
|
||||
static bool battery_service_client_handle_query_complete_for_connection_setup(battery_service_client_t * client, uint8_t status){
|
||||
switch (client->state){
|
||||
case BATTERY_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT:
|
||||
if (status != ATT_ERROR_SUCCESS){
|
||||
@ -395,7 +419,10 @@ static bool battery_service_client_handle_query_complete(battery_service_client_
|
||||
case BATTERY_SERVICE_CLIENT_W4_CHARACTERISTIC_CONFIGURATION_RESULT:
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_CONNECTED;
|
||||
battery_service_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||
battery_service_start_polling_if_needed(client);
|
||||
if (battery_service_is_polling_needed(client)){
|
||||
battery_service_start_polling(client);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case BATTERY_SERVICE_CLIENT_STATE_W4_NOTIFICATION_REGISTERED:
|
||||
@ -406,33 +433,47 @@ static bool battery_service_client_handle_query_complete(battery_service_client_
|
||||
}
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
for (client->service_index = 0; client->service_index < client->num_instances; client->service_index++){
|
||||
bool need_polling = (client->poll_bitmap & (1 << client->service_index)) != 0;
|
||||
printf("read CCC 1 0x%02x, polling %d \n", client->services[client->service_index].ccc_handle, (int) need_polling);
|
||||
if ( (client->services[client->service_index].ccc_handle != 0) && !need_polling ) {
|
||||
client->state = BATTERY_SERVICE_CLIENT_W2_READ_CHARACTERISTIC_CONFIGURATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool need_polling = (client->poll_bitmap & (1 << client->service_index)) != 0;
|
||||
printf("read CCC 1 0x%02x, polling %d \n", client->services[client->service_index].ccc_handle, (int) need_polling);
|
||||
if ( (client->services[client->service_index].ccc_handle != 0) && !need_polling ) {
|
||||
client->state = BATTERY_SERVICE_CLIENT_W2_READ_CHARACTERISTIC_CONFIGURATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_CONNECTED;
|
||||
battery_service_emit_connection_established(client, ERROR_CODE_SUCCESS);
|
||||
battery_service_start_polling_if_needed(client);
|
||||
if (battery_service_is_polling_needed(client)){
|
||||
battery_service_start_polling(client);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case BATTERY_SERVICE_CLIENT_STATE_CONNECTED:
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool battery_service_client_handle_query_complete(battery_service_client_t * client, uint8_t status){
|
||||
switch (client->state){
|
||||
|
||||
case BATTERY_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_VALUE_READ:
|
||||
if (client->polled_service_index != BATTERY_SERVICE_INVALID_INDEX){
|
||||
if (status != ATT_ERROR_SUCCESS){
|
||||
battery_service_emit_battery_level(client, client->services[client->polled_service_index].value_handle, status, 0);
|
||||
}
|
||||
client->polled_service_index = BATTERY_SERVICE_INVALID_INDEX;
|
||||
}
|
||||
break;
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_CONNECTED;
|
||||
return (client->need_poll_bitmap != 0u);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
@ -443,7 +484,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
battery_service_client_t * client = NULL;
|
||||
gatt_client_service_t service;
|
||||
gatt_client_characteristic_t characteristic;
|
||||
bool call_run = true;
|
||||
bool send_next_gatt_query = false;
|
||||
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
case GATT_EVENT_SERVICE_QUERY_RESULT:
|
||||
@ -462,6 +503,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
} else {
|
||||
log_info("Found more then %d, Battery Service instances. Increase MAX_NUM_BATTERY_SERVICES to store all.", MAX_NUM_BATTERY_SERVICES);
|
||||
}
|
||||
// for sending next query w4 GATT_EVENT_QUERY_COMPLETE
|
||||
break;
|
||||
|
||||
case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
|
||||
@ -483,6 +525,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
characteristic.value_handle, characteristic.uuid16,
|
||||
client->service_index);
|
||||
#endif
|
||||
// for sending next query w4 GATT_EVENT_QUERY_COMPLETE
|
||||
break;
|
||||
|
||||
case GATT_EVENT_NOTIFICATION:
|
||||
@ -495,6 +538,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
gatt_event_notification_get_value_handle(packet),
|
||||
ATT_ERROR_SUCCESS,
|
||||
gatt_event_notification_get_value(packet)[0]);
|
||||
|
||||
break;
|
||||
|
||||
case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
|
||||
@ -514,6 +558,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
gatt_event_characteristic_value_query_result_get_value_handle(packet),
|
||||
ATT_ERROR_SUCCESS,
|
||||
gatt_event_characteristic_value_query_result_get_value(packet)[0]);
|
||||
// reset need_poll_bitmap in GATT_EVENT_QUERY_COMPLETE
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
@ -533,21 +578,37 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
characteristic_descriptor.uuid16);
|
||||
}
|
||||
break;
|
||||
// for sending next query w4 GATT_EVENT_QUERY_COMPLETE
|
||||
}
|
||||
#endif
|
||||
|
||||
case GATT_EVENT_QUERY_COMPLETE:
|
||||
client = battery_service_get_client_for_con_handle(gatt_event_query_complete_get_handle(packet));
|
||||
btstack_assert(client != NULL);
|
||||
call_run = battery_service_client_handle_query_complete(client, gatt_event_query_complete_get_att_status(packet));
|
||||
|
||||
// 1. handle service establishment/notification subscription query results (client->state < BATTERY_SERVICE_CLIENT_STATE_CONNECTED)
|
||||
if (client->state < BATTERY_SERVICE_CLIENT_STATE_CONNECTED){
|
||||
send_next_gatt_query = battery_service_client_handle_query_complete_for_connection_setup(client, gatt_event_query_complete_get_att_status(packet));
|
||||
break;
|
||||
}
|
||||
|
||||
// 2. handle battery value query result when devices is connected
|
||||
send_next_gatt_query = battery_service_client_handle_query_complete(client, gatt_event_query_complete_get_att_status(packet));
|
||||
if (!send_next_gatt_query){
|
||||
// if there are no further queries, and we're connected, trigger next polling read
|
||||
if (battery_service_is_polling_needed(client)){
|
||||
battery_service_poll_timer_start(client);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (call_run && (client != NULL)){
|
||||
battery_service_run_for_client(client);
|
||||
if (send_next_gatt_query){
|
||||
battery_service_client_request_send_gatt_query(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,8 +659,12 @@ uint8_t battery_service_client_connect(hci_con_handle_t con_handle, btstack_pack
|
||||
client->client_handler = packet_handler;
|
||||
client->poll_interval_ms = poll_interval_ms;
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE;
|
||||
battery_service_run_for_client(client);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
|
||||
uint8_t status = battery_service_client_request_send_gatt_query(client);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
client->state = BATTERY_SERVICE_CLIENT_STATE_IDLE;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t battery_service_client_disconnect(uint16_t battery_service_cid){
|
||||
@ -612,12 +677,13 @@ uint8_t battery_service_client_disconnect(uint16_t battery_service_cid){
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint8_t battery_service_client_read_battery_level(uint16_t battery_service_cid, uint8_t service_index){
|
||||
battery_service_client_t * client = battery_service_get_client_for_cid(battery_service_cid);
|
||||
if (client == NULL) {
|
||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||
}
|
||||
if (client->state != BATTERY_SERVICE_CLIENT_STATE_CONNECTED) {
|
||||
if (client->state < BATTERY_SERVICE_CLIENT_STATE_CONNECTED) {
|
||||
return GATT_CLIENT_IN_WRONG_STATE;
|
||||
}
|
||||
if (service_index >= client->num_instances) {
|
||||
@ -625,13 +691,18 @@ uint8_t battery_service_client_read_battery_level(uint16_t battery_service_cid,
|
||||
}
|
||||
|
||||
client->need_poll_bitmap |= (1u << service_index);
|
||||
battery_service_run_for_client(client);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
|
||||
uint8_t status = battery_service_client_request_send_gatt_query(client);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
client->need_poll_bitmap &= ~(1u << client->polled_service_index);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void battery_service_client_init(void){
|
||||
hci_event_callback_registration.callback = &handle_hci_event;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
battery_service_handle_can_send_now.callback = &battery_service_send_next_query;
|
||||
}
|
||||
|
||||
void battery_service_client_deinit(void){
|
||||
|
@ -83,6 +83,7 @@ typedef enum {
|
||||
BATTERY_SERVICE_CLIENT_STATE_W2_REGISTER_NOTIFICATION,
|
||||
BATTERY_SERVICE_CLIENT_STATE_W4_NOTIFICATION_REGISTERED,
|
||||
BATTERY_SERVICE_CLIENT_STATE_CONNECTED,
|
||||
BATTERY_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_VALUE_READ,
|
||||
|
||||
#ifdef ENABLE_TESTING_SUPPORT
|
||||
BATTERY_SERVICE_CLIENT_W2_READ_CHARACTERISTIC_CONFIGURATION,
|
||||
@ -142,7 +143,7 @@ void battery_service_client_init(void);
|
||||
* If notifications are not supported by remote Battery Service, the client will poll battery level
|
||||
* If poll_interval_ms is 0, polling is disabled, and only notifications will be received.
|
||||
* In either case, the battery level is received via GATTSERVICE_SUBEVENT_BATTERY_SERVICE_LEVEL event.
|
||||
* The battery level is reported as percentage, i.e. 100 = full and it is valid if the ATTT status is equal to ATT_ERROR_SUCCESS,
|
||||
* The battery level is reported as percentage, i.e. 100 = full and it is valid if the ATT status is equal to ATT_ERROR_SUCCESS,
|
||||
* see ATT errors (see bluetooth.h) for other values.
|
||||
*
|
||||
* For manual polling, see battery_service_client_read_battery_level below.
|
||||
|
Loading…
x
Reference in New Issue
Block a user