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