gatt_client.c (d9ced76fd2dcaba210c1d75fac12ddaae8083928) | gatt_client.c (58e8c9f5466ca2e36515d631514c9a587297aee3) |
---|---|
1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 42 unchanged lines hidden (view full) --- 51#include "bluetooth_psm.h" 52#include "btstack_debug.h" 53#include "btstack_event.h" 54#include "btstack_memory.h" 55#include "btstack_run_loop.h" 56#include "btstack_util.h" 57#include "hci.h" 58#include "hci_dump.h" | 1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 42 unchanged lines hidden (view full) --- 51#include "bluetooth_psm.h" 52#include "btstack_debug.h" 53#include "btstack_event.h" 54#include "btstack_memory.h" 55#include "btstack_run_loop.h" 56#include "btstack_util.h" 57#include "hci.h" 58#include "hci_dump.h" |
59#include "hci_event_builder.h" |
|
59#include "l2cap.h" 60#include "classic/sdp_client.h" 61#include "bluetooth_gatt.h" 62#include "bluetooth_sdp.h" 63#include "classic/sdp_util.h" 64 65#if defined(ENABLE_GATT_OVER_EATT) && !defined(ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE) 66#error "GATT Over EATT requires support for L2CAP Enhanced CoC. Please enable ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE" 67#endif 68 69// L2CAP Test Spec p35 defines a minimum of 100 ms, but PTS might indicate an error if we sent after 100 ms 70#define GATT_CLIENT_COLLISION_BACKOFF_MS 150 71 72static btstack_linked_list_t gatt_client_connections; 73static btstack_linked_list_t gatt_client_value_listeners; | 60#include "l2cap.h" 61#include "classic/sdp_client.h" 62#include "bluetooth_gatt.h" 63#include "bluetooth_sdp.h" 64#include "classic/sdp_util.h" 65 66#if defined(ENABLE_GATT_OVER_EATT) && !defined(ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE) 67#error "GATT Over EATT requires support for L2CAP Enhanced CoC. Please enable ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE" 68#endif 69 70// L2CAP Test Spec p35 defines a minimum of 100 ms, but PTS might indicate an error if we sent after 100 ms 71#define GATT_CLIENT_COLLISION_BACKOFF_MS 150 72 73static btstack_linked_list_t gatt_client_connections; 74static btstack_linked_list_t gatt_client_value_listeners; |
75static btstack_linked_list_t gatt_client_service_changed_handler; |
|
74static btstack_packet_callback_registration_t hci_event_callback_registration; 75static btstack_packet_callback_registration_t sm_event_callback_registration; 76static btstack_context_callback_registration_t gatt_client_deferred_event_emit; 77 78// GATT Client Configuration 79static bool gatt_client_mtu_exchange_enabled; 80static gap_security_level_t gatt_client_required_security_level; 81 --- 14 unchanged lines hidden (view full) --- 96 97#ifdef ENABLE_GATT_OVER_EATT 98static bool gatt_client_le_enhanced_handle_can_send_query(gatt_client_t * gatt_client); 99static void gatt_client_le_enhanced_retry(btstack_timer_source_t * ts); 100#endif 101 102void gatt_client_init(void){ 103 gatt_client_connections = NULL; | 76static btstack_packet_callback_registration_t hci_event_callback_registration; 77static btstack_packet_callback_registration_t sm_event_callback_registration; 78static btstack_context_callback_registration_t gatt_client_deferred_event_emit; 79 80// GATT Client Configuration 81static bool gatt_client_mtu_exchange_enabled; 82static gap_security_level_t gatt_client_required_security_level; 83 --- 14 unchanged lines hidden (view full) --- 98 99#ifdef ENABLE_GATT_OVER_EATT 100static bool gatt_client_le_enhanced_handle_can_send_query(gatt_client_t * gatt_client); 101static void gatt_client_le_enhanced_retry(btstack_timer_source_t * ts); 102#endif 103 104void gatt_client_init(void){ 105 gatt_client_connections = NULL; |
106 gatt_client_service_changed_handler = NULL; |
|
104 105 // default configuration 106 gatt_client_mtu_exchange_enabled = true; 107 gatt_client_required_security_level = LEVEL_0; 108 109 // register for HCI Events 110 hci_event_callback_registration.callback = &gatt_client_event_packet_handler; 111 hci_add_event_handler(&hci_event_callback_registration); --- 548 unchanged lines hidden (view full) --- 660 661static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){ 662 if (size < 2) return 0xffff; 663 uint8_t attr_length = packet[1]; 664 if ((2 + attr_length) > size) return 0xffff; 665 return little_endian_read_16(packet, size - attr_length); 666} 667 | 107 108 // default configuration 109 gatt_client_mtu_exchange_enabled = true; 110 gatt_client_required_security_level = LEVEL_0; 111 112 // register for HCI Events 113 hci_event_callback_registration.callback = &gatt_client_event_packet_handler; 114 hci_add_event_handler(&hci_event_callback_registration); --- 548 unchanged lines hidden (view full) --- 663 664static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){ 665 if (size < 2) return 0xffff; 666 uint8_t attr_length = packet[1]; 667 if ((2 + attr_length) > size) return 0xffff; 668 return little_endian_read_16(packet, size - attr_length); 669} 670 |
671static void gatt_client_service_emit_event(gatt_client_t * gatt_client, uint8_t * event, uint16_t size){ 672 btstack_linked_list_iterator_t it; 673 btstack_linked_list_iterator_init(&it, &gatt_client_service_changed_handler); 674 while (btstack_linked_list_iterator_has_next(&it)) { 675 btstack_packet_callback_registration_t *callback = (btstack_packet_callback_registration_t *) btstack_linked_list_iterator_next(&it); 676 (*callback->callback)(HCI_EVENT_PACKET, (uint16_t) gatt_client->con_handle, event, size); 677 } 678} 679 680static void 681gatt_client_service_emit_database_hash(gatt_client_t *gatt_client, const uint8_t *value, uint16_t value_len) { 682 if (value_len == 16){ 683 uint8_t event[21]; 684 hci_event_builder_context_t context; 685 hci_event_builder_init(&context, event, sizeof(event), HCI_EVENT_GATTSERVICE_META, GATTSERVICE_SUBEVENT_GATT_DATABASE_HASH); 686 hci_event_builder_add_con_handle(&context, gatt_client->con_handle); 687 hci_event_builder_add_bytes(&context, value, 16); 688 gatt_client_service_emit_event(gatt_client, event, hci_event_builder_get_length(&context)); 689 } 690} 691 692static void 693gatt_client_service_emit_service_changed(gatt_client_t *gatt_client, const uint8_t *value, uint16_t value_len) { 694 if (value_len == 4){ 695 uint8_t event[9]; 696 hci_event_builder_context_t context; 697 hci_event_builder_init(&context, event, sizeof(event), HCI_EVENT_GATTSERVICE_META, GATTSERVICE_SUBEVENT_GATT_SERVICE_CHANGED); 698 hci_event_builder_add_con_handle(&context, gatt_client->con_handle); 699 hci_event_builder_add_bytes(&context, value, 4); 700 gatt_client_service_emit_event(gatt_client, event, hci_event_builder_get_length(&context)); 701 } 702} 703 |
|
668static void gatt_client_service_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 669 hci_con_handle_t con_handle; 670 gatt_client_t *gatt_client; 671 gatt_client_service_t service; 672 gatt_client_characteristic_t characteristic; 673 switch (packet_type) { 674 case HCI_EVENT_PACKET: 675 switch (hci_event_packet_get_type(packet)) { --- 25 unchanged lines hidden (view full) --- 701 break; 702 } 703 break; 704 case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: 705 con_handle = gatt_event_characteristic_value_query_result_get_handle(packet); 706 gatt_client = gatt_client_get_context_for_handle(con_handle); 707 btstack_assert(gatt_client != NULL); 708 btstack_assert(gatt_client->gatt_service_state == GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W4_DONE); | 704static void gatt_client_service_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 705 hci_con_handle_t con_handle; 706 gatt_client_t *gatt_client; 707 gatt_client_service_t service; 708 gatt_client_characteristic_t characteristic; 709 switch (packet_type) { 710 case HCI_EVENT_PACKET: 711 switch (hci_event_packet_get_type(packet)) { --- 25 unchanged lines hidden (view full) --- 737 break; 738 } 739 break; 740 case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: 741 con_handle = gatt_event_characteristic_value_query_result_get_handle(packet); 742 gatt_client = gatt_client_get_context_for_handle(con_handle); 743 btstack_assert(gatt_client != NULL); 744 btstack_assert(gatt_client->gatt_service_state == GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W4_DONE); |
745 gatt_client_service_emit_database_hash(gatt_client, 746 gatt_event_characteristic_value_query_result_get_value(packet), 747 gatt_event_characteristic_value_query_result_get_value_length(packet)); |
|
709 break; 710 case GATT_EVENT_QUERY_COMPLETE: 711 con_handle = gatt_event_query_complete_get_handle(packet); 712 gatt_client = gatt_client_get_context_for_handle(con_handle); 713 btstack_assert(gatt_client != NULL); 714 switch (gatt_client->gatt_service_state) { 715 case GATT_CLIENT_SERVICE_DISCOVER_W4_DONE: 716 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W2_SEND; --- 396 unchanged lines hidden (view full) --- 1113 if (!gatt_client_accept_server_message(gatt_client)) return; 1114 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client->con_handle, value_handle, value, length); 1115 emit_event_to_registered_listeners(gatt_client->con_handle, value_handle, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length); 1116} 1117 1118// @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes 1119static void report_gatt_indication(gatt_client_t *gatt_client, uint16_t value_handle, uint8_t *value, int length) { 1120 if (!gatt_client_accept_server_message(gatt_client)) return; | 748 break; 749 case GATT_EVENT_QUERY_COMPLETE: 750 con_handle = gatt_event_query_complete_get_handle(packet); 751 gatt_client = gatt_client_get_context_for_handle(con_handle); 752 btstack_assert(gatt_client != NULL); 753 switch (gatt_client->gatt_service_state) { 754 case GATT_CLIENT_SERVICE_DISCOVER_W4_DONE: 755 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W2_SEND; --- 396 unchanged lines hidden (view full) --- 1152 if (!gatt_client_accept_server_message(gatt_client)) return; 1153 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client->con_handle, value_handle, value, length); 1154 emit_event_to_registered_listeners(gatt_client->con_handle, value_handle, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length); 1155} 1156 1157// @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes 1158static void report_gatt_indication(gatt_client_t *gatt_client, uint16_t value_handle, uint8_t *value, int length) { 1159 if (!gatt_client_accept_server_message(gatt_client)) return; |
1160 // Directly Handle GATT Service Changed and Database Hash indications 1161 if (value_handle == gatt_client->gatt_service_database_hash_value_handle){ 1162 gatt_client_service_emit_database_hash(gatt_client, value, length); 1163 } 1164 if (value_handle == gatt_client->gatt_service_changed_value_handle){ 1165 gatt_client_service_emit_service_changed(gatt_client, value, length); 1166 } |
|
1121 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, gatt_client->con_handle, value_handle, value, length); 1122 emit_event_to_registered_listeners(gatt_client->con_handle, value_handle, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length); 1123} 1124 1125// @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes 1126static void report_gatt_characteristic_value(gatt_client_t * gatt_client, uint16_t attribute_handle, uint8_t * value, uint16_t length){ 1127 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, gatt_client->con_handle, attribute_handle, value, length); 1128 emit_event_new(gatt_client->callback, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length); --- 1902 unchanged lines hidden (view full) --- 3031 } 3032 if (gatt_client->write_without_response_callback != NULL){ 3033 return GATT_CLIENT_IN_WRONG_STATE; 3034 } 3035 gatt_client->write_without_response_callback = callback; 3036 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle); 3037 return ERROR_CODE_SUCCESS; 3038} | 1167 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, gatt_client->con_handle, value_handle, value, length); 1168 emit_event_to_registered_listeners(gatt_client->con_handle, value_handle, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length); 1169} 1170 1171// @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes 1172static void report_gatt_characteristic_value(gatt_client_t * gatt_client, uint16_t attribute_handle, uint8_t * value, uint16_t length){ 1173 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, gatt_client->con_handle, attribute_handle, value, length); 1174 emit_event_new(gatt_client->callback, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length); --- 1902 unchanged lines hidden (view full) --- 3077 } 3078 if (gatt_client->write_without_response_callback != NULL){ 3079 return GATT_CLIENT_IN_WRONG_STATE; 3080 } 3081 gatt_client->write_without_response_callback = callback; 3082 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle); 3083 return ERROR_CODE_SUCCESS; 3084} |
3085void gatt_client_add_service_changed_handler(btstack_packet_callback_registration_t * callback) { 3086 btstack_linked_list_add_tail(&gatt_client_service_changed_handler, (btstack_linked_item_t*) callback); 3087} |
|
3039 | 3088 |
3089void gatt_client_remove_service_changed_handler(btstack_packet_callback_registration_t * callback){ 3090 btstack_linked_list_remove(&gatt_client_service_changed_handler, (btstack_linked_item_t*) callback); 3091} |
|
3040 3041#if defined(ENABLE_GATT_OVER_CLASSIC) || defined(ENABLE_GATT_OVER_EATT) 3042 3043#include "hci_event.h" 3044 3045static const hci_event_t gatt_client_connected = { 3046 GATT_EVENT_CONNECTED, 0, "1BH" 3047}; --- 628 unchanged lines hidden --- | 3092 3093#if defined(ENABLE_GATT_OVER_CLASSIC) || defined(ENABLE_GATT_OVER_EATT) 3094 3095#include "hci_event.h" 3096 3097static const hci_event_t gatt_client_connected = { 3098 GATT_EVENT_CONNECTED, 0, "1BH" 3099}; --- 628 unchanged lines hidden --- |