diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a63b6442..722181f05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,8 @@ btstack_uart: `btstack_uart_t` interface extends `btstack_uart_block_t`: btstack_uart_slip_wrapper: wrapper that implements SLIP functionality for existing `btstack_uart_block` drivers. hci_transport: add parity field and pass on to `btstack_uart_t` in h4 and h5 GATT Client: Battery Service Client -GATT Client: Device Information Service Client +GATT Client: Device Information Service Client +GATT Client: Scan Parameters Service Client ### Fixed diff --git a/README.md b/README.md index 34599b32e..4cbe069bf 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ BTstack is free for non-commercial use. However, for commercial use, +#include + + +#include "scan_parameters_service_client.h" + +#include "btstack_memory.h" +#include "ble/att_db.h" +#include "ble/core.h" +#include "ble/gatt_client.h" +#include "ble/sm.h" +#include "bluetooth_gatt.h" +#include "btstack_debug.h" +#include "btstack_event.h" +#include "btstack_run_loop.h" +#include "gap.h" + +static btstack_linked_list_t clients; +static uint16_t scan_parameters_service_cid_counter = 0; +static uint16_t scan_parameters_service_scan_window = 0; +static uint16_t scan_parameters_service_scan_interval = 0; + +static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); + +static uint16_t scan_parameters_service_get_next_cid(void){ + if (scan_parameters_service_cid_counter == 0xffff) { + scan_parameters_service_cid_counter = 1; + } else { + scan_parameters_service_cid_counter++; + } + return scan_parameters_service_cid_counter; +} + +static scan_parameters_service_client_t * scan_parameters_service_create_client(hci_con_handle_t con_handle, uint16_t cid){ + scan_parameters_service_client_t * client = btstack_memory_scan_parameters_service_client_get(); + if (!client){ + log_error("Not enough memory to create client"); + return NULL; + } + + client->cid = cid; + client->con_handle = con_handle; + client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_IDLE; + + client->start_handle = 0; + client->end_handle = 0; + + client->scan_interval_window_value_handle = 0; + client->scan_interval_window_value_update = false; + btstack_linked_list_add(&clients, (btstack_linked_item_t *) client); + return client; +} + +static void scan_parameters_service_finalize_client(scan_parameters_service_client_t * client){ + btstack_linked_list_remove(&clients, (btstack_linked_item_t *) client); + btstack_memory_scan_parameters_service_client_free(client); +} + +static scan_parameters_service_client_t * scan_parameters_service_get_client_for_con_handle(hci_con_handle_t con_handle){ + btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_init(&it, &clients); + while (btstack_linked_list_iterator_has_next(&it)){ + scan_parameters_service_client_t * client = (scan_parameters_service_client_t *)btstack_linked_list_iterator_next(&it); + if (client->con_handle != con_handle) continue; + return client; + } + return NULL; +} + +static scan_parameters_service_client_t * scan_parameters_service_get_client_for_cid(uint16_t scann_parameters_service_cid){ + btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_init(&it, &clients); + while (btstack_linked_list_iterator_has_next(&it)){ + scan_parameters_service_client_t * client = (scan_parameters_service_client_t *)btstack_linked_list_iterator_next(&it); + if (client->cid != scann_parameters_service_cid) continue; + return client; + } + return NULL; +} + +static void scan_parameters_service_emit_connection_established(scan_parameters_service_client_t * client, uint8_t status){ + uint8_t event[6]; + int pos = 0; + event[pos++] = HCI_EVENT_GATTSERVICE_META; + event[pos++] = sizeof(event) - 2; + event[pos++] = GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_CONNECTED; + little_endian_store_16(event, pos, client->cid); + pos += 2; + event[pos++] = status; + (*client->client_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event)); +} + + +static void scan_parameters_service_run_for_client(scan_parameters_service_client_t * client){ + uint8_t att_status; + gatt_client_service_t service; + + switch (client->state){ + case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE: + client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT; + att_status = gatt_client_discover_primary_services_by_uuid16(handle_gatt_client_event, client->con_handle, ORG_BLUETOOTH_SERVICE_SCAN_PARAMETERS); + // TODO handle status + UNUSED(att_status); + break; + + case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTIC: + client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT; + + service.start_group_handle = client->start_handle; + service.end_group_handle = client->end_handle; + att_status = gatt_client_discover_characteristics_for_service_by_uuid16( + handle_gatt_client_event, client->con_handle, &service, ORG_BLUETOOTH_CHARACTERISTIC_SCAN_INTERVAL_WINDOW); + // TODO handle status + UNUSED(att_status); + break; + + case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED: + if (client->scan_interval_window_value_update){ + uint8_t value[4]; + little_endian_store_16(value, 0, scan_parameters_service_scan_interval); + little_endian_store_16(value, 2, scan_parameters_service_scan_window); + + att_status = gatt_client_write_value_of_characteristic_without_response(client->con_handle, client->scan_interval_window_value_handle, 4, value); + client->scan_interval_window_value_update = false; + // TODO handle status + UNUSED(att_status); + } + break; + default: + break; + } +} + +static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + UNUSED(packet_type); + UNUSED(channel); + UNUSED(size); + + scan_parameters_service_client_t * client = NULL; + gatt_client_service_t service; + gatt_client_characteristic_t characteristic; + uint8_t att_status; + + switch(hci_event_packet_get_type(packet)){ + case GATT_EVENT_SERVICE_QUERY_RESULT: + client = scan_parameters_service_get_client_for_con_handle(gatt_event_service_query_result_get_handle(packet)); + btstack_assert(client != NULL); + + if (client->state != SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT) { + scan_parameters_service_emit_connection_established(client, GATT_CLIENT_IN_WRONG_STATE); + scan_parameters_service_finalize_client(client); + break; + } + + gatt_event_service_query_result_get_service(packet, &service); + client->start_handle = service.start_group_handle; + client->end_handle = service.end_group_handle; + break; + + case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: + client = scan_parameters_service_get_client_for_con_handle(gatt_event_characteristic_query_result_get_handle(packet)); + btstack_assert(client != NULL); + + // found scan_interval_window_value_handle, check att_status + gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic); + client->scan_interval_window_value_handle = characteristic.value_handle; + break; + + case GATT_EVENT_QUERY_COMPLETE: + client = scan_parameters_service_get_client_for_con_handle(gatt_event_query_complete_get_handle(packet)); + btstack_assert(client != NULL); + + att_status = gatt_event_query_complete_get_att_status(packet); + + switch (client->state){ + case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT: + if (att_status != ATT_ERROR_SUCCESS){ + scan_parameters_service_emit_connection_established(client, att_status); + scan_parameters_service_finalize_client(client); + break; + } + + if (client->start_handle != 0){ + scan_parameters_service_emit_connection_established(client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE); + scan_parameters_service_finalize_client(client); + break; + } + client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTIC; + break; + + case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT: + if (att_status != ATT_ERROR_SUCCESS){ + scan_parameters_service_emit_connection_established(client, att_status); + scan_parameters_service_finalize_client(client); + break; + } + + if (client->scan_interval_window_value_handle == 0){ + scan_parameters_service_emit_connection_established(client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE); + scan_parameters_service_finalize_client(client); + break; + } + client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED; + client->scan_interval_window_value_update = true; + break; + + default: + break; + } + break; + default: + break; + } + + if (client != NULL){ + scan_parameters_service_run_for_client(client); + } +} + +void scan_parameters_service_client_set(uint16_t scan_interval, uint16_t scan_window){ + scan_parameters_service_scan_interval = scan_interval; + scan_parameters_service_scan_window = scan_window; + + btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_init(&it, &clients); + while (btstack_linked_list_iterator_has_next(&it)){ + scan_parameters_service_client_t * client = (scan_parameters_service_client_t*) btstack_linked_list_iterator_next(&it); + client->scan_interval_window_value_update = true; + scan_parameters_service_run_for_client(client); + } +} + +uint8_t scan_parameters_service_client_connect(hci_con_handle_t con_handle, btstack_packet_handler_t packet_handler, uint16_t * scan_parameters_service_cid){ + btstack_assert(packet_handler != NULL); + + scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_con_handle(con_handle); + if (client != NULL){ + return ERROR_CODE_COMMAND_DISALLOWED; + } + + uint16_t cid = scan_parameters_service_get_next_cid(); + if (scan_parameters_service_cid != NULL) { + *scan_parameters_service_cid = cid; + } + + client = scan_parameters_service_create_client(con_handle, cid); + if (client == NULL) { + return BTSTACK_MEMORY_ALLOC_FAILED; + } + + client->client_handler = packet_handler; + client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE; + scan_parameters_service_run_for_client(client); + return ERROR_CODE_SUCCESS; +} + +uint8_t scan_parameters_service_client_disconnect(uint16_t scan_parameters_service_cid){ + scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_cid(scan_parameters_service_cid); + if (client == NULL){ + return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; + } + // finalize connections + scan_parameters_service_finalize_client(client); + return ERROR_CODE_SUCCESS; +} + +void scan_parameters_service_client_init(void){} + +void scan_parameters_service_client_deinit(void){} + diff --git a/src/ble/gatt-service/scan_parameters_service_client.h b/src/ble/gatt-service/scan_parameters_service_client.h new file mode 100644 index 000000000..fe3766262 --- /dev/null +++ b/src/ble/gatt-service/scan_parameters_service_client.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2021 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +#ifndef SCAN_PARAMAETERS_SERVICE_CLIENT_H +#define SCAN_PARAMAETERS_SERVICE_CLIENT_H + +#include +#include "btstack_defines.h" +#include "bluetooth.h" +#include "ble/gatt_client.h" +#include "btstack_linked_list.h" + +#if defined __cplusplus +extern "C" { +#endif + +typedef enum { + SCAN_PARAMETERS_SERVICE_CLIENT_STATE_IDLE, + SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE, + SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT, + SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTIC, + SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT, + SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED +} scan_parameters_service_client_state_t; + + +typedef struct { + btstack_linked_item_t item; + + hci_con_handle_t con_handle; + uint16_t cid; + scan_parameters_service_client_state_t state; + btstack_packet_handler_t client_handler; + + // service + uint16_t start_handle; + uint16_t end_handle; + + // characteristic + uint16_t scan_interval_window_value_handle; + bool scan_interval_window_value_update; +} scan_parameters_service_client_t; + +/* API_START */ + +/** + * @brief Initialize Scan Parameters Service. + */ +void scan_parameters_service_client_init(void); + +/** + * @brief Connect to Scan Parameters Service of remote device. + * + * The GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_CONNECTED event completes the request. + * Its status is set to ERROR_CODE_SUCCESS if remote service and SCAN_INTERVAL_WINDOW characteristic are found. + * Other status codes of this event: + * - GATT_CLIENT_IN_WRONG_STATE: client in wrong state + * - ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE: service or characteristic not found + * - ATT errors, see bluetooth.h + * + * @param con_handle + * @param packet_handler + * @param scan_parameters_cid + * @return status ERROR_CODE_SUCCESS on success, otherwise ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER if client with con_handle not found + */ +uint8_t scan_parameters_service_client_connect(hci_con_handle_t con_handle, btstack_packet_handler_t packet_handler, uint16_t * scan_parameters_cid); + +/** + * @brief Set Scan Parameters Service. It will update all connected devices. + * @param scan_interval + * @param scan_window + */ +void scan_parameters_service_client_set(uint16_t scan_interval, uint16_t scan_window); + +/** + * @brief Disconnect from Scan Parameters Service. + * @param scan_parameters_cid + * @return status ERROR_CODE_SUCCESS on success, otherwise ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER if client with con_handle is not found + */ +uint8_t scan_parameters_service_client_disconnect(uint16_t scan_parameters_cid); + + +/** + * @brief De-initialize Scan Parameters Service. + */ +void scan_parameters_service_client_deinit(void); + +/* API_END */ + +#if defined __cplusplus +} +#endif + +#endif diff --git a/src/btstack.h b/src/btstack.h index c8066aacc..494d0a62e 100644 --- a/src/btstack.h +++ b/src/btstack.h @@ -89,6 +89,7 @@ #include "ble/gatt-service/device_information_service_server.h" #include "ble/gatt-service/heart_rate_service_server.h" #include "ble/gatt-service/hids_device.h" +#include "ble/gatt-service/scan_parameters_service_client.h" #ifdef ENABLE_MESH #include "ble/gatt-service/mesh_provisioning_service_server.h" #include "ble/gatt-service/mesh_proxy_service_server.h" diff --git a/src/btstack_defines.h b/src/btstack_defines.h index e62c9110c..dacf3afdb 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -3183,6 +3183,14 @@ typedef uint8_t sm_key_t[16]; */ #define GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_PNP_ID 0x0F +/** + * @format 1H1 + * @param subevent_code + * @param con_handle + * @param att_status + */ +#define GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_CONNECTED 0x10 + // MAP Meta Event Group diff --git a/src/btstack_event.h b/src/btstack_event.h index 373377469..6a75b85bc 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -9465,6 +9465,25 @@ static inline uint16_t gattservice_subevent_device_information_pnp_id_get_produc return little_endian_read_16(event, 11); } +/** + * @brief Get field con_handle from event GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_CONNECTED + * @param event packet + * @return con_handle + * @note: btstack_type H + */ +static inline hci_con_handle_t gattservice_subevent_scan_parameters_service_connected_get_con_handle(const uint8_t * event){ + return little_endian_read_16(event, 3); +} +/** + * @brief Get field att_status from event GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_CONNECTED + * @param event packet + * @return att_status + * @note: btstack_type 1 + */ +static inline uint8_t gattservice_subevent_scan_parameters_service_connected_get_att_status(const uint8_t * event){ + return event[5]; +} + /** * @brief Get field map_cid from event MAP_SUBEVENT_CONNECTION_OPENED * @param event packet diff --git a/src/btstack_memory.c b/src/btstack_memory.c index 20a030fbd..40d6e185e 100644 --- a/src/btstack_memory.c +++ b/src/btstack_memory.c @@ -55,11 +55,6 @@ #include -#ifdef ENABLE_MALLOC_TEST -extern "C" void * test_malloc(size_t size); -#define malloc test_malloc -#endif - #ifdef HAVE_MALLOC typedef struct btstack_memory_buffer { struct btstack_memory_buffer * next; @@ -1099,6 +1094,63 @@ void btstack_memory_battery_service_client_free(battery_service_client_t *batter #endif +// MARK: scan_parameters_service_client_t +#if !defined(HAVE_MALLOC) && !defined(MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS) + #if defined(MAX_NO_SCAN_PARAMETERS_SERVICE_CLIENTS) + #error "Deprecated MAX_NO_SCAN_PARAMETERS_SERVICE_CLIENTS defined instead of MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS. Please update your btstack_config.h to use MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS." + #else + #define MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS 0 + #endif +#endif + +#ifdef MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS +#if MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS > 0 +static scan_parameters_service_client_t scan_parameters_service_client_storage[MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS]; +static btstack_memory_pool_t scan_parameters_service_client_pool; +scan_parameters_service_client_t * btstack_memory_scan_parameters_service_client_get(void){ + void * buffer = btstack_memory_pool_get(&scan_parameters_service_client_pool); + if (buffer){ + memset(buffer, 0, sizeof(scan_parameters_service_client_t)); + } + return (scan_parameters_service_client_t *) buffer; +} +void btstack_memory_scan_parameters_service_client_free(scan_parameters_service_client_t *scan_parameters_service_client){ + btstack_memory_pool_free(&scan_parameters_service_client_pool, scan_parameters_service_client); +} +#else +scan_parameters_service_client_t * btstack_memory_scan_parameters_service_client_get(void){ + return NULL; +} +void btstack_memory_scan_parameters_service_client_free(scan_parameters_service_client_t *scan_parameters_service_client){ + UNUSED(scan_parameters_service_client); +}; +#endif +#elif defined(HAVE_MALLOC) + +typedef struct { + btstack_memory_buffer_t tracking; + scan_parameters_service_client_t data; +} btstack_memory_scan_parameters_service_client_t; + +scan_parameters_service_client_t * btstack_memory_scan_parameters_service_client_get(void){ + btstack_memory_scan_parameters_service_client_t * buffer = (btstack_memory_scan_parameters_service_client_t *) malloc(sizeof(btstack_memory_scan_parameters_service_client_t)); + if (buffer){ + memset(buffer, 0, sizeof(btstack_memory_scan_parameters_service_client_t)); + btstack_memory_tracking_add(&buffer->tracking); + return &buffer->data; + } else { + return NULL; + } +} +void btstack_memory_scan_parameters_service_client_free(scan_parameters_service_client_t *scan_parameters_service_client){ + // reconstruct buffer start + btstack_memory_buffer_t * buffer = &((btstack_memory_buffer_t *) scan_parameters_service_client)[-1]; + btstack_memory_tracking_remove(buffer); + free(buffer); +} +#endif + + // MARK: gatt_client_t #if !defined(HAVE_MALLOC) && !defined(MAX_NR_GATT_CLIENTS) #if defined(MAX_NO_GATT_CLIENTS) @@ -1735,6 +1787,9 @@ void btstack_memory_init(void){ #if MAX_NR_BATTERY_SERVICE_CLIENTS > 0 btstack_memory_pool_create(&battery_service_client_pool, battery_service_client_storage, MAX_NR_BATTERY_SERVICE_CLIENTS, sizeof(battery_service_client_t)); #endif +#if MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS > 0 + btstack_memory_pool_create(&scan_parameters_service_client_pool, scan_parameters_service_client_storage, MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS, sizeof(scan_parameters_service_client_t)); +#endif #if MAX_NR_GATT_CLIENTS > 0 btstack_memory_pool_create(&gatt_client_pool, gatt_client_storage, MAX_NR_GATT_CLIENTS, sizeof(gatt_client_t)); #endif diff --git a/src/btstack_memory.h b/src/btstack_memory.h index 7ced45e4b..85575e837 100644 --- a/src/btstack_memory.h +++ b/src/btstack_memory.h @@ -74,6 +74,7 @@ extern "C" { #include "ble/gatt_client.h" #include "ble/gatt-service/battery_service_client.h" #include "ble/sm.h" +#include "ble/gatt-service/scan_parameters_service_client.h" #endif #ifdef ENABLE_MESH @@ -156,9 +157,11 @@ void btstack_memory_avrcp_browsing_connection_free(avrcp_browsing_connection_t #endif #ifdef ENABLE_BLE -// battery_service_client, gatt_client, sm_lookup_entry, whitelist_entry +// battery_service_client, scan_parameters_service_client, gatt_client, sm_lookup_entry, whitelist_entry battery_service_client_t * btstack_memory_battery_service_client_get(void); void btstack_memory_battery_service_client_free(battery_service_client_t *battery_service_client); +scan_parameters_service_client_t * btstack_memory_scan_parameters_service_client_get(void); +void btstack_memory_scan_parameters_service_client_free(scan_parameters_service_client_t *scan_parameters_service_client); gatt_client_t * btstack_memory_gatt_client_get(void); void btstack_memory_gatt_client_free(gatt_client_t *gatt_client); sm_lookup_entry_t * btstack_memory_sm_lookup_entry_get(void); diff --git a/test/btstack_memory/btstack_memory_test.c b/test/btstack_memory/btstack_memory_test.c index 9ee99090f..a856c9722 100644 --- a/test/btstack_memory/btstack_memory_test.c +++ b/test/btstack_memory/btstack_memory_test.c @@ -802,6 +802,48 @@ TEST(btstack_memory, battery_service_client_NotEnoughBuffers){ +TEST(btstack_memory, scan_parameters_service_client_GetAndFree){ + scan_parameters_service_client_t * context; +#ifdef HAVE_MALLOC + context = btstack_memory_scan_parameters_service_client_get(); + CHECK(context != NULL); + btstack_memory_scan_parameters_service_client_free(context); +#else +#ifdef MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS + // single + context = btstack_memory_scan_parameters_service_client_get(); + CHECK(context != NULL); + btstack_memory_scan_parameters_service_client_free(context); +#else + // none + context = btstack_memory_scan_parameters_service_client_get(); + CHECK(context == NULL); + btstack_memory_scan_parameters_service_client_free(context); +#endif +#endif +} + +TEST(btstack_memory, scan_parameters_service_client_NotEnoughBuffers){ + scan_parameters_service_client_t * context; +#ifdef HAVE_MALLOC + simulate_no_memory = 1; +#else +#ifdef MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS + int i; + // alloc all static buffers + for (i = 0; i < MAX_NR_SCAN_PARAMETERS_SERVICE_CLIENTS; i++){ + context = btstack_memory_scan_parameters_service_client_get(); + CHECK(context != NULL); + } +#endif +#endif + // get one more + context = btstack_memory_scan_parameters_service_client_get(); + CHECK(context == NULL); +} + + + TEST(btstack_memory, gatt_client_GetAndFree){ gatt_client_t * context; #ifdef HAVE_MALLOC diff --git a/tool/btstack_memory_generator.py b/tool/btstack_memory_generator.py index 30f841285..8b694bf0d 100755 --- a/tool/btstack_memory_generator.py +++ b/tool/btstack_memory_generator.py @@ -82,6 +82,7 @@ extern "C" { #include "ble/gatt_client.h" #include "ble/gatt-service/battery_service_client.h" #include "ble/sm.h" +#include "ble/gatt-service/scan_parameters_service_client.h" #endif #ifdef ENABLE_MESH @@ -298,7 +299,7 @@ list_of_classic_structs = [ ["avrcp_browsing_connection"], ] list_of_le_structs = [ - ["battery_service_client", "gatt_client", "sm_lookup_entry", "whitelist_entry"], + ["battery_service_client", "scan_parameters_service_client", "gatt_client", "sm_lookup_entry", "whitelist_entry"], ] list_of_mesh_structs = [ ['mesh_network_pdu', 'mesh_segmented_pdu', 'mesh_upper_transport_pdu', 'mesh_network_key', 'mesh_transport_key', 'mesh_virtual_address', 'mesh_subnet']