1 /* 2 * Copyright (C) 2023 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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 /** 39 * @title GATT Service Client 40 * 41 */ 42 43 #ifndef GATT_SERVICE_CLIENT_H 44 #define GATT_SERVICE_CLIENT_H 45 46 #include <stdint.h> 47 #include "btstack_defines.h" 48 #include "bluetooth.h" 49 #include "btstack_linked_list.h" 50 #include "ble/gatt_client.h" 51 52 #if defined __cplusplus 53 extern "C" { 54 #endif 55 56 /** 57 * @text A generic GATT Service Client 58 */ 59 60 #define GATT_SERVICE_CLIENT_INVALID_INDEX 0xff 61 62 typedef enum { 63 GATT_SERVICE_CLIENT_STATE_W2_QUERY_PRIMARY_SERVICE, 64 GATT_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT, 65 GATT_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTICS, 66 GATT_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT, 67 GATT_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTIC_DESCRIPTORS, 68 GATT_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_DESCRIPTORS_RESULT, 69 70 GATT_SERVICE_CLIENT_STATE_W2_REGISTER_NOTIFICATION, 71 GATT_SERVICE_CLIENT_STATE_W4_NOTIFICATION_REGISTERED, 72 GATT_SERVICE_CLIENT_STATE_CONNECTED 73 } gatt_service_client_state_t; 74 75 typedef struct { 76 uint16_t value_handle; 77 uint16_t client_configuration_handle; 78 uint16_t properties; 79 uint16_t end_handle; 80 } gatt_service_client_characteristic_t; 81 82 struct gatt_service_client; 83 84 typedef struct { 85 btstack_linked_item_t item; 86 87 struct gatt_service_client * client; 88 89 hci_con_handle_t con_handle; 90 uint16_t cid; 91 gatt_service_client_state_t state; 92 93 // service 94 uint16_t service_uuid16; 95 uint8_t service_index; 96 uint16_t service_instances_num; 97 uint16_t start_handle; 98 uint16_t end_handle; 99 100 uint8_t characteristic_index; 101 gatt_service_client_characteristic_t * characteristics; 102 103 gatt_client_service_notification_t notification_listener; 104 } gatt_service_client_connection_t; 105 106 typedef struct gatt_service_client { 107 btstack_linked_item_t item; 108 btstack_linked_list_t connections; 109 uint16_t service_id; 110 uint16_t cid_counter; 111 112 // characteristics 113 uint8_t characteristics_desc16_num; // uuid16s_num 114 const uint16_t * characteristics_desc16; // uuid16s 115 116 btstack_packet_handler_t packet_handler; 117 } gatt_service_client_t; 118 119 /* API_START */ 120 121 122 /** 123 * @brief Initialize GATT Service Client infrastructure 124 */ 125 void gatt_service_client_init(void); 126 127 /** 128 * @brief Register new GATT Service Client with list of Characteristic UUID16s 129 * @param client 130 * @param characteristic_uuid16s 131 * @param characteristic_uuid16s_num 132 * @param trampoline_packet_handler packet handler that calls gatt_service_client_trampoline_packet_handler with client 133 */ 134 void gatt_service_client_register_client(gatt_service_client_t *client, btstack_packet_handler_t packet_handler, 135 const uint16_t *characteristic_uuid16s, uint16_t characteristic_uuid16s_num); 136 137 /** 138 * @brief Get Characteristic UUID16 for given Characteristic index 139 * 140 * @param client 141 * @param characteristic_index 142 * @return uuid16 or 0 if index out of range 143 */ 144 uint16_t gatt_service_client_characteristic_uuid16_for_index(const gatt_service_client_t * client, uint8_t characteristic_index); 145 146 /** 147 * @bbreif Unregister GATT Service Client 148 * @param client 149 */ 150 void gatt_service_client_unregister_client(gatt_service_client_t * client); 151 152 /** 153 * @brief Connect to the n-th instance of Primary GATT Service with UUID16 154 * 155 * @param con_handle 156 * @param client 157 * @param connection 158 * @param service_uuid16 159 * @param service_index 160 * @param characteristics 161 * @param characteristics_num 162 * @return 163 */ 164 uint8_t 165 gatt_service_client_connect_primary_service_with_uuid16(hci_con_handle_t con_handle, gatt_service_client_t *client, 166 gatt_service_client_connection_t *connection, 167 uint16_t service_uuid16, uint8_t service_index, 168 gatt_service_client_characteristic_t *characteristics, 169 uint8_t characteristics_num); 170 171 /** 172 * @brief Connect to the Secondary GATT Service with given handle range 173 * 174 * UUID16 and Service Index are stored for GATT Service Client user only 175 * 176 * @param con_handle 177 * @param client 178 * @param connection 179 * @param service_uuid16 180 * @param service_start_handle 181 * @param service_end_handle 182 * @param service_index 183 * @param characteristics 184 * @param characteristics_num 185 * @return 186 */ 187 uint8_t 188 gatt_service_client_connect_secondary_service_with_uuid16(hci_con_handle_t con_handle, gatt_service_client_t *client, 189 gatt_service_client_connection_t *connection, 190 uint16_t service_uuid16, uint8_t service_index, 191 uint16_t service_start_handle, uint16_t service_end_handle, 192 gatt_service_client_characteristic_t *characteristics, 193 uint8_t characteristics_num); 194 195 /** 196 * @brief Disconnect service client 197 * @param client 198 * @param connection 199 * @return 200 */ 201 uint8_t gatt_service_client_disconnect(gatt_service_client_connection_t *connection); 202 203 /** 204 * @brief Check if Characteristic is available and can be queried 205 * @param client 206 * @param connection 207 * @param characteristic_index 208 * @return ERROR_CODE_SUCCESS if ready, ERROR_CODE_COMMAND_DISALLOWED or ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE otherwise 209 */ 210 uint8_t 211 gatt_service_client_can_query_characteristic(const gatt_service_client_connection_t *connection, 212 uint8_t characteristic_index); 213 214 /** 215 * @brief Get Characteristic Value Handle for given Characteristic index 216 * * 217 * @param connection 218 * @param characteristic_index 219 * @return 220 */ 221 uint16_t gatt_service_client_characteristic_value_handle_for_index(const gatt_service_client_connection_t *connection, 222 uint8_t characteristic_index); 223 224 /** 225 * @brief Get Characteristic index Handle for given Characteristic Value Handle 226 * * 227 * @param connection 228 * @param value_handle 229 * @return index of characteristic in initial list or GATT_SERVICE_CLIENT_INVALID_INDEX 230 */ 231 uint8_t gatt_service_client_characteristic_index_for_value_handle(const gatt_service_client_connection_t *connection, 232 uint16_t value_handle); 233 234 /** 235 * @brief Get connection id 236 * @param client 237 * @param connection 238 * @returns connection_id 239 */ 240 uint16_t gatt_service_client_get_connection_id(const gatt_service_client_connection_t * connection); 241 242 /** 243 * @brief Get connection handle 244 * @param client 245 * @param connection 246 * @returns con_handle 247 */ 248 hci_con_handle_t gatt_service_client_get_con_handle(const gatt_service_client_connection_t * connection); 249 250 /** 251 * @brief Get service index provided in connect call 252 * @param client 253 * @param connection 254 * @returns connection_id 255 */ 256 uint8_t gatt_service_client_get_service_index(const gatt_service_client_connection_t * connection); 257 258 /** 259 * @brief Get remote MTU 260 * @param client 261 * @param connection 262 * @returns MTU or 0 in case of error 263 */ 264 uint16_t gatt_service_client_get_mtu(const gatt_service_client_connection_t *connection); 265 266 267 /** 268 * @brief Dump characteristic value handles 269 * @param client 270 * @param connection 271 * @param characteristic_names 272 */ 273 void gatt_service_client_dump_characteristic_value_handles(const gatt_service_client_connection_t *connection, 274 const char **characteristic_names); 275 276 /** 277 * @brief De-Init 278 * @param client 279 */ 280 void gatt_service_client_deinit(void); 281 282 283 /** 284 * @brief Map ATT Error Code to (extended) Error Codes 285 * @param att_error_code 286 * @return 287 */ 288 uint8_t gatt_service_client_att_status_to_error_code(uint8_t att_error_code); 289 290 291 /* API_END */ 292 293 #if defined __cplusplus 294 } 295 #endif 296 297 #endif 298