From 8f5e31a8226bc9c5c2ef18635d8fd66e03d60d32 Mon Sep 17 00:00:00 2001 From: "mila@ringwald.ch" Date: Fri, 2 May 2014 08:06:50 +0000 Subject: [PATCH] ble client: used att_dispatch_register_client --- ble/att_dispatch.h | 8 + ble/gatt_client.c | 5 +- ble/l2cap_le.c | 4 +- example/libusb/ad_parser.c | 153 --- example/libusb/ad_parser.h | 73 -- example/libusb/gatt_client.c | 1282 --------------------- example/libusb/gatt_client.h | 295 ----- test/ble_client/Makefile | 19 +- test/ble_client/advertising_data_parser.c | 9 +- 9 files changed, 35 insertions(+), 1813 deletions(-) delete mode 100644 example/libusb/ad_parser.c delete mode 100644 example/libusb/ad_parser.h delete mode 100644 example/libusb/gatt_client.c delete mode 100644 example/libusb/gatt_client.h diff --git a/ble/att_dispatch.h b/ble/att_dispatch.h index f065160b2..c07371ae0 100644 --- a/ble/att_dispatch.h +++ b/ble/att_dispatch.h @@ -43,6 +43,10 @@ #include +#if defined __cplusplus +extern "C" { +#endif + /** * @brief reset att dispatchter * @param packet_hander for ATT client packets @@ -55,4 +59,8 @@ void att_dispatch_register_client(btstack_packet_handler_t packet_handler); */ void att_dispatch_register_server(btstack_packet_handler_t packet_handler); +#if defined __cplusplus +} +#endif + #endif // __ATT_DISPATCH_H diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 51cf6af57..ee0ab3b8e 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -51,6 +51,7 @@ #include "hci_dump.h" #include "l2cap.h" #include "att.h" +#include "att_dispatch.h" #ifdef HAVE_UART_CC2564 #include "bt_control_cc256x.h" @@ -61,13 +62,15 @@ static linked_list_t gatt_client_connections = NULL; static uint16_t att_client_start_handle = 0x0001; static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size); + void (*gatt_client_callback)(le_event_t * event); void gatt_client_init(){ att_client_start_handle = 0x0000; gatt_client_connections = NULL; - l2cap_register_fixed_channel(gatt_client_att_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL); + //l2cap_register_fixed_channel(gatt_client_att_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL); + att_dispatch_register_client(gatt_client_att_packet_handler); } static void dummy_notify(le_event_t* event){} diff --git a/ble/l2cap_le.c b/ble/l2cap_le.c index 6acc2f2c8..5b682e5c9 100644 --- a/ble/l2cap_le.c +++ b/ble/l2cap_le.c @@ -146,10 +146,10 @@ void l2cap_event_handler( uint8_t *packet, uint16_t size ){ (*packet_handler)(NULL, HCI_EVENT_PACKET, 0, packet, size); } if (attribute_protocol_packet_handler){ - (*attribute_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size) + (*attribute_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size); } if (security_protocol_packet_handler) { - (*security_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size) + (*security_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size); } } diff --git a/example/libusb/ad_parser.c b/example/libusb/ad_parser.c deleted file mode 100644 index bb0cbb01e..000000000 --- a/example/libusb/ad_parser.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2011-2013 by 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. This software may not be used in a commercial product - * without an explicit license granted by the copyright holder. - * - * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD 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. - * - */ - -//***************************************************************************** -// -// Advertising Data Parser -// -//***************************************************************************** - -#include -#include -#include -#include - -#include -#include -#include - -#include "hci.h" -#include "ad_parser.h" - -typedef enum { - IncompleteList16 = 0x02, - CompleteList16 = 0x03, - IncompleteList128 = 0x06, - CompleteList128 = 0x07 -} UUID_TYPE; - -void ad_iterator_init(ad_context_t *context, uint8_t ad_len, uint8_t * ad_data){ - context->data = ad_data; - context->length = ad_len; - context->offset = 0; -} - -int ad_iterator_has_more(ad_context_t * context){ - return context->offset < context->length; -} - -void ad_iterator_next(ad_context_t * context){ - uint8_t chunk_len = context->data[context->offset]; - context->offset += 1 + chunk_len; -} - -uint8_t ad_iterator_get_data_len(ad_context_t * context){ - return context->data[context->offset] - 1; -} - -uint8_t ad_iterator_get_data_type(ad_context_t * context){ - return context->data[context->offset + 1]; -} - -uint8_t * ad_iterator_get_data(ad_context_t * context){ - return &context->data[context->offset + 2]; -} - -int ad_data_contains_uuid16(uint8_t ad_len, uint8_t * ad_data, uint16_t uuid16){ - ad_context_t context; - for (ad_iterator_init(&context, ad_len, ad_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){ - uint8_t data_type = ad_iterator_get_data_type(&context); - uint8_t data_len = ad_iterator_get_data_len(&context); - uint8_t * data = ad_iterator_get_data(&context); - - int i; - uint8_t ad_uuid128[16], uuid128_bt[16]; - - switch (data_type){ - case IncompleteList16: - case CompleteList16: - for (i=0; i -#include -#include -#include -#include -#include -#include -#include - -#include "btstack-config.h" - -#include "ble_client.h" -#include "ad_parser.h" - -#include "debug.h" -#include "btstack_memory.h" -#include "hci.h" -#include "hci_dump.h" -#include "l2cap.h" -#include "att.h" - -#ifdef HAVE_UART_CC2564 -#include "bt_control_cc256x.h" -#endif - - -static linked_list_t gatt_client_connections = NULL; -static uint16_t att_client_start_handle = 0x0001; - -static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size); -void (*gatt_client_callback)(le_event_t * event); - - -void gatt_client_init(){ - att_client_start_handle = 0x0000; - gatt_client_connections = NULL; - l2cap_register_fixed_channel(gatt_client_att_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL); -} - -static void dummy_notify(le_event_t* event){} - -void gatt_client_register_handler(void (*gatt_callback)(le_event_t* event)){ - if (gatt_callback == NULL){ - gatt_callback = &dummy_notify; - } - gatt_client_callback = gatt_callback; -} - -// gatt client API -// start/stop gatt client -void gatt_client_start(gatt_client_t *context, uint16_t handle){ - memset(context, 0, sizeof(gatt_client_t)); - context->handle = handle; - context->mtu_state = SEND_MTU_EXCHANGE; - context->gatt_client_state = P_READY; - linked_list_add(&gatt_client_connections, (linked_item_t*)context); -} - -void gatt_client_stop(gatt_client_t *context){ - linked_list_remove(&gatt_client_connections, (linked_item_t*) context); -} - - -// START Helper Functions - to be sorted -static uint16_t l2cap_max_mtu_for_handle(uint16_t handle){ - return l2cap_max_mtu(); -} - -// END Helper Functions - -static inline void send_gatt_complete_event(gatt_client_t * peripheral, uint8_t type, uint8_t status){ - gatt_complete_event_t event; - event.type = type; - event.device = peripheral; - event.status = status; - (*gatt_client_callback)((le_event_t*)&event); -} - -// precondition: can_send_packet_now == TRUE -static void att_confirmation(uint16_t peripheral_handle){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = ATT_HANDLE_VALUE_CONFIRMATION; - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 1); -} - -// precondition: can_send_packet_now == TRUE -static void att_find_information_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - bt_store_16(request, 1, start_handle); - bt_store_16(request, 3, end_handle); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5); -} - -// precondition: can_send_packet_now == TRUE -static void att_find_by_type_value_request(uint16_t request_type, uint16_t attribute_group_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle, uint8_t * value, uint16_t value_size){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - - request[0] = request_type; - bt_store_16(request, 1, start_handle); - bt_store_16(request, 3, end_handle); - bt_store_16(request, 5, attribute_group_type); - memcpy(&request[7], value, value_size); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7+value_size); -} - -// precondition: can_send_packet_now == TRUE -static void att_read_by_type_or_group_request(uint16_t request_type, uint16_t attribute_group_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - bt_store_16(request, 1, start_handle); - bt_store_16(request, 3, end_handle); - bt_store_16(request, 5, attribute_group_type); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7); -} - -// precondition: can_send_packet_now == TRUE -static void att_read_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - bt_store_16(request, 1, attribute_handle); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3); -} - -// precondition: can_send_packet_now == TRUE -static void att_read_blob_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - bt_store_16(request, 1, attribute_handle); - bt_store_16(request, 3, value_offset); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5); -} - -// precondition: can_send_packet_now == TRUE -static void att_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - bt_store_16(request, 1, attribute_handle); - memcpy(&request[3], value, value_length); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length); -} - -// precondition: can_send_packet_now == TRUE -static void att_execute_write_request(uint16_t request_type, uint16_t peripheral_handle, uint8_t execute_write){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - request[1] = execute_write; - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 2); -} - -// precondition: can_send_packet_now == TRUE -static void att_prepare_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset, uint16_t blob_length, uint8_t * value){ - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = request_type; - bt_store_16(request, 1, attribute_handle); - bt_store_16(request, 3, value_offset); - memcpy(&request[5], &value[value_offset], blob_length); - - l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5+blob_length); -} - -static uint16_t write_blob_length(gatt_client_t * peripheral){ - uint16_t max_blob_length = peripheral->mtu - 5; - if (peripheral->attribute_offset >= peripheral->attribute_length) { - return 0; - } - uint16_t rest_length = peripheral->attribute_length - peripheral->attribute_offset; - if (max_blob_length > rest_length){ - return rest_length; - } - return max_blob_length; -} - - -static void send_gatt_services_request(gatt_client_t *peripheral){ - return att_read_by_type_or_group_request(ATT_READ_BY_GROUP_TYPE_REQUEST, GATT_PRIMARY_SERVICE_UUID, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle); -} - -static void send_gatt_by_uuid_request(gatt_client_t *peripheral, uint16_t attribute_group_type){ - if (peripheral->uuid16){ - uint8_t uuid16[2]; - bt_store_16(uuid16, 0, peripheral->uuid16); - return att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid16, 2); - } - uint8_t uuid128[16]; - swap128(peripheral->uuid128, uuid128); - return att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid128, 16); -} - -static void send_gatt_services_by_uuid_request(gatt_client_t *peripheral){ - send_gatt_by_uuid_request(peripheral, GATT_PRIMARY_SERVICE_UUID); -} - -static void send_gatt_included_service_uuid_request(gatt_client_t *peripheral){ - att_read_request(ATT_READ_REQUEST, peripheral->handle, peripheral->query_start_handle); -} - -static void send_gatt_included_service_request(gatt_client_t *peripheral){ - att_read_by_type_or_group_request(ATT_READ_BY_TYPE_REQUEST, GATT_INCLUDE_SERVICE_UUID, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle); -} - -static void send_gatt_characteristic_request(gatt_client_t *peripheral){ - att_read_by_type_or_group_request(ATT_READ_BY_TYPE_REQUEST, GATT_CHARACTERISTICS_UUID, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle); -} - -static void send_gatt_characteristic_descriptor_request(gatt_client_t *peripheral){ - att_find_information_request(ATT_FIND_INFORMATION_REQUEST, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle); -} - -static void send_gatt_read_characteristic_value_request(gatt_client_t *peripheral){ - att_read_request(ATT_READ_REQUEST, peripheral->handle, peripheral->attribute_handle); -} - -static void send_gatt_read_blob_request(gatt_client_t *peripheral){ - att_read_blob_request(ATT_READ_BLOB_REQUEST, peripheral->handle, peripheral->attribute_handle, peripheral->attribute_offset); -} - -static void send_gatt_write_attribute_value_request(gatt_client_t * peripheral){ - att_write_request(ATT_WRITE_REQUEST, peripheral->handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value); -} - -static void send_gatt_write_client_characteristic_configuration_request(gatt_client_t * peripheral){ - att_write_request(ATT_WRITE_REQUEST, peripheral->handle, peripheral->client_characteristic_configuration_handle, 2, peripheral->client_characteristic_configuration_value); -} - -static void send_gatt_prepare_write_request(gatt_client_t * peripheral){ - att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, peripheral->handle, peripheral->attribute_handle, peripheral->attribute_offset, write_blob_length(peripheral), peripheral->attribute_value); -} - -static void send_gatt_execute_write_request(gatt_client_t * peripheral){ - att_execute_write_request(ATT_EXECUTE_WRITE_REQUEST, peripheral->handle, 1); -} - -static void send_gatt_cancel_prepared_write_request(gatt_client_t * peripheral){ - att_execute_write_request(ATT_EXECUTE_WRITE_REQUEST, peripheral->handle, 0); -} - -static void send_gatt_read_client_characteristic_configuration_request(gatt_client_t * peripheral){ - att_read_by_type_or_group_request(ATT_READ_BY_TYPE_REQUEST, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle); -} - -static void send_gatt_read_characteristic_descriptor_request(gatt_client_t * peripheral){ - att_read_request(ATT_READ_REQUEST, peripheral->handle, peripheral->attribute_handle); -} - -static char * att_errors[] = { - "OK", - "Invalid Handle", - "Read Not Permitted", - "Write Not Permitted", - "Invalid PDU", - "Insufficient Authentication", - "Request Not Supported", - "Invalid Offset", - "Insufficient Authorization", - "Prepare Queue Full", - "Attribute Not Found", - "Attribute Not Long", - "Insufficient Encryption Key Size", - "Invalid Attribute Value Length", - "Unlikely Error", - "Insufficient Encryption", - "Unsupported Group Type", - "Insufficient Resources" -}; - -static void att_client_report_error(uint8_t * packet, uint16_t size){ - - uint8_t error_code = packet[4]; - char * error = "Unknown"; - if (error_code <= 0x11){ - error = att_errors[error_code]; - } - uint16_t handle = READ_BT_16(packet, 2); - printf("ATT_ERROR_REPORT handle 0x%04x, error: %u - %s\n", handle, error_code, error); -} - -static uint16_t get_last_result_handle(uint8_t * packet, uint16_t size){ - uint8_t attr_length = packet[1]; - uint8_t handle_offset = 0; - switch (packet[0]){ - case ATT_READ_BY_TYPE_RESPONSE: - handle_offset = 3; - break; - case ATT_READ_BY_GROUP_TYPE_RESPONSE: - handle_offset = 2; - break; - } - return READ_BT_16(packet, size - attr_length + handle_offset); -} - -static void report_gatt_services(gatt_client_t * peripheral, uint8_t * packet, uint16_t size){ - uint8_t attr_length = packet[1]; - uint8_t uuid_length = attr_length - 4; - - le_service_t service; - le_service_event_t event; - event.type = GATT_SERVICE_QUERY_RESULT; - - int i; - for (i = 2; i < size; i += attr_length){ - service.start_group_handle = READ_BT_16(packet,i); - service.end_group_handle = READ_BT_16(packet,i+2); - - if (uuid_length == 2){ - service.uuid16 = READ_BT_16(packet, i+4); - sdp_normalize_uuid((uint8_t*) &service.uuid128, service.uuid16); - } else { - swap128(&packet[i+4], service.uuid128); - } - event.service = service; - // printf(" report_gatt_services 0x%02x : 0x%02x-0x%02x\n", service.uuid16, service.start_group_handle, service.end_group_handle); - - (*gatt_client_callback)((le_event_t*)&event); - } - // printf("report_gatt_services for %02X done\n", peripheral->handle); -} - -// helper -static void characteristic_start_found(gatt_client_t * peripheral, uint16_t start_handle, uint8_t properties, uint16_t value_handle, uint8_t * uuid, uint16_t uuid_length){ - uint8_t uuid128[16]; - uint16_t uuid16; - if (uuid_length == 2){ - uuid16 = READ_BT_16(uuid, 0); - sdp_normalize_uuid((uint8_t*) uuid128, uuid16); - } else { - swap128(uuid, uuid128); - } - - if (peripheral->filter_with_uuid && memcmp(peripheral->uuid128, uuid128, 16) != 0) return; - - peripheral->characteristic_properties = properties; - peripheral->characteristic_start_handle = start_handle; - peripheral->attribute_handle = value_handle; - - if (peripheral->filter_with_uuid) return; - - peripheral->uuid16 = uuid16; - memcpy(peripheral->uuid128, uuid128, 16); -} - -static void characteristic_end_found(gatt_client_t * peripheral, uint16_t end_handle){ - // TODO: stop searching if filter and uuid found - - if (!peripheral->characteristic_start_handle) return; - - le_characteristic_event_t event; - event.type = GATT_CHARACTERISTIC_QUERY_RESULT; - event.characteristic.start_handle = peripheral->characteristic_start_handle; - event.characteristic.value_handle = peripheral->attribute_handle; - event.characteristic.end_handle = end_handle; - event.characteristic.properties = peripheral->characteristic_properties; - event.characteristic.uuid16 = peripheral->uuid16; - memcpy(event.characteristic.uuid128, peripheral->uuid128, 16); - (*gatt_client_callback)((le_event_t*)&event); - - peripheral->characteristic_start_handle = 0; -} - -static void report_gatt_characteristics(gatt_client_t * peripheral, uint8_t * packet, uint16_t size){ - uint8_t attr_length = packet[1]; - uint8_t uuid_length = attr_length - 5; - int i; - for (i = 2; i < size; i += attr_length){ - uint16_t start_handle = READ_BT_16(packet, i); - uint8_t properties = packet[i+2]; - uint16_t value_handle = READ_BT_16(packet, i+3); - characteristic_end_found(peripheral, start_handle-1); - characteristic_start_found(peripheral, start_handle, properties, value_handle, &packet[i+5], uuid_length); - } -} - - -static void report_gatt_included_service(gatt_client_t * peripheral, uint8_t *uuid128, uint16_t uuid16){ - le_service_t service; - service.uuid16 = uuid16; - if (service.uuid16){ - sdp_normalize_uuid((uint8_t*) &service.uuid128, service.uuid16); - } - if (uuid128){ - memcpy(service.uuid128, uuid128, 16); - } - - service.start_group_handle = peripheral->query_start_handle; - service.end_group_handle = peripheral->query_end_handle; - - le_service_event_t event; - event.type = GATT_INCLUDED_SERVICE_QUERY_RESULT; - event.service = service; - (*gatt_client_callback)((le_event_t*)&event); -} - -static void send_characteristic_value_event(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, uint16_t length, uint16_t offset, uint8_t event_type){ - le_characteristic_value_event_t event; - event.type = event_type; - event.characteristic_value_handle = handle; - event.characteristic_value_blob_length = length; - event.characteristic_value = value; - event.characteristic_value_offset = offset; - (*gatt_client_callback)((le_event_t*)&event); -} - -static void report_gatt_long_characteristic_value_blob(gatt_client_t * peripheral, uint8_t * value, uint16_t blob_length, int value_offset){ - send_characteristic_value_event(peripheral, peripheral->attribute_handle, value, blob_length, value_offset, GATT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT); -} - -static void report_gatt_notification(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ - send_characteristic_value_event(peripheral, handle, value, length, 0, GATT_NOTIFICATION); -} - -static void report_gatt_indication(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ - send_characteristic_value_event(peripheral, handle, value, length, 0, GATT_INDICATION); -} - -static void report_gatt_characteristic_value(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ - send_characteristic_value_event(peripheral, handle, value, length, 0, GATT_CHARACTERISTIC_VALUE_QUERY_RESULT); -} - -static void report_gatt_characteristic_descriptor(gatt_client_t * peripheral, uint16_t handle, uint8_t *value, uint16_t value_length, uint16_t value_offset, uint8_t event_type){ - le_characteristic_descriptor_event_t event; - event.type = event_type; // GATT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT; - - le_characteristic_descriptor_t descriptor; - descriptor.handle = handle; - descriptor.uuid16 = peripheral->uuid16; - descriptor.value_offset = value_offset; - if (peripheral->uuid128){ - memcpy(descriptor.uuid128, peripheral->uuid128, 16); - } - - descriptor.value = value; - descriptor.value_length = value_length; - event.characteristic_descriptor = descriptor; - (*gatt_client_callback)((le_event_t*)&event); -} - -static void report_gatt_all_characteristic_descriptors(gatt_client_t * peripheral, uint8_t * packet, uint16_t size, uint16_t pair_size){ - le_characteristic_descriptor_t descriptor; - le_characteristic_descriptor_event_t event; - event.type = GATT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT; - - int i; - for (i = 0; iend_group_handle){ - peripheral->start_group_handle = last_result_handle + 1; - peripheral->gatt_client_state = next_query_state; - return; - } - // DONE - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, complete_event_type, 0); -} - - -static inline void trigger_next_included_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){ - trigger_next_query(peripheral, last_result_handle, P_W2_SEND_INCLUDED_SERVICE_QUERY, GATT_INCLUDED_SERVICE_QUERY_COMPLETE); -} - -static inline void trigger_next_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){ - trigger_next_query(peripheral, last_result_handle, P_W2_SEND_SERVICE_QUERY, GATT_SERVICE_QUERY_COMPLETE); -} - -static inline void trigger_next_service_by_uuid_query(gatt_client_t * peripheral, uint16_t last_result_handle){ - trigger_next_query(peripheral, last_result_handle, P_W2_SEND_SERVICE_WITH_UUID_QUERY, GATT_SERVICE_QUERY_COMPLETE); -} - -static inline void trigger_next_characteristic_query(gatt_client_t * peripheral, uint16_t last_result_handle){ - trigger_next_query(peripheral, last_result_handle, P_W2_SEND_CHARACTERISTIC_QUERY, GATT_CHARACTERISTIC_QUERY_COMPLETE); -} - -//static inline void trigger_next_characteristic_by_uuid_query(gatt_client_t * peripheral, uint16_t last_result_handle){ -// trigger_next_query(peripheral, last_result_handle, P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY, GATT_CHARACTERISTIC_QUERY_COMPLETE); -//} - -static inline void trigger_next_characteristic_descriptor_query(gatt_client_t * peripheral, uint16_t last_result_handle){ - trigger_next_query(peripheral, last_result_handle, P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY, GATT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_COMPLETE); -} - -static inline void trigger_next_prepare_write_query(gatt_client_t * peripheral, gatt_client_state_t next_query_state, gatt_client_state_t done_state){ - peripheral->attribute_offset += write_blob_length(peripheral); - uint16_t next_blob_length = write_blob_length(peripheral); - - if (next_blob_length == 0){ - peripheral->gatt_client_state = done_state; - return; - } - peripheral->gatt_client_state = next_query_state; -} - -static inline void trigger_next_blob_query(gatt_client_t * peripheral, gatt_client_state_t next_query_state, uint8_t done_event, uint16_t received_blob_length){ - - uint16_t max_blob_length = peripheral->mtu - 1; - if (received_blob_length < max_blob_length){ - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, done_event, 0); - return; - } - - peripheral->attribute_offset += received_blob_length; - peripheral->gatt_client_state = next_query_state; -} - -static int is_value_valid(gatt_client_t *peripheral, uint8_t *packet, uint16_t size){ - uint16_t attribute_handle = READ_BT_16(packet, 1); - uint16_t value_offset = READ_BT_16(packet, 3); - - if (peripheral->attribute_handle != attribute_handle) return 0; - if (peripheral->attribute_offset != value_offset) return 0; - return memcmp(&peripheral->attribute_value[peripheral->attribute_offset], &packet[5], size-5) == 0; -} - - -static gatt_client_t * get_gatt_client_context_for_handle(uint16_t handle){ - linked_item_t *it; - for (it = (linked_item_t *) gatt_client_connections; it ; it = it->next){ - gatt_client_t * peripheral = (gatt_client_t *) it; - if (peripheral->handle == handle){ - return peripheral; - } - } - return NULL; -} - -static void gatt_client_handle_context_list(){ - if (!hci_can_send_packet_now_using_packet_buffer(HCI_COMMAND_DATA_PACKET)) return; - // printf("handle_peripheral_list 4\n"); - if (!l2cap_can_send_connectionless_packet_now()) return; - // printf("handle_peripheral_list 5\n"); - - // printf("handle_peripheral_list empty %u\n", linked_list_empty(&le_connections)); - linked_item_t *it; - for (it = (linked_item_t *) gatt_client_connections; it ; it = it->next){ - gatt_client_t * peripheral = (gatt_client_t *) it; - // printf("handle_peripheral_list, status %u\n", peripheral->state); - - switch (peripheral->mtu_state) { - case SEND_MTU_EXCHANGE:{ - peripheral->mtu_state = SENT_MTU_EXCHANGE; - uint16_t mtu = l2cap_max_mtu_for_handle(peripheral->handle); - // TODO: extract as att_exchange_mtu_request - l2cap_reserve_packet_buffer(); - uint8_t * request = l2cap_get_outgoing_buffer(); - request[0] = ATT_EXCHANGE_MTU_REQUEST; - bt_store_16(request, 1, mtu); - l2cap_send_prepared_connectionless(peripheral->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3); - return; - } - case SENT_MTU_EXCHANGE: - return; - default: - break; - } - - if (peripheral->send_confirmation){ - peripheral->send_confirmation = 0; - att_confirmation(peripheral->handle); - return; - } - - // printf("gatt_client_state %u\n", peripheral->gatt_client_state); - switch (peripheral->gatt_client_state){ - case P_W2_SEND_SERVICE_QUERY: - peripheral->gatt_client_state = P_W4_SERVICE_QUERY_RESULT; - send_gatt_services_request(peripheral); - break; - - case P_W2_SEND_SERVICE_WITH_UUID_QUERY: - peripheral->gatt_client_state = P_W4_SERVICE_WITH_UUID_RESULT; - send_gatt_services_by_uuid_request(peripheral); - break; - - case P_W2_SEND_CHARACTERISTIC_QUERY: - peripheral->gatt_client_state = P_W4_CHARACTERISTIC_QUERY_RESULT; - send_gatt_characteristic_request(peripheral); - break; - - case P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY: - peripheral->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT; - send_gatt_characteristic_request(peripheral); - break; - - case P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY: - peripheral->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT; - send_gatt_characteristic_descriptor_request(peripheral); - break; - - case P_W2_SEND_INCLUDED_SERVICE_QUERY: - peripheral->gatt_client_state = P_W4_INCLUDED_SERVICE_QUERY_RESULT; - send_gatt_included_service_request(peripheral); - break; - - case P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY: - peripheral->gatt_client_state = P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT; - send_gatt_included_service_uuid_request(peripheral); - break; - - case P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY: - peripheral->gatt_client_state = P_W4_READ_CHARACTERISTIC_VALUE_RESULT; - send_gatt_read_characteristic_value_request(peripheral); - break; - - case P_W2_SEND_READ_BLOB_QUERY: - peripheral->gatt_client_state = P_W4_READ_BLOB_RESULT; - send_gatt_read_blob_request(peripheral); - break; - - case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE: - peripheral->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT; - send_gatt_write_attribute_value_request(peripheral); - break; - - case P_W2_PREPARE_WRITE: - peripheral->gatt_client_state = P_W4_PREPARE_WRITE_RESULT; - send_gatt_prepare_write_request(peripheral); - break; - - case P_W2_PREPARE_RELIABLE_WRITE: - peripheral->gatt_client_state = P_W4_PREPARE_RELIABLE_WRITE_RESULT; - send_gatt_prepare_write_request(peripheral); - break; - - case P_W2_EXECUTE_PREPARED_WRITE: - peripheral->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_RESULT; - send_gatt_execute_write_request(peripheral); - break; - - case P_W2_CANCEL_PREPARED_WRITE: - peripheral->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_RESULT; - send_gatt_cancel_prepared_write_request(peripheral); - break; - - case P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY: - peripheral->gatt_client_state = P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT; - send_gatt_read_client_characteristic_configuration_request(peripheral); - break; - - case P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY: - peripheral->gatt_client_state = P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT; - send_gatt_read_characteristic_descriptor_request(peripheral); - break; - - case P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY: - peripheral->gatt_client_state = P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT; - send_gatt_read_blob_request(peripheral); - break; - - case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR: - peripheral->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT; - send_gatt_write_attribute_value_request(peripheral); - break; - - case P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION: - peripheral->gatt_client_state = P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT; - send_gatt_write_client_characteristic_configuration_request(peripheral); - break; - - case P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR: - peripheral->gatt_client_state = P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT; - send_gatt_prepare_write_request(peripheral); - break; - - case P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR: - peripheral->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT; - send_gatt_execute_write_request(peripheral); - break; - default: - break; - } - - } - -} - -static void gatt_client_run(){ - gatt_client_handle_context_list(); -} - -void gatt_packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ - if (packet_type != HCI_EVENT_PACKET) return; - switch (packet[0]) { - case HCI_EVENT_DISCONNECTION_COMPLETE: - { - uint16_t handle = READ_BT_16(packet,3); - gatt_client_t * peripheral = get_gatt_client_context_for_handle(handle); - if (!peripheral) break; - - // TODO should we send some complete event if transaction pending??? - - peripheral->gatt_client_state = P_READY; - linked_list_remove(&gatt_client_connections, (linked_item_t *) peripheral); - break; - } - default: - break; - } - gatt_client_run(); -} - -static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ - if (packet_type != ATT_DATA_PACKET) return; - - gatt_client_t * peripheral = get_gatt_client_context_for_handle(handle); - if (!peripheral) return; - - switch (packet[0]){ - case ATT_EXCHANGE_MTU_RESPONSE: - { - uint16_t remote_rx_mtu = READ_BT_16(packet, 1); - uint16_t local_rx_mtu = l2cap_max_mtu_for_handle(handle); - peripheral->mtu = remote_rx_mtu < local_rx_mtu ? remote_rx_mtu : local_rx_mtu; - peripheral->mtu_state = MTU_EXCHANGED; - break; - } - case ATT_READ_BY_GROUP_TYPE_RESPONSE: - switch(peripheral->gatt_client_state){ - case P_W4_SERVICE_QUERY_RESULT: - report_gatt_services(peripheral, packet, size); - trigger_next_service_query(peripheral, get_last_result_handle(packet, size)); - break; - default: - printf("ATT_READ_BY_GROUP_TYPE_RESPONSE\n"); - break; - } - break; - case ATT_HANDLE_VALUE_NOTIFICATION: - report_gatt_notification(peripheral, READ_BT_16(packet,1), &packet[3], size-3); - break; - - case ATT_HANDLE_VALUE_INDICATION: - report_gatt_indication(peripheral, READ_BT_16(packet,1), &packet[3], size-3); - peripheral->send_confirmation = 1; - break; - - case ATT_READ_BY_TYPE_RESPONSE: - switch (peripheral->gatt_client_state){ - case P_W4_CHARACTERISTIC_QUERY_RESULT: - report_gatt_characteristics(peripheral, packet, size); - trigger_next_characteristic_query(peripheral, get_last_result_handle(packet, size)); - break; - case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT: - report_gatt_characteristics(peripheral, packet, size); - trigger_next_characteristic_query(peripheral, get_last_result_handle(packet, size)); - break; - case P_W4_INCLUDED_SERVICE_QUERY_RESULT: - { - uint16_t uuid16 = 0; - uint16_t pair_size = packet[1]; - - if (pair_size < 7){ - // UUIDs not available, query first included service - peripheral->start_group_handle = READ_BT_16(packet, 2); // ready for next query - peripheral->query_start_handle = READ_BT_16(packet, 4); - peripheral->query_end_handle = READ_BT_16(packet,6); - peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY; - break; - } - - uint16_t offset; - for (offset = 2; offset < size; offset += pair_size){ - peripheral->query_start_handle = READ_BT_16(packet,offset+2); - peripheral->query_end_handle = READ_BT_16(packet,offset+4); - uuid16 = READ_BT_16(packet, offset+6); - report_gatt_included_service(peripheral, NULL, uuid16); - } - - trigger_next_included_service_query(peripheral, get_last_result_handle(packet, size)); - break; - } - case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT: - peripheral->client_characteristic_configuration_handle = READ_BT_16(packet, 2); - peripheral->gatt_client_state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION; - break; - default: - break; - } - break; - case ATT_READ_RESPONSE: - switch (peripheral->gatt_client_state){ - case P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT: { - uint8_t uuid128[16]; - swap128(&packet[1], uuid128); - report_gatt_included_service(peripheral, uuid128, 0); - trigger_next_included_service_query(peripheral, peripheral->start_group_handle); - break; - } - case P_W4_READ_CHARACTERISTIC_VALUE_RESULT: - peripheral->gatt_client_state = P_READY; - report_gatt_characteristic_value(peripheral, peripheral->attribute_handle, &packet[1], size-1); - break; - - case P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT:{ - peripheral->gatt_client_state = P_READY; - report_gatt_characteristic_descriptor(peripheral, peripheral->attribute_handle, &packet[1], size-1, 0, GATT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT); - break; - } - default: - break; - } - break; - - case ATT_FIND_BY_TYPE_VALUE_RESPONSE: - { - uint8_t pair_size = 4; - le_service_t service; - le_service_event_t event; - event.type = GATT_SERVICE_QUERY_RESULT; - - int i; - for (i = 1; iuuid128, 16); - service.uuid16 = peripheral->uuid16; - event.service = service; - (*gatt_client_callback)((le_event_t*)&event); - } - - trigger_next_service_by_uuid_query(peripheral, service.end_group_handle); - break; - } - case ATT_FIND_INFORMATION_REPLY: - { - uint8_t pair_size = 4; - if (packet[1] == 2){ - pair_size = 18; - } - uint16_t last_descriptor_handle = READ_BT_16(packet, size - pair_size); - - report_gatt_all_characteristic_descriptors(peripheral, &packet[2], size-2, pair_size); - trigger_next_characteristic_descriptor_query(peripheral, last_descriptor_handle); - - break; - } - - case ATT_WRITE_RESPONSE: - switch (peripheral->gatt_client_state){ - case P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_CHARACTERISTIC_VALUE_WRITE_RESPONSE, 0); - break; - case P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_COMPLETE, 0); - break; - case P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_CHARACTERISTIC_DESCRIPTOR_WRITE_RESPONSE, 0); - break; - default: - break; - } - break; - - case ATT_READ_BLOB_RESPONSE:{ - uint16_t received_blob_length = size-1; - - switch(peripheral->gatt_client_state){ - case P_W4_READ_BLOB_RESULT: - report_gatt_long_characteristic_value_blob(peripheral, &packet[1], received_blob_length, peripheral->attribute_offset); - trigger_next_blob_query(peripheral, P_W2_SEND_READ_BLOB_QUERY, GATT_LONG_CHARACTERISTIC_VALUE_QUERY_COMPLETE, received_blob_length); - break; - case P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT: - report_gatt_characteristic_descriptor(peripheral, peripheral->attribute_handle, - &packet[1], received_blob_length, - peripheral->attribute_offset, GATT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT); - trigger_next_blob_query(peripheral, P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY, GATT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_COMPLETE, received_blob_length); - break; - default: - break; - } - break; - } - case ATT_PREPARE_WRITE_RESPONSE: - switch (peripheral->gatt_client_state){ - case P_W4_PREPARE_WRITE_RESULT:{ - peripheral->attribute_offset = READ_BT_16(packet, 3); - trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE, P_W2_EXECUTE_PREPARED_WRITE); - break; - } - case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:{ - peripheral->attribute_offset = READ_BT_16(packet, 3); - trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR, P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR); - break; - } - case P_W4_PREPARE_RELIABLE_WRITE_RESULT:{ - if (is_value_valid(peripheral, packet, size)){ - peripheral->attribute_offset = READ_BT_16(packet, 3); - trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_RELIABLE_WRITE, P_W2_EXECUTE_PREPARED_WRITE); - break; - } - peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE; - break; - } - default: - break; - } - break; - - case ATT_EXECUTE_WRITE_RESPONSE: - switch (peripheral->gatt_client_state){ - case P_W4_EXECUTE_PREPARED_WRITE_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_LONG_CHARACTERISTIC_VALUE_WRITE_COMPLETE, 0); - break; - case P_W4_CANCEL_PREPARED_WRITE_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_LONG_CHARACTERISTIC_VALUE_WRITE_CANCELED, 1); - break; - case P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_LONG_CHARACTERISTIC_DESCRIPTOR_WRITE_COMPLETE, 0); - break; - default: - break; - - } - break; - - case ATT_ERROR_RESPONSE: - // printf("ATT_ERROR_RESPONSE error %u, state %u\n", packet[4], peripheral->state); - switch (packet[4]){ - case ATT_ERROR_ATTRIBUTE_NOT_FOUND: { - switch(peripheral->gatt_client_state){ - case P_W4_SERVICE_QUERY_RESULT: - case P_W4_SERVICE_WITH_UUID_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_SERVICE_QUERY_COMPLETE, 0); - break; - - case P_W4_CHARACTERISTIC_QUERY_RESULT: - case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT: - characteristic_end_found(peripheral, peripheral->end_group_handle); - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_CHARACTERISTIC_QUERY_COMPLETE, 0); - break; - - case P_W4_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_COMPLETE, 0); - break; - case P_W4_INCLUDED_SERVICE_QUERY_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_INCLUDED_SERVICE_QUERY_COMPLETE, 0); - break; - case P_W4_READ_BLOB_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_LONG_CHARACTERISTIC_VALUE_QUERY_COMPLETE, 0); - break; - case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT: - peripheral->gatt_client_state = P_READY; - send_gatt_complete_event(peripheral, GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_COMPLETE, 0); - break; - default: - printf("ATT_ERROR_ATTRIBUTE_NOT_FOUND in %d\n", peripheral->gatt_client_state); - return; - } - - break; - } - default: - att_client_report_error(packet, size); - break; - } - break; - - default: - printf("ATT Handler, unhandled response type 0x%02x\n", packet[0]); - break; - } - gatt_client_run(); -} - - - -le_command_status_t gatt_client_discover_primary_services(gatt_client_t *peripheral){ - peripheral->start_group_handle = 0x0001; - peripheral->end_group_handle = 0xffff; - peripheral->gatt_client_state = P_W2_SEND_SERVICE_QUERY; - - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - - -le_command_status_t gatt_client_discover_primary_services_by_uuid16(gatt_client_t *peripheral, uint16_t uuid16){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->start_group_handle = 0x0001; - peripheral->end_group_handle = 0xffff; - peripheral->gatt_client_state = P_W2_SEND_SERVICE_WITH_UUID_QUERY; - peripheral->uuid16 = uuid16; - sdp_normalize_uuid((uint8_t*) &(peripheral->uuid128), peripheral->uuid16); - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_discover_primary_services_by_uuid128(gatt_client_t *peripheral, const uint8_t * uuid128){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->start_group_handle = 0x0001; - peripheral->end_group_handle = 0xffff; - peripheral->uuid16 = 0; - memcpy(peripheral->uuid128, uuid128, 16); - - peripheral->gatt_client_state = P_W2_SEND_SERVICE_WITH_UUID_QUERY; - - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_discover_characteristics_for_service(gatt_client_t *peripheral, le_service_t *service){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->start_group_handle = service->start_group_handle; - peripheral->end_group_handle = service->end_group_handle; - peripheral->filter_with_uuid = 0; - peripheral->characteristic_start_handle = 0; - peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_QUERY; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_find_included_services_for_service(gatt_client_t *peripheral, le_service_t *service){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->start_group_handle = service->start_group_handle; - peripheral->end_group_handle = service->end_group_handle; - peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_QUERY; - - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_discover_characteristics_for_handle_range_by_uuid16(gatt_client_t *peripheral, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->start_group_handle = start_handle; - peripheral->end_group_handle = end_handle; - peripheral->filter_with_uuid = 1; - peripheral->uuid16 = uuid16; - sdp_normalize_uuid((uint8_t*) &(peripheral->uuid128), uuid16); - peripheral->characteristic_start_handle = 0; - peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY; - - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_discover_characteristics_for_handle_range_by_uuid128(gatt_client_t *peripheral, uint16_t start_handle, uint16_t end_handle, uint8_t * uuid128){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->start_group_handle = start_handle; - peripheral->end_group_handle = end_handle; - peripheral->filter_with_uuid = 1; - peripheral->uuid16 = 0; - memcpy(peripheral->uuid128, uuid128, 16); - peripheral->characteristic_start_handle = 0; - peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY; - - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - - -le_command_status_t gatt_client_discover_characteristics_for_service_by_uuid16 (gatt_client_t *peripheral, le_service_t *service, uint16_t uuid16){ - return gatt_client_discover_characteristics_for_handle_range_by_uuid16(peripheral, service->start_group_handle, service->end_group_handle, uuid16); -} - -le_command_status_t gatt_client_discover_characteristics_for_service_by_uuid128(gatt_client_t *peripheral, le_service_t *service, uint8_t * uuid128){ - return gatt_client_discover_characteristics_for_handle_range_by_uuid128(peripheral, service->start_group_handle, service->end_group_handle, uuid128); -} - -le_command_status_t gatt_client_discover_characteristic_descriptors(gatt_client_t *peripheral, le_characteristic_t *characteristic){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - if (characteristic->value_handle == characteristic->end_handle){ - send_gatt_complete_event(peripheral, GATT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_COMPLETE, 0); - return BLE_PERIPHERAL_OK; - } - peripheral->start_group_handle = characteristic->value_handle + 1; - peripheral->end_group_handle = characteristic->end_handle; - peripheral->gatt_client_state = P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY; - - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_read_value_of_characteristic_using_value_handle(gatt_client_t *peripheral, uint16_t value_handle){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = value_handle; - peripheral->attribute_offset = 0; - peripheral->gatt_client_state = P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_read_value_of_characteristic(gatt_client_t *peripheral, le_characteristic_t *characteristic){ - return gatt_client_read_value_of_characteristic_using_value_handle(peripheral, characteristic->value_handle); -} - - -le_command_status_t gatt_client_read_long_value_of_characteristic_using_value_handle(gatt_client_t *peripheral, uint16_t value_handle){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = value_handle; - peripheral->attribute_offset = 0; - peripheral->gatt_client_state = P_W2_SEND_READ_BLOB_QUERY; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_read_long_value_of_characteristic(gatt_client_t *peripheral, le_characteristic_t *characteristic){ - return gatt_client_read_long_value_of_characteristic_using_value_handle(peripheral, characteristic->value_handle); -} - -le_command_status_t gatt_client_write_value_of_characteristic_without_response(gatt_client_t *peripheral, uint16_t value_handle, uint16_t value_length, uint8_t * value){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - if (value_length >= peripheral->mtu - 3) return BLE_VALUE_TOO_LONG; - - att_write_request(ATT_WRITE_COMMAND, peripheral->handle, value_handle, value_length, value); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_write_value_of_characteristic(gatt_client_t *peripheral, uint16_t value_handle, uint16_t value_length, uint8_t * value){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - if (value_length >= peripheral->mtu - 3) return BLE_VALUE_TOO_LONG; - - peripheral->attribute_handle = value_handle; - peripheral->attribute_length = value_length; - peripheral->attribute_value = value; - peripheral->gatt_client_state = P_W2_SEND_WRITE_CHARACTERISTIC_VALUE; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_write_long_value_of_characteristic(gatt_client_t *peripheral, uint16_t value_handle, uint16_t value_length, uint8_t * value){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = value_handle; - peripheral->attribute_length = value_length; - peripheral->attribute_offset = 0; - peripheral->attribute_value = value; - peripheral->gatt_client_state = P_W2_PREPARE_WRITE; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_reliable_write_long_value_of_characteristic(gatt_client_t *peripheral, uint16_t value_handle, uint16_t value_length, uint8_t * value){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = value_handle; - peripheral->attribute_length = value_length; - peripheral->attribute_offset = 0; - peripheral->attribute_value = value; - peripheral->gatt_client_state = P_W2_PREPARE_RELIABLE_WRITE; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_write_client_characteristic_configuration(gatt_client_t *peripheral, le_characteristic_t * characteristic, uint16_t configuration){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION) && - (characteristic->properties & ATT_PROPERTY_NOTIFY) == 0) { - log_info("le_central_write_client_characteristic_configuration: BLE_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED"); - return BLE_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED; - } else if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION) && - (characteristic->properties & ATT_PROPERTY_INDICATE) == 0){ - log_info("le_central_write_client_characteristic_configuration: BLE_CHARACTERISTIC_INDICATION_NOT_SUPPORTED\n"); - return BLE_CHARACTERISTIC_INDICATION_NOT_SUPPORTED; - } - - peripheral->start_group_handle = characteristic->value_handle; - peripheral->end_group_handle = characteristic->end_handle; - bt_store_16(peripheral->client_characteristic_configuration_value, 0, configuration); - - peripheral->gatt_client_state = P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_read_characteristic_descriptor(gatt_client_t *peripheral, le_characteristic_descriptor_t * descriptor){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = descriptor->handle; - - peripheral->uuid16 = descriptor->uuid16; - if (!descriptor->uuid16){ - memcpy(peripheral->uuid128, descriptor->uuid128, 16); - } - - peripheral->gatt_client_state = P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_read_long_characteristic_descriptor(gatt_client_t *peripheral, le_characteristic_descriptor_t * descriptor){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = descriptor->handle; - peripheral->attribute_offset = 0; - peripheral->gatt_client_state = P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_write_characteristic_descriptor(gatt_client_t *peripheral, le_characteristic_descriptor_t * descriptor, uint16_t length, uint8_t * value){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = descriptor->handle; - peripheral->attribute_length = length; - peripheral->attribute_offset = 0; - peripheral->attribute_value = value; - - peripheral->gatt_client_state = P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - -le_command_status_t gatt_client_write_long_characteristic_descriptor(gatt_client_t *peripheral, le_characteristic_descriptor_t * descriptor, uint16_t length, uint8_t * value){ - if (peripheral->gatt_client_state != P_READY) return BLE_PERIPHERAL_IN_WRONG_STATE; - peripheral->attribute_handle = descriptor->handle; - peripheral->attribute_length = length; - peripheral->attribute_offset = 0; - peripheral->attribute_value = value; - - peripheral->gatt_client_state = P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR; - gatt_client_run(); - return BLE_PERIPHERAL_OK; -} - diff --git a/example/libusb/gatt_client.h b/example/libusb/gatt_client.h deleted file mode 100644 index 2cbc96e97..000000000 --- a/example/libusb/gatt_client.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2011-2014 by 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. This software may not be used in a commercial product - * without an explicit license granted by the copyright holder. - * - * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD 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. - * - */ - - -#ifndef btstack_gatt_client_h -#define btstack_gatt_client_h - -#if defined __cplusplus -extern "C" { -#endif - -//*************** le client - -typedef struct le_event { - uint8_t type; -} le_event_t; - -typedef enum { - BLE_PERIPHERAL_OK = 0, - BLE_PERIPHERAL_IN_WRONG_STATE, - BLE_PERIPHERAL_DIFFERENT_CONTEXT_FOR_ADDRESS_ALREADY_EXISTS, - BLE_PERIPHERAL_NOT_CONNECTED, - BLE_VALUE_TOO_LONG, - BLE_PERIPHERAL_BUSY, - BLE_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED, - BLE_CHARACTERISTIC_INDICATION_NOT_SUPPORTED -} le_command_status_t; - - -//*************** gatt client -typedef enum { - P_READY, - P_W2_SEND_SERVICE_QUERY, - P_W4_SERVICE_QUERY_RESULT, - P_W2_SEND_SERVICE_WITH_UUID_QUERY, - P_W4_SERVICE_WITH_UUID_RESULT, - - P_W2_SEND_CHARACTERISTIC_QUERY, - P_W4_CHARACTERISTIC_QUERY_RESULT, - P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY, - P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT, - - P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY, - P_W4_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT, - - P_W2_SEND_INCLUDED_SERVICE_QUERY, - P_W4_INCLUDED_SERVICE_QUERY_RESULT, - P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY, - P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT, - - P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY, - P_W4_READ_CHARACTERISTIC_VALUE_RESULT, - - P_W2_SEND_READ_BLOB_QUERY, - P_W4_READ_BLOB_RESULT, - - P_W2_SEND_WRITE_CHARACTERISTIC_VALUE, - P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT, - - P_W2_PREPARE_WRITE, - P_W4_PREPARE_WRITE_RESULT, - P_W2_PREPARE_RELIABLE_WRITE, - P_W4_PREPARE_RELIABLE_WRITE_RESULT, - - P_W2_EXECUTE_PREPARED_WRITE, - P_W4_EXECUTE_PREPARED_WRITE_RESULT, - P_W2_CANCEL_PREPARED_WRITE, - P_W4_CANCEL_PREPARED_WRITE_RESULT, - - P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY, - P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT, - P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION, - P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT, - - P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY, - P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT, - - P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY, - P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT, - - P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR, - P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT, - - P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR, - P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT, - P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR, - P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT -} gatt_client_state_t; - - -typedef enum{ - SEND_MTU_EXCHANGE, - SENT_MTU_EXCHANGE, - MTU_EXCHANGED -} gatt_client_mtu_t; - -typedef struct gatt_client{ - linked_item_t item; - gatt_client_state_t gatt_client_state; - // le_central_state_t le_central_state; - - uint16_t handle; - - uint8_t address_type; - bd_addr_t address; - uint16_t mtu; - gatt_client_mtu_t mtu_state; - - uint16_t uuid16; - uint8_t uuid128[16]; - - uint16_t start_group_handle; - uint16_t end_group_handle; - - uint16_t query_start_handle; - uint16_t query_end_handle; - - uint8_t characteristic_properties; - uint16_t characteristic_start_handle; - - uint16_t attribute_handle; - uint16_t attribute_offset; - uint16_t attribute_length; - uint8_t* attribute_value; - - uint16_t client_characteristic_configuration_handle; - uint8_t client_characteristic_configuration_value[2]; - - uint8_t filter_with_uuid; - uint8_t send_confirmation; - -} gatt_client_t; - -typedef struct gatt_complete_event{ - uint8_t type; - gatt_client_t * device; - uint8_t status; -} gatt_complete_event_t; - -typedef struct le_service{ - uint16_t start_group_handle; - uint16_t end_group_handle; - uint16_t uuid16; - uint8_t uuid128[16]; -} le_service_t; - -typedef struct le_service_event{ - uint8_t type; - le_service_t service; -} le_service_event_t; - -typedef struct le_characteristic{ - uint8_t properties; - uint16_t start_handle; - uint16_t value_handle; - uint16_t end_handle; - uint16_t uuid16; - uint8_t uuid128[16]; -} le_characteristic_t; - -typedef struct le_characteristic_event{ - uint8_t type; - le_characteristic_t characteristic; -} le_characteristic_event_t; - -typedef struct le_characteristic_descriptor{ - uint16_t handle; - uint16_t uuid16; - uint8_t uuid128[16]; - uint16_t value_length; - uint16_t value_offset; - uint8_t * value; -} le_characteristic_descriptor_t; - -typedef struct le_characteristic_descriptor_event{ - uint8_t type; - le_characteristic_descriptor_t characteristic_descriptor; -} le_characteristic_descriptor_event_t; - -typedef struct le_characteristic_value{ - -} le_characteristic_value_t; - -typedef struct le_characteristic_value_event{ - uint8_t type; - uint16_t characteristic_value_handle; - uint16_t characteristic_value_blob_length; - uint16_t characteristic_value_offset; - uint8_t * characteristic_value; -} le_characteristic_value_event_t; - - -void gatt_client_init(); -void gatt_client_register_handler(void (*le_callback)(le_event_t * event)); -void gatt_packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); - -// start/stop gatt client -void gatt_client_start(gatt_client_t *context, uint16_t handle); -void gatt_client_stop(gatt_client_t *context); - -// returns primary services -le_command_status_t gatt_client_discover_primary_services(gatt_client_t *context); -// { type (8), gatt_client_t *context, le_service * } - - -//TODO: define uuid type -le_command_status_t gatt_client_discover_primary_services_by_uuid16(gatt_client_t *context, uint16_t uuid16); -le_command_status_t gatt_client_discover_primary_services_by_uuid128(gatt_client_t *context, const uint8_t * uuid); - -// Returns included services. -// Information about service type (primary/secondary) can be retrieved either by sending an ATT find query or -// by comparing the service to the list of primary services obtained by calling le_central_get_services. -le_command_status_t gatt_client_find_included_services_for_service(gatt_client_t *context, le_service_t *service); -// { type (8), gatt_client_t *context, le_service * } - -// returns characteristics, no included services -le_command_status_t gatt_client_discover_characteristics_for_service(gatt_client_t *context, le_service_t *service); -// { type (8), gatt_client_t *context, service_handle, le_characteristic *} - -// gets all characteristics in handle range, and returns those that match the given UUID. -le_command_status_t gatt_client_discover_characteristics_for_handle_range_by_uuid16(gatt_client_t *context, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16); -// { type (8), gatt_client_t *context, service_handle, le_characteristic *} -le_command_status_t gatt_client_discover_characteristics_for_handle_range_by_uuid128(gatt_client_t *context, uint16_t start_handle, uint16_t end_handle, uint8_t * uuid); -// { type (8), gatt_client_t *context, service_handle, le_characteristic *} - -// more convenience -le_command_status_t gatt_client_discover_characteristics_for_service_by_uuid16 (gatt_client_t *context, le_service_t *service, uint16_t uuid16); -le_command_status_t gatt_client_discover_characteristics_for_service_by_uuid128(gatt_client_t *context, le_service_t *service, uint8_t * uuid128); - -// returns handle and uuid16 of a descriptor -le_command_status_t gatt_client_discover_characteristic_descriptors(gatt_client_t *context, le_characteristic_t *characteristic); - -// Reads value of characteristic using characteristic value handle -le_command_status_t gatt_client_read_value_of_characteristic(gatt_client_t *context, le_characteristic_t *characteristic); -le_command_status_t gatt_client_read_value_of_characteristic_using_value_handle(gatt_client_t *context, uint16_t characteristic_value_handle); - -// Reads long caharacteristic value. -le_command_status_t gatt_client_read_long_value_of_characteristic(gatt_client_t *context, le_characteristic_t *characteristic); -le_command_status_t gatt_client_read_long_value_of_characteristic_using_value_handle(gatt_client_t *context, uint16_t characteristic_value_handle); - - -le_command_status_t gatt_client_write_value_of_characteristic_without_response(gatt_client_t *context, uint16_t characteristic_value_handle, uint16_t length, uint8_t * data); -le_command_status_t gatt_client_write_value_of_characteristic(gatt_client_t *context, uint16_t characteristic_value_handle, uint16_t length, uint8_t * data); - -le_command_status_t gatt_client_write_long_value_of_characteristic(gatt_client_t *context, uint16_t characteristic_value_handle, uint16_t length, uint8_t * data); -le_command_status_t gatt_client_reliable_write_long_value_of_characteristic(gatt_client_t *context, uint16_t characteristic_value_handle, uint16_t length, uint8_t * data); - - -le_command_status_t gatt_client_read_characteristic_descriptor(gatt_client_t *context, le_characteristic_descriptor_t * descriptor); -le_command_status_t gatt_client_read_long_characteristic_descriptor(gatt_client_t *context, le_characteristic_descriptor_t * descriptor); - -le_command_status_t gatt_client_write_characteristic_descriptor(gatt_client_t *context, le_characteristic_descriptor_t * descriptor, uint16_t length, uint8_t * data); -le_command_status_t gatt_client_write_long_characteristic_descriptor(gatt_client_t *context, le_characteristic_descriptor_t * descriptor, uint16_t length, uint8_t * data); - -le_command_status_t gatt_client_write_client_characteristic_configuration(gatt_client_t *context, le_characteristic_t * characteristic, uint16_t configuration); - -// { read/write/subscribe/unsubscribe confirm/result} - -// { type, le_peripheral *, characteristic handle, int len, uint8_t data[]?} - -#if defined __cplusplus -} -#endif - -#endif diff --git a/test/ble_client/Makefile b/test/ble_client/Makefile index f107f6c36..0bd41eacd 100644 --- a/test/ble_client/Makefile +++ b/test/ble_client/Makefile @@ -9,11 +9,20 @@ CFLAGS = -g -Wall -I. -I${BTSTACK_ROOT}/example/libusb -I${BTSTACK_ROOT}/src -I LDFLAGS += -L$(CPPUTEST_HOME) -lCppUTest -lCppUTestExt COMMON = \ - ${BTSTACK_ROOT}/example/libusb/ad_parser.c \ - ${BTSTACK_ROOT}/src/sdp_util.c \ - ${BTSTACK_ROOT}/src/utils.c \ - ${BTSTACK_ROOT}/ble/att.c \ - ${BTSTACK_ROOT}/example/libusb/ble_client.c \ + ${BTSTACK_ROOT}/src/utils.c \ + ${BTSTACK_ROOT}/src/btstack_memory.c \ + ${BTSTACK_ROOT}/src/memory_pool.c \ + ${BTSTACK_ROOT}/src/linked_list.c \ + ${BTSTACK_ROOT}/src/sdp_util.c \ + ${BTSTACK_ROOT}/src/remote_device_db_memory.c \ + ${BTSTACK_ROOT}/src/run_loop.c \ + ${BTSTACK_ROOT}/src/run_loop_posix.c \ + ${BTSTACK_ROOT}/src/hci_cmds.c \ + ${BTSTACK_ROOT}/ble/att_dispatch.c \ + ${BTSTACK_ROOT}/ble/att.c \ + ${BTSTACK_ROOT}/ble/ad_parser.c \ + ${BTSTACK_ROOT}/ble/gatt_client.c \ + ${BTSTACK_ROOT}/example/libusb/ble_client.c \ COMMON_OBJ = $(COMMON:.c=.o) diff --git a/test/ble_client/advertising_data_parser.c b/test/ble_client/advertising_data_parser.c index 53f397221..0320f457d 100644 --- a/test/ble_client/advertising_data_parser.c +++ b/test/ble_client/advertising_data_parser.c @@ -11,11 +11,16 @@ #include #include -#include "ad_parser.h" - #include "CppUTest/TestHarness.h" #include "CppUTest/CommandLineTestRunner.h" +#include + +#include "btstack_memory.h" +#include "hci.h" +#include "ad_parser.h" +#include "l2cap.h" + static uint8_t ad_data[] = {0x02, 0x01, 0x05, 0x03, 0x02, 0xF0, 0xFF}; static uint8_t ad_uuid16[] = {0x02, 0x04, 0x78, 0x56, 0x34, 0x12,