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 ---