From 9293bfa465772fe235b803158dc699ffd991663d Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 15 Nov 2015 20:56:59 +0100 Subject: [PATCH] rework SDP Service Record management. Service Records can be stored in ROM, daemon creates records on the heap --- example/embedded/spp_and_le_counter.c | 13 +- example/embedded/spp_counter.c | 13 +- example/embedded/spp_flowcontrol.c | 9 +- platform/daemon/src/daemon.c | 57 +++++-- port/ez430-rf2560/example/ant-test.c | 7 +- port/ez430-rf2560/example/spp_accel.c | 7 +- .../example/ant-test.c | 7 +- .../example/spp_accel.c | 7 +- src/classic/sdp.c | 161 +++++------------- src/classic/sdp.h | 55 +++--- src/hci_cmds.h | 1 + test/gatt_client/mock.c | 12 +- test/pts/bnep_test.c | 9 +- test/pts/classic_test.c | 4 +- test/pts/hfp_ag_test.c | 5 +- test/pts/hfp_hf_test.c | 4 +- test/pts/hsp_ag_test.c | 8 +- test/pts/hsp_hs_test.c | 7 +- 18 files changed, 157 insertions(+), 229 deletions(-) diff --git a/example/embedded/spp_and_le_counter.c b/example/embedded/spp_and_le_counter.c index 03ee5b1bf..95dcd5275 100644 --- a/example/embedded/spp_and_le_counter.c +++ b/example/embedded/spp_and_le_counter.c @@ -261,20 +261,9 @@ int btstack_main(void) // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); -/* LISTING_PAUSE */ -#ifdef EMBEDDED -/* LISTING_RESUME */ - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, RFCOMM_SERVER_CHANNEL, "SPP Counter"); - printf("SDP service buffer size: %u\n", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); -/* LISTING_PAUSE */ -#else sdp_create_spp_service( (uint8_t*)spp_service_buffer, RFCOMM_SERVER_CHANNEL, "SPP Counter"); printf("SDP service record size: %u\n", de_get_len((uint8_t*)spp_service_buffer)); - sdp_register_service_internal((uint8_t*)spp_service_buffer); -#endif -/* LISTING_RESUME */ + sdp_register_service((uint8_t*)spp_service_buffer); hci_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO); diff --git a/example/embedded/spp_counter.c b/example/embedded/spp_counter.c index 9510ab089..3db802c94 100644 --- a/example/embedded/spp_counter.c +++ b/example/embedded/spp_counter.c @@ -100,20 +100,9 @@ static void spp_service_setup(void){ // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); -/* LISTING_PAUSE */ -#ifdef EMBEDDED -/* LISTING_RESUME */ - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, RFCOMM_SERVER_CHANNEL, "SPP Counter"); - printf("SDP service buffer size: %u\n", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); -/* LISTING_PAUSE */ -#else sdp_create_spp_service( (uint8_t*) spp_service_buffer, RFCOMM_SERVER_CHANNEL, "SPP Counter"); printf("SDP service record size: %u\n", de_get_len((uint8_t*) spp_service_buffer)); - sdp_register_service_internal((uint8_t*)spp_service_buffer); -#endif -/* LISTING_RESUME */ + sdp_register_service((uint8_t*)spp_service_buffer); } /* LISTING_END */ diff --git a/example/embedded/spp_flowcontrol.c b/example/embedded/spp_flowcontrol.c index 07ee4c9a4..7b69576bb 100644 --- a/example/embedded/spp_flowcontrol.c +++ b/example/embedded/spp_flowcontrol.c @@ -88,15 +88,14 @@ static void spp_service_setup(void){ rfcomm_init(); rfcomm_register_packet_handler(packet_handler); // reserved channel, mtu limited by l2cap, 1 credit - rfcomm_register_service_with_initial_credits_internal(NULL, rfcomm_channel_nr, 0xffff, 1); + rfcomm_register_service_with_initial_credits(rfcomm_channel_nr, 0xffff, 1); // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Counter"); - printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); + sdp_create_spp_service( (uint8_t*) &spp_service_buffer, 1, "SPP Counter"); + printf("SDP service buffer size: %u\n\r", (uint16_t) de_get_len((uint8_t*) sdp_create_spp_service)); + sdp_register_service(spp_service_buffer); } /* LISTING_END */ diff --git a/platform/daemon/src/daemon.c b/platform/daemon/src/daemon.c index 75d4314a4..88cda53ab 100644 --- a/platform/daemon/src/daemon.c +++ b/platform/daemon/src/daemon.c @@ -498,7 +498,7 @@ static void daemon_sdp_close_connection(client_state_t * daemon_client){ linked_list_iterator_init(&it, list); while (linked_list_iterator_has_next(&it)){ linked_list_uint32_t * item = (linked_list_uint32_t*) linked_list_iterator_next(&it); - sdp_unregister_service_internal(&daemon_client->connection, item->value); + sdp_unregister_service(item->value); linked_list_remove(list, (linked_item_t *) item); free(item); } @@ -521,6 +521,45 @@ static connection_t * connection_for_l2cap_cid(uint16_t cid){ return NULL; } +static const uint8_t removeServiceRecordHandleAttributeIDList[] = { 0x36, 0x00, 0x05, 0x0A, 0x00, 0x01, 0xFF, 0xFF }; + +// register a service record +// pre: AttributeIDs are in ascending order +// pre: ServiceRecordHandle is first attribute and is not already registered in database +// @returns status +static uint32_t daemon_sdp_create_and_register_service(uint8_t * record){ + + // create new handle + uint32_t record_handle = sdp_create_service_record_handle(); + + // calculate size of new service record: DES (2 byte len) + // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes + uint16_t recordSize = 3 + (3 + 5) + de_get_data_size(record); + + // alloc memory for new service record + uint8_t * newRecord = malloc(recordSize); + if (!newRecord) return 0; + + // create DES for new record + de_create_sequence(newRecord); + + // set service record handle + de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0); + de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle); + + // add other attributes + sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord); + + uint8_t status = sdp_register_service(newRecord); + + if (status) { + free(newRecord); + return 0; + } + + return record_handle; +} + static connection_t * connection_for_rfcomm_cid(uint16_t cid){ linked_list_iterator_t cl; linked_list_iterator_init(&cl, &clients); @@ -637,7 +676,6 @@ static void send_l2cap_connection_open_failed(connection_t * connection, bd_addr } static void l2cap_emit_service_registered(void *connection, uint8_t status, uint16_t psm){ - log_info("L2CAP_EVENT_SERVICE_REGISTERED status 0x%x psm 0x%x", status, psm); uint8_t event[5]; event[0] = L2CAP_EVENT_SERVICE_REGISTERED; event[1] = sizeof(event) - 2; @@ -648,7 +686,6 @@ static void l2cap_emit_service_registered(void *connection, uint8_t status, uint } static void rfcomm_emit_service_registered(void *connection, uint8_t status, uint8_t channel){ - log_info("RFCOMM_EVENT_SERVICE_REGISTERED status 0x%x channel #%u", status, channel); uint8_t event[4]; event[0] = RFCOMM_EVENT_SERVICE_REGISTERED; event[1] = sizeof(event) - 2; @@ -675,10 +712,8 @@ static void send_rfcomm_create_channel_failed(void * connection, bd_addr_t addr, socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event)); } - // data: event(8), len(8), status(8), service_record_handle(32) static void sdp_emit_service_registered(void *connection, uint32_t handle, uint8_t status) { - if (!app_packet_handler) return; uint8_t event[7]; event[0] = SDP_SERVICE_REGISTERED; event[1] = sizeof(event) - 2; @@ -781,14 +816,13 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui uint32_t service_record_handle; client_state_t *client; uint8_t status; - + uint8_t * data; #if defined(HAVE_MALLOC) && defined(HAVE_BLE) uint8_t uuid128[16]; le_service_t service; le_characteristic_t characteristic; le_characteristic_descriptor_t descriptor; uint16_t data_length; - uint8_t * data; linked_list_gatt_client_helper_t * gatt_helper; #endif @@ -985,10 +1019,9 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); break; } - case SDP_REGISTER_SERVICE_RECORD: log_info("SDP_REGISTER_SERVICE_RECORD size %u\n", size); - service_record_handle = sdp_register_service_internal(&packet[3]); + service_record_handle = daemon_sdp_create_and_register_service(&packet[3]); if (service_record_handle){ daemon_add_client_sdp_service_record_handle(connection, service_record_handle); sdp_emit_service_registered(connection, service_record_handle, 0); @@ -999,8 +1032,12 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui case SDP_UNREGISTER_SERVICE_RECORD: service_record_handle = READ_BT_32(packet, 3); log_info("SDP_UNREGISTER_SERVICE_RECORD handle 0x%x ", service_record_handle); - sdp_unregister_service_internal(service_record_handle); + data = sdp_get_record_for_handle(service_record_handle); + sdp_unregister_service(service_record_handle); daemon_remove_client_sdp_service_record_handle(connection, service_record_handle); + if (data){ + free(data); + } break; case SDP_CLIENT_QUERY_RFCOMM_SERVICES: bt_flip_addr(addr, &packet[3]); diff --git a/port/ez430-rf2560/example/ant-test.c b/port/ez430-rf2560/example/ant-test.c index 70b155cd8..a0b5b2d7e 100644 --- a/port/ez430-rf2560/example/ant-test.c +++ b/port/ez430-rf2560/example/ant-test.c @@ -227,10 +227,9 @@ int btstack_main(int argc, const char * argv[]){ // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Counter"); - printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); + sdp_create_spp_service( (uint8_t*) spp_service_buffer, 1, "SPP Counter"); + printf("SDP service buffer size: %u\n\r", (uint16_t) (de_get_len((uint8_t*) spp_service_buffer))); + sdp_register_service(service_record_item); // set one-shot timer timer_source_t heartbeat; diff --git a/port/ez430-rf2560/example/spp_accel.c b/port/ez430-rf2560/example/spp_accel.c index d44ce3355..2cfe36c2a 100644 --- a/port/ez430-rf2560/example/spp_accel.c +++ b/port/ez430-rf2560/example/spp_accel.c @@ -217,10 +217,9 @@ int btstack_main(int argc, const char * argv[]){ // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Accel"); - printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); + sdp_create_spp_service((uint8_t*) spp_service_buffer, 1, "SPP Accel"); + printf("SDP service buffer size: %u\n\r", (uint16_t) de_get_len((uint8_t*) spp_service_buffer)); + sdp_register_service((uint8_t*) spp_service_buffer); // ready - enable irq used in h4 task __enable_interrupt(); diff --git a/port/msp-exp430f5438-cc2564b/example/ant-test.c b/port/msp-exp430f5438-cc2564b/example/ant-test.c index d88678488..4cc39c1fa 100644 --- a/port/msp-exp430f5438-cc2564b/example/ant-test.c +++ b/port/msp-exp430f5438-cc2564b/example/ant-test.c @@ -227,10 +227,9 @@ int btstack_main(int argc, const char * argv[]){ // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Counter"); - printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); + sdp_create_spp_service( (uint8_t*) spp_service_buffer, 1, "SPP Counter"); + printf("SDP service buffer size: %u\n\r", (uint16_t) de_get_len((uint8_t*) spp_service_buffer)); + sdp_register_service(spp_service_buffer); // set one-shot timer timer_source_t heartbeat; diff --git a/port/msp-exp430f5438-cc2564b/example/spp_accel.c b/port/msp-exp430f5438-cc2564b/example/spp_accel.c index 6739faa81..7802621ab 100644 --- a/port/msp-exp430f5438-cc2564b/example/spp_accel.c +++ b/port/msp-exp430f5438-cc2564b/example/spp_accel.c @@ -217,10 +217,9 @@ int btstack_main(int argc, const char * argv[]){ // init SDP, create record for SPP and register with SDP sdp_init(); memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); - service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer; - sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "SPP Accel"); - printf("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); + sdp_create_spp_service( (uint8_t*) spp_service_buffer, 1, "SPP Accel"); + printf("SDP service buffer size: %u\n\r", (uint16_t) de_get_len((uint8_t*) spp_service_buffer)); + sdp_register_service(spp_service_buffer); // ready - enable irq used in h4 task __enable_interrupt(); diff --git a/src/classic/sdp.c b/src/classic/sdp.c index b3eae927f..03a8f8dab 100644 --- a/src/classic/sdp.c +++ b/src/classic/sdp.c @@ -39,17 +39,16 @@ * Implementation of the Service Discovery Protocol Server */ -#include "classic/sdp.h" - #include #include -#include "classic/sdp_util.h" - +#include "btstack_memory.h" +#include "debug.h" #include "hci_dump.h" #include "l2cap.h" -#include "debug.h" +#include "classic/sdp.h" +#include "classic/sdp_util.h" // max reserved ServiceRecordHandle #define maxReservedServiceRecordHandle 0xffff @@ -58,7 +57,6 @@ #define SDP_RESPONSE_BUFFER_SIZE (HCI_ACL_BUFFER_SIZE-HCI_ACL_HEADER_SIZE) static void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -uint32_t sdp_get_service_record_handle(uint8_t * record); // registered service records static linked_list_t sdp_service_records = NULL; @@ -76,15 +74,16 @@ void sdp_init(void){ l2cap_register_service(sdp_packet_handler, PSM_SDP, 0xffff, LEVEL_0); } -uint32_t sdp_get_service_record_handle(uint8_t * record){ - uint8_t * serviceRecordHandleAttribute = sdp_get_attribute_value_for_attribute_id(record, SDP_ServiceRecordHandle); +uint32_t sdp_get_service_record_handle(const uint8_t * record){ + // TODO: make sdp_get_attribute_value_for_attribute_id accept const data to remove cast + uint8_t * serviceRecordHandleAttribute = sdp_get_attribute_value_for_attribute_id((uint8_t *)record, SDP_ServiceRecordHandle); if (!serviceRecordHandleAttribute) return 0; if (de_get_element_type(serviceRecordHandleAttribute) != DE_UINT) return 0; if (de_get_size_type(serviceRecordHandleAttribute) != DE_SIZE_32) return 0; return READ_NET_32(serviceRecordHandleAttribute, 1); } -static service_record_item_t * sdp_get_record_for_handle(uint32_t handle){ +static service_record_item_t * sdp_get_record_item_for_handle(uint32_t handle){ linked_item_t *it; for (it = (linked_item_t *) sdp_service_records; it ; it = it->next){ service_record_item_t * item = (service_record_item_t *) it; @@ -95,140 +94,58 @@ static service_record_item_t * sdp_get_record_for_handle(uint32_t handle){ return NULL; } +uint8_t * sdp_get_record_for_handle(uint32_t handle){ + service_record_item_t * record_item = sdp_get_record_item_for_handle(handle); + if (!record_item) return 0; + return record_item->service_record; +} + // get next free, unregistered service record handle -static uint32_t sdp_create_service_record_handle(void){ +uint32_t sdp_create_service_record_handle(void){ uint32_t handle = 0; do { handle = sdp_next_service_record_handle++; - if (sdp_get_record_for_handle(handle)) handle = 0; + if (sdp_get_record_item_for_handle(handle)) handle = 0; } while (handle == 0); return handle; } -#ifdef EMBEDDED +/** + * @brief Register Service Record with database using ServiceRecordHandle stored in record + * @pre AttributeIDs are in ascending order + * @pre ServiceRecordHandle is first attribute and valid + * @param record is not copied! + * @result status + */ +uint8_t sdp_register_service(const uint8_t * record){ -// register service record internally - this special version doesn't copy the record, it should not be freeed -// pre: AttributeIDs are in ascending order -// pre: ServiceRecordHandle is first attribute and valid -// pre: record -// @returns ServiceRecordHandle or 0 if registration failed -uint32_t sdp_register_service_internal(service_record_item_t * record_item){ - // get user record handle - uint32_t record_handle = record_item->service_record_handle; - // get actual record - uint8_t *record = record_item->service_record; - - // check for ServiceRecordHandle attribute, returns pointer or null - uint8_t * req_record_handle = sdp_get_attribute_value_for_attribute_id(record, SDP_ServiceRecordHandle); - if (!req_record_handle) { - log_error("SDP Error - record does not contain ServiceRecordHandle attribute"); - return 0; - } - - // validate service record handle is not in reserved range - if (record_handle <= maxReservedServiceRecordHandle) record_handle = 0; - - // check if already in use - if (record_handle) { - if (sdp_get_record_for_handle(record_handle)) { - record_handle = 0; - } - } - - // create new handle if needed - if (!record_handle){ - record_handle = sdp_create_service_record_handle(); - // Write the handle back into the record too - record_item->service_record_handle = record_handle; - sdp_set_attribute_value_for_attribute_id(record, SDP_ServiceRecordHandle, record_handle); - } - - // add to linked list - linked_list_add(&sdp_service_records, (linked_item_t *) record_item); - - return record_handle; -} - -#else - -// AttributeIDList used to remove ServiceRecordHandle -static const uint8_t removeServiceRecordHandleAttributeIDList[] = { 0x36, 0x00, 0x05, 0x0A, 0x00, 0x01, 0xFF, 0xFF }; - -// register service record internally - the normal version creates a copy of the record -// pre: AttributeIDs are in ascending order => ServiceRecordHandle is first attribute if present -// @returns ServiceRecordHandle or 0 if registration failed -uint32_t sdp_register_service_internal(uint8_t * record){ - - // dump for now - // log_info("Register service record"); - // de_dump_data_element(record); - - // get user record handle + // validate service record handle. it must: exist, be in valid range, not have been already used uint32_t record_handle = sdp_get_service_record_handle(record); + if (!record_handle) return SDP_HANDLE_INVALID; + if (record_handle <= maxReservedServiceRecordHandle) return SDP_HANDLE_INVALID; + if (sdp_get_record_item_for_handle(record_handle)) return SDP_HANDLE_ALREADY_REGISTERED; - // validate service record handle is not in reserved range - if (record_handle <= maxReservedServiceRecordHandle) record_handle = 0; - - // check if already in use - if (record_handle) { - if (sdp_get_record_for_handle(record_handle)) { - record_handle = 0; - } - } - - // create new handle if needed - if (!record_handle){ - record_handle = sdp_create_service_record_handle(); - } - - // calculate size of new service record: DES (2 byte len) - // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes - uint16_t recordSize = 3 + (3 + 5) + de_get_data_size(record); - // alloc memory for new service_record_item - service_record_item_t * newRecordItem = (service_record_item_t *) malloc(recordSize + sizeof(service_record_item_t)); - if (!newRecordItem) { - return 0; - } - // set new handle - newRecordItem->service_record_handle = record_handle; + service_record_item_t * newRecordItem = btstack_memory_service_record_item_get(); + if (!newRecordItem) return BTSTACK_MEMORY_ALLOC_FAILED; - // create updated service record - uint8_t * newRecord = (uint8_t *) &(newRecordItem->service_record); - - // create DES for new record - de_create_sequence(newRecord); - - // set service record handle - de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0); - de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle); - - // add other attributes - sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord); - - // dump for now - // de_dump_data_element(newRecord); - // log_info("reserved size %u, actual size %u", recordSize, de_get_len(newRecord)); + // set handle and record + newRecordItem->service_record_handle = record_handle; + newRecordItem->service_record = (uint8_t*) record; // add to linked list linked_list_add(&sdp_service_records, (linked_item_t *) newRecordItem); - return record_handle; + return 0; } -#endif - -// unregister service record internally -// -// makes sure one client cannot remove service records of other clients // -void sdp_unregister_service_internal(uint32_t service_record_handle){ - service_record_item_t * record_item = sdp_get_record_for_handle(service_record_handle); +// unregister service record +// +void sdp_unregister_service(uint32_t service_record_handle){ + service_record_item_t * record_item = sdp_get_record_item_for_handle(service_record_handle); if (!record_item) return; linked_list_remove(&sdp_service_records, (linked_item_t *) record_item); -#ifndef EMBEDDED - free(record_item); -#endif } // PDU @@ -343,7 +260,7 @@ int sdp_handle_service_attribute_request(uint8_t * packet, uint16_t remote_mtu){ } // get service record - service_record_item_t * item = sdp_get_record_for_handle(serviceRecordHandle); + service_record_item_t * item = sdp_get_record_item_for_handle(serviceRecordHandle); if (!item){ // service record handle doesn't exist return sdp_create_error_response(transaction_id, 0x0002); /// invalid Service Record Handle diff --git a/src/classic/sdp.h b/src/classic/sdp.h index 182bec918..8d5be183b 100644 --- a/src/classic/sdp.h +++ b/src/classic/sdp.h @@ -57,22 +57,18 @@ typedef enum { SDP_ServiceSearchAttributeResponse } SDP_PDU_ID_t; -// service record -// -- uses user_data field for actual typedef struct { // linked list - assert: first field linked_item_t item; - - // data is contained in same memory + uint32_t service_record_handle; - uint8_t service_record[1]; // waste 1 byte to allow compilation with older compilers + uint8_t * service_record; } service_record_item_t; int sdp_handle_service_search_request(uint8_t * packet, uint16_t remote_mtu); int sdp_handle_service_attribute_request(uint8_t * packet, uint16_t remote_mtu); int sdp_handle_service_search_attribute_request(uint8_t * packet, uint16_t remote_mtu); - /* API_START */ /** @@ -80,30 +76,43 @@ int sdp_handle_service_search_attribute_request(uint8_t * packet, uint16_t remot */ void sdp_init(void); -#ifdef EMBEDDED -/** - * @brief Register service record internally - this version doesn't copy the record therefore it must be forever accessible. Preconditions: - - AttributeIDs are in ascending order; - - ServiceRecordHandle is first attribute and valid. - * @return ServiceRecordHandle or 0 if registration failed. +/** + * @brief Register Service Record with database using ServiceRecordHandle stored in record + * @pre AttributeIDs are in ascending order + * @pre ServiceRecordHandle is first attribute and valid + * @param record is not copied! + * @result status */ -uint32_t sdp_register_service_internal(service_record_item_t * record_item); -#endif - -#ifndef EMBEDDED -/** - * @brief Register service record internally - this version creates a copy of the record precondition: AttributeIDs are in ascending order => ServiceRecordHandle is first attribute if present. - * @return ServiceRecordHandle or 0 if registration failed - */ -uint32_t sdp_register_service_internal(uint8_t * service_record); -#endif +uint8_t sdp_register_service(const uint8_t * record); /** * @brief Unregister service record internally. */ -void sdp_unregister_service_internal(uint32_t service_record_handle); +void sdp_unregister_service(uint32_t service_record_handle); + /* API_END */ +// used by daemon + +/** + * @brief Finds an unused valid service record handle + * @result handle + */ +uint32_t sdp_create_service_record_handle(void); + +/** + * @brief gets record for handle + * @result record + */ + +uint8_t * sdp_get_record_for_handle(uint32_t handle); + +/** + * @brief gets service record handle from record + * @resutl service record handle or 0 + */ +uint32_t sdp_get_service_record_handle(const uint8_t * record); + #if defined __cplusplus } #endif diff --git a/src/hci_cmds.h b/src/hci_cmds.h index 7167bf386..45fb0ba57 100644 --- a/src/hci_cmds.h +++ b/src/hci_cmds.h @@ -853,6 +853,7 @@ extern "C" { #define SDP_HANDLE_ALREADY_REGISTERED 0x80 #define SDP_QUERY_INCOMPLETE 0x81 #define SDP_SERVICE_NOT_FOUND 0x82 +#define SDP_HANDLE_INVALID 0x83 #define ATT_HANDLE_VALUE_INDICATION_IN_PORGRESS 0x90 #define ATT_HANDLE_VALUE_INDICATION_TIMEOUT 0x91 diff --git a/test/gatt_client/mock.c b/test/gatt_client/mock.c index ef3c04850..36d67921e 100644 --- a/test/gatt_client/mock.c +++ b/test/gatt_client/mock.c @@ -12,7 +12,7 @@ #include "ble/sm.h" static btstack_packet_handler_t att_packet_handler; -static void (*registered_l2cap_packet_handler) (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) = NULL; +static void (*registered_l2cap_packet_handler) (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) = NULL; static linked_list_t connections; static const uint16_t max_mtu = 23; @@ -25,22 +25,22 @@ uint16_t get_gatt_client_handle(void){ void mock_simulate_command_complete(const hci_cmd_t *cmd){ uint8_t packet[] = {HCI_EVENT_COMMAND_COMPLETE, 4, 1, cmd->opcode & 0xff, cmd->opcode >> 8, 0}; - registered_l2cap_packet_handler(NULL, HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, sizeof(packet)); + registered_l2cap_packet_handler(HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, sizeof(packet)); } void mock_simulate_hci_state_working(void){ uint8_t packet[3] = {BTSTACK_EVENT_STATE, 0, HCI_STATE_WORKING}; - registered_l2cap_packet_handler(NULL, HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, 3); + registered_l2cap_packet_handler(HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, 3); } void mock_simulate_connected(void){ uint8_t packet[] = {0x3E, 0x13, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x9B, 0x77, 0xD1, 0xF7, 0xB1, 0x34, 0x50, 0x00, 0x00, 0x00, 0xD0, 0x07, 0x05}; - registered_l2cap_packet_handler(NULL, HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, sizeof(packet)); + registered_l2cap_packet_handler(HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, sizeof(packet)); } void mock_simulate_scan_response(void){ uint8_t packet[] = {0xE2, 0x13, 0xE2, 0x01, 0x34, 0xB1, 0xF7, 0xD1, 0x77, 0x9B, 0xCC, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; - registered_l2cap_packet_handler(NULL, HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, sizeof(packet)); + registered_l2cap_packet_handler(HCI_EVENT_PACKET, NULL, (uint8_t *)&packet, sizeof(packet)); } le_command_status_t le_central_start_scan(void){ @@ -89,7 +89,7 @@ void l2cap_register_fixed_channel(btstack_packet_handler_t packet_handler, uint1 att_packet_handler = packet_handler; } -void l2cap_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)){ +void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)){ registered_l2cap_packet_handler = handler; } diff --git a/test/pts/bnep_test.c b/test/pts/bnep_test.c index 3f05f9e1b..c1e5b901d 100644 --- a/test/pts/bnep_test.c +++ b/test/pts/bnep_test.c @@ -799,16 +799,9 @@ int btstack_main(int argc, const char * argv[]){ sdp_init(); uint16_t network_packet_types[] = { NETWORK_TYPE_IPv4, NETWORK_TYPE_ARP, 0}; // 0 as end of list -#ifdef EMBEDDED - service_record_item_t * service_record_item = (service_record_item_t *) panu_sdp_record; - pan_create_panu_service((uint8_t*) &service_record_item->service_record, network_packet_types, NULL, NULL, BNEP_SECURITY_NONE); - printf("SDP service buffer size: %u\n", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record))); - sdp_register_service_internal(service_record_item); -#else pan_create_panu_service(panu_sdp_record, network_packet_types, NULL, NULL, BNEP_SECURITY_NONE); printf("SDP service record size: %u\n", de_get_len((uint8_t*) panu_sdp_record)); - sdp_register_service_internal((uint8_t*)panu_sdp_record); -#endif + sdp_register_service((uint8_t*)panu_sdp_record); /* Turn on the device */ hci_power_control(HCI_POWER_ON); diff --git a/test/pts/classic_test.c b/test/pts/classic_test.c index 67fb3c06b..516f9fd6f 100644 --- a/test/pts/classic_test.c +++ b/test/pts/classic_test.c @@ -781,12 +781,12 @@ int btstack_main(int argc, const char * argv[]){ sdp_create_spp_service((uint8_t*) spp_service_buffer, RFCOMM_SERVER_CHANNEL, "SPP Counter"); de_dump_data_element((uint8_t*) spp_service_buffer); printf("SDP service record size: %u\n\r", de_get_len((uint8_t*)spp_service_buffer)); - sdp_register_service_internal((uint8_t*)spp_service_buffer); + sdp_register_service((uint8_t*)spp_service_buffer); memset(dummy_service_buffer, 0, sizeof(dummy_service_buffer)); sdp_create_dummy_service((uint8_t*)dummy_service_buffer, "UUID128 Test"); de_dump_data_element((uint8_t*)dummy_service_buffer); printf("Dummy service record size: %u\n\r", de_get_len((uint8_t*)dummy_service_buffer)); - sdp_register_service_internal((uint8_t*)dummy_service_buffer); + sdp_register_service((uint8_t*)dummy_service_buffer); sdp_query_rfcomm_register_callback(handle_query_rfcomm_event, NULL); diff --git a/test/pts/hfp_ag_test.c b/test/pts/hfp_ag_test.c index 66b33fa33..32964e838 100644 --- a/test/pts/hfp_ag_test.c +++ b/test/pts/hfp_ag_test.c @@ -202,12 +202,11 @@ int btstack_main(int argc, const char * argv[]){ hfp_ag_register_packet_handler(packet_handler); - sdp_init(); // init SDP, create record for SPP and register with SDP + sdp_init(); memset((uint8_t *)hfp_service_buffer, 0, sizeof(hfp_service_buffer)); hfp_ag_create_sdp_record((uint8_t *)hfp_service_buffer, rfcomm_channel_nr, hfp_ag_service_name, 0, 0); - - sdp_register_service_internal((uint8_t *)hfp_service_buffer); + sdp_register_service((uint8_t *)hfp_service_buffer); // turn on! hci_power_control(HCI_POWER_ON); diff --git a/test/pts/hfp_hf_test.c b/test/pts/hfp_hf_test.c index 91cb128ac..e6c254e5f 100644 --- a/test/pts/hfp_hf_test.c +++ b/test/pts/hfp_hf_test.c @@ -236,11 +236,11 @@ int btstack_main(int argc, const char * argv[]){ hfp_hf_register_packet_handler(packet_handler); - sdp_init(); // init SDP, create record for SPP and register with SDP + sdp_init(); memset((uint8_t *)hfp_service_buffer, 0, sizeof(hfp_service_buffer)); hfp_hf_create_sdp_record((uint8_t *)hfp_service_buffer, rfcomm_channel_nr, hfp_hf_service_name, 0); - sdp_register_service_internal((uint8_t *)hfp_service_buffer); + sdp_register_service((uint8_t *)hfp_service_buffer); // turn on! hci_power_control(HCI_POWER_ON); diff --git a/test/pts/hsp_ag_test.c b/test/pts/hsp_ag_test.c index 99c0495b5..e729eb028 100644 --- a/test/pts/hsp_ag_test.c +++ b/test/pts/hsp_ag_test.c @@ -184,15 +184,15 @@ static void packet_handler(uint8_t * event, uint16_t event_size){ int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ - // init SDP, create record for SPP and register with SDP - memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer)); - hsp_ag_create_service((uint8_t *)hsp_service_buffer, rfcomm_channel_nr, hsp_ag_service_name); hsp_ag_init(rfcomm_channel_nr); hsp_ag_register_packet_handler(packet_handler); + // init SDP, create record for SPP and register with SDP sdp_init(); - sdp_register_service_internal((uint8_t *)hsp_service_buffer); + memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer)); + hsp_ag_create_service((uint8_t *)hsp_service_buffer, rfcomm_channel_nr, hsp_ag_service_name); + sdp_register_service((uint8_t *)hsp_service_buffer); // turn on! hci_power_control(HCI_POWER_ON); diff --git a/test/pts/hsp_hs_test.c b/test/pts/hsp_hs_test.c index 66e859fcb..7152ba73b 100644 --- a/test/pts/hsp_hs_test.c +++ b/test/pts/hsp_hs_test.c @@ -305,14 +305,13 @@ int btstack_main(int argc, const char * argv[]){ setup_audio(); hci_register_sco_packet_handler(&sco_packet_handler); - memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer)); - hsp_hs_create_service((uint8_t *)hsp_service_buffer, rfcomm_channel_nr, hsp_hs_service_name, 0); - hsp_hs_init(rfcomm_channel_nr); hsp_hs_register_packet_handler(packet_handler); sdp_init(); - sdp_register_service_internal((uint8_t *)hsp_service_buffer); + memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer)); + hsp_hs_create_service((uint8_t *)hsp_service_buffer, rfcomm_channel_nr, hsp_hs_service_name, 0); + sdp_register_service((uint8_t *)hsp_service_buffer); hci_discoverable_control(1); hci_set_class_of_device(0x200418);